build 190303. loose shunting ai mode, minor ai logic tweaks, doorstep state readout for python scripts

This commit is contained in:
tmj-fstate
2019-03-04 15:26:41 +01:00
parent e356172a81
commit 400b067628
7 changed files with 324 additions and 267 deletions

View File

@@ -351,7 +351,7 @@ std::string TSpeedPos::TableText() const
bool TSpeedPos::IsProperSemaphor(TOrders order)
{ // sprawdzenie czy semafor jest zgodny z trybem jazdy
if (order < 0x40) // Wait_for_orders, Prepare_engine, Change_direction, Connect, Disconnect, Shunt
if (order < Obey_train) // Wait_for_orders, Prepare_engine, Change_direction, Connect, Disconnect, Shunt
{
if (iFlags & (spSemaphor | spShuntSemaphor))
return true;
@@ -382,7 +382,7 @@ bool TSpeedPos::Set(basic_event *event, double dist, double length, TOrders orde
// zależnie od trybu sprawdzenie czy jest tutaj gdzieś semafor lub tarcza manewrowa
// jeśli wskazuje stop wtedy wystawiamy true jako koniec sprawdzania
// WriteLog("EventSet: Vel=" + AnsiString(fVelNext) + " iFlags=" + AnsiString(iFlags) + " order="+AnsiString(order));
if (order < 0x40) // Wait_for_orders, Prepare_engine, Change_direction, Connect, Disconnect, Shunt
if (order < Obey_train) // Wait_for_orders, Prepare_engine, Change_direction, Connect, Disconnect, Shunt
{
if (iFlags & (spSemaphor | spShuntSemaphor) && fVelNext == 0.0)
return true;
@@ -541,7 +541,7 @@ void TController::TableTraceRoute(double fDistance, TDynamicObject *pVehicle)
return;
}
else {
if( ( OrderCurrentGet() < 0x40 )
if( ( OrderCurrentGet() < Obey_train )
&& ( sSpeedTable[SemNextStopIndex].iFlags & ( spSemaphor | spShuntSemaphor | spOutsideStation ) ) ) {
return;
}
@@ -860,7 +860,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// jeśli przystanek, trzeba obsłużyć wg rozkładu
iDrivigFlags |= moveStopPointFound;
// stop points are irrelevant when not in one of the basic modes
if( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) == 0 ) { continue; }
if( ( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) == 0 ) { continue; }
// first 19 chars of the command is expected to be "PassengerStopPoint:" so we skip them
if ( ToLower(sSpeedTable[i].evEvent->input_text()).compare( 19, sizeof(asNextStop), ToLower(asNextStop)) != 0 )
{ // jeśli nazwa nie jest zgodna
@@ -1012,7 +1012,7 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
}
}
if (OrderCurrentGet() & Shunt) {
if (OrderCurrentGet() & ( Shunt | Loose_shunt )) {
OrderNext(Obey_train); // uruchomić jazdę pociągową
CheckVehicles(); // zmienić światła
}
@@ -1688,7 +1688,9 @@ std::string TController::Order2Str(TOrders Order) const {
case Connect: return "Connect";
case Disconnect: return "Disconnect";
case Shunt: return "Shunt";
case Loose_shunt: return "Loose_shunt";
case Obey_train: return "Obey_train";
case Bank: return "Bank";
case Jump_to_first_order: return "Jump_to_first_order";
default: return "Undefined";
}
@@ -1766,14 +1768,13 @@ void TController::Activation()
// ewentualna zmiana kabiny użytkownikowi
Global.changeDynObj = pVehicle; // uruchomienie protezy
}
ControllingSet(); // utworzenie połączenia do sterowanego pojazdu (może się zmienić) -
// silnikowy dla EZT
ControllingSet(); // utworzenie połączenia do sterowanego pojazdu (może się zmienić) - silnikowy dla EZT
}
if( mvControlling->EngineType == TEngineType::DieselEngine ) {
// dla 2Ls150 - przed ustawieniem kierunku - można zmienić tryb pracy
if( mvControlling->ShuntModeAllow ) {
mvControlling->CurrentSwitch(
( ( OrderList[ OrderPos ] & Shunt ) == Shunt )
( ( OrderCurrentGet() & ( Shunt | Loose_shunt ) ) != 0 )
|| ( fMass > 224000.0 ) ); // do tego na wzniesieniu może nie dać rady na liniowym
}
}
@@ -1908,7 +1909,7 @@ void TController::AutoRewident()
fBrake_a1[i+1] = 0;
}
if( OrderCurrentGet() & Shunt ) {
if( OrderCurrentGet() & ( Shunt | Loose_shunt ) ) {
// for uniform behaviour and compatibility with older scenarios set default acceleration table values for shunting
fAccThreshold = (
mvOccupied->TrainType == dt_EZT ? -0.55 :
@@ -1921,7 +1922,7 @@ void TController::AutoRewident()
}
}
if( OrderCurrentGet() & Obey_train ) {
if( OrderCurrentGet() & ( Obey_train | Bank ) ) {
// 4. Przeliczanie siły hamowania
double const velstep = ( mvOccupied->Vmax*0.5 ) / BrakeAccTableSize;
d = pVehicles[0]; // pojazd na czele składu
@@ -2022,9 +2023,10 @@ double TController::ESMVelocity(bool Main)
int TController::CheckDirection() {
int d = mvOccupied->DirAbsolute; // który sprzęg jest z przodu
if( !d ) // jeśli nie ma ustalonego kierunku
d = mvOccupied->CabNo; // to jedziemy wg aktualnej kabiny
iDirection = d; // ustalenie kierunku jazdy (powinno zrobić PrepareEngine?)
if( !d ) {
// jeśli nie ma ustalonego kierunku to jedziemy wg aktualnej kabiny
d = mvOccupied->CabNo;
}
return d;
}
@@ -2076,8 +2078,8 @@ bool TController::CheckVehicles(TOrders user)
{
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
if( ( p != pVehicle )
&& ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 )
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control | coupling::permanent ) ) == 0 ) ) {
&& ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 )
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
p->MoverParameters->BatterySwitch( true );
}
@@ -2112,7 +2114,7 @@ bool TController::CheckVehicles(TOrders user)
frontlights,
rearlights );
}
else if (OrderCurrentGet() & (Shunt | Connect))
else if (OrderCurrentGet() & (Shunt | Loose_shunt | Connect))
{
// HACK: the 'front' and 'rear' of the consist is determined by current consist direction
// since direction shouldn't affect Tb1 light configuration, we 'counter' this behaviour by virtually swapping end vehicles
@@ -2144,7 +2146,7 @@ bool TController::CheckVehicles(TOrders user)
}
}
if( OrderCurrentGet() & ( Obey_train | Shunt ) ) {
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) {
// nastawianie hamulca do jazdy pociągowej
AutoRewident();
// enable door locks
@@ -2232,6 +2234,15 @@ void TController::DirectionInitial()
CheckVehicles(); // sprawdzenie świateł oraz skrajnych pojazdów do skanowania
};
void TController::DirectionChange() {
auto const initialstate { iDirection };
iDirection = CheckDirection();
if( iDirection != initialstate ) {
CheckVehicles( Change_direction );
}
}
int TController::OrderDirectionChange(int newdir, TMoverParameters *Vehicle)
{ // zmiana kierunku jazdy, niezależnie od kabiny
int testd = newdir;
@@ -2280,9 +2291,7 @@ void TController::SetVelocity(double NewVel, double NewVelNext, TStopReason r)
{
eStopReason = stopNone; // podana prędkość, to nie ma powodów do stania
// to całe poniżej to warunki zatrąbienia przed ruszeniem
if (OrderList[OrderPos] ?
OrderList[OrderPos] & (Obey_train | Shunt | Connect | Prepare_engine) :
true) // jeśli jedzie w dowolnym trybie
if( (OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank | Connect | Prepare_engine ) ) != 0 ) // jeśli jedzie w dowolnym trybie
if ((mvOccupied->Vel < 1.0)) // jesli stoi (na razie, bo chyba powinien też, gdy hamuje przed semaforem)
if (iDrivigFlags & moveStartHorn) // jezeli trąbienie włączone
if (!(iDrivigFlags & (moveStartHornDone | moveConnect)))
@@ -2311,7 +2320,7 @@ double TController::BrakeAccFactor() const
void TController::SetDriverPsyche()
{
if ((Psyche == Aggressive) && (OrderList[OrderPos] == Obey_train))
if ((Psyche == Aggressive) && (OrderCurrentGet() == Obey_train))
{
ReactionTime = HardReactionTime; // w zaleznosci od charakteru maszynisty
if (mvOccupied->CategoryFlag & 2)
@@ -2634,6 +2643,11 @@ bool TController::IncBrake()
// enforce use of train brake for DMUs
standalone = false;
}
else if( ( ( OrderCurrentGet() & ( Loose_shunt ) ) != 0 )
&& ( mvOccupied->Vel - VelDesired < fVelPlus + fVelMinus ) ) {
// try to reduce train brake use in loose shunting mode
standalone = true;
}
else {
/*
standalone =
@@ -3486,7 +3500,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
{
if (NewLocation)
vCommandLocation = *NewLocation;
if ((NewValue1 != 0.0) && (OrderList[OrderPos] != Obey_train))
if ((NewValue1 != 0.0) && (OrderCurrentGet() != Obey_train))
{ // o ile jazda
if( iEngineActive == 0 ) {
// trzeba odpalić silnik najpierw, światła ustawi
@@ -3565,7 +3579,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
if (NewCommand == "Change_direction")
{
TOrders o = OrderList[OrderPos]; // co robił przed zmianą kierunku
TOrders o = OrderCurrentGet(); // co robił przed zmianą kierunku
if (!iEngineActive)
OrderNext(Prepare_engine); // trzeba odpalić silnik najpierw
if (NewValue1 == 0.0)
@@ -3592,18 +3606,29 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
return true;
}
if (NewCommand == "Obey_train")
{
if (!iEngineActive)
OrderNext(Prepare_engine); // trzeba odpalić silnik najpierw
OrderNext(Obey_train);
if (NewCommand == "Obey_train") {
if( false == iEngineActive ) {
OrderNext( Prepare_engine ); // trzeba odpalić silnik najpierw
}
OrderNext( Obey_train );
// if (NewValue1>0) TrainNumber=floor(NewValue1); //i co potem ???
OrderCheck(); // jeśli jazda pociągowa teraz, to wykonać niezbędne operacje
return true;
}
if (NewCommand == "Shunt")
if (NewCommand == "Bank") {
if( false == iEngineActive ) {
OrderNext( Prepare_engine ); // trzeba odpalić silnik najpierw
}
OrderNext( Bank );
// if (NewValue1>0) TrainNumber=floor(NewValue1); //i co potem ???
OrderCheck(); // jeśli jazda pociągowa teraz, to wykonać niezbędne operacje
return true;
}
if( ( NewCommand == "Shunt" ) || ( NewCommand == "Loose_shunt" ) )
{ // NewValue1 - ilość wagonów (-1=wszystkie); NewValue2: 0=odczep, 1..63=dołącz, -1=bez zmian
//-3,-y - podłączyć do całego stojącego składu (sprzęgiem y>=1), zmienić kierunek i czekać w
// trybie pociągowym
@@ -3613,8 +3638,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
//-1, y - podłączyć do całego stojącego składu (sprzęgiem y>=1) i jechać dalej
//-1, 0 - tryb manewrowy bez zmian (odczepianie z pozostawieniem wagonów nie ma sensu)
// 0, 0 - odczepienie lokomotywy
// 1,-y - podłączyć się do składu (sprzęgiem y>=1), a następnie odczepić i zabrać (x)
// wagonów
// 1,-y - podłączyć się do składu (sprzęgiem y>=1), a następnie odczepić i zabrać (x) wagonów
// 1, 0 - odczepienie lokomotywy z jednym wagonem
iDrivigFlags &= ~moveStopHere; // podjeżanie do semaforów zezwolone
if (!iEngineActive)
@@ -3628,9 +3652,15 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
iDirectionOrder = -iDirection; // zmiana na ciągnięcie
OrderPush(Change_direction); // najpierw zmień kierunek, bo odczepiamy z tyłu
OrderPush(Disconnect); // a odczep już po zmianie kierunku
if( ( NewValue2 > 0.0 )
&& ( NewCommand == "Loose_shunt" ) ) {
// after decoupling continue pushing in the original direction
// NOTE: for backward compatibility this option isn't supported for basic shunting mode
iDirectionOrder = iDirection; // back to pushing
OrderPush( Change_direction );
}
}
else if (NewValue2 < 0.0) // jeśli wszystkie, a sprzęg ujemny, to tylko zmiana kierunku
// po podczepieniu
else if (NewValue2 < 0.0) // jeśli wszystkie, a sprzęg ujemny, to tylko zmiana kierunku po podczepieniu
{ // np. Shunt -1 -3
iDirectionOrder = -iDirection; // jak się podczepi, to jazda w przeciwną stronę
OrderNext(Change_direction);
@@ -3662,9 +3692,9 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
iDrivigFlags |= moveStopHere; // nie podjeżdżać do semafora, jeśli droga nie jest wolna
// (nie dotyczy Connect)
if (NewValue1 < -2.5) // jeśli
OrderNext(Obey_train); // to potem jazda pociągowa
OrderNext(( NewCommand == "Shunt" ? Obey_train : Bank )); // to potem jazda pociągowa
else
OrderNext(Shunt); // to potem manewruj dalej
OrderNext(( NewCommand == "Shunt" ? Shunt : Loose_shunt )); // to potem manewruj dalej
CheckVehicles(); // sprawdzić światła
// if ((iVehicleCount>=0)&&(NewValue1<0)) WriteLog("Skasowano ilosć wagonów w Shunt!");
if (NewValue1 != iVehicleCount)
@@ -3815,12 +3845,18 @@ TController::UpdateSituation(double dt) {
LastReactionTime += dt;
LastUpdatedTime += dt;
if( ( mvOccupied->Vel < 0.05 )
&& ( ( OrderCurrentGet() & ( Obey_train | Shunt ) ) != 0 ) ) {
&& ( ( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) != 0 ) ) {
IdleTime += dt;
}
else {
IdleTime = 0.0;
}
// HACK: activate route scanning if an idling vehicle is activated by a human user
if( ( OrderCurrentGet() == Wait_for_orders )
&& ( false == AIControllFlag )
&& ( true == mvControlling->Battery ) ) {
OrderNext( Prepare_engine );
}
// log vehicle data
if( ( WriteLogFlag )
@@ -4037,7 +4073,7 @@ TController::UpdateSituation(double dt) {
mvControlling->PantFront( true );
}
}
if( mvOccupied->Vel > 10 ) {
if( mvOccupied->Vel > 5 ) {
// opuszczenie przedniego po rozpędzeniu się o ile jest więcej niż jeden
if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) {
if( iDirection >= 0 ) // jak jedzie w kierunku sprzęgu 0
@@ -4145,20 +4181,22 @@ TController::UpdateSituation(double dt) {
// następnie w drugą stronę, z drogi hamowania i chwilowej prędkości powinno być wyznaczane zalecane ciśnienie
// przybliżona droga hamowania
fBrakeDist = fDriverBraking * mvOccupied->Vel * ( 40.0 + mvOccupied->Vel );
// NOTE: we're ensuring some minimal braking distance to reduce ai flipping states between starting and braking
auto const velceil { std::max( 2.0, std::ceil( mvOccupied->Vel ) ) };
fBrakeDist = fDriverBraking * velceil * ( 40.0 + velceil );
if( fMass > 1000000.0 ) {
// korekta dla ciężkich, bo przeżynają - da to coś?
fBrakeDist *= 2.0;
}
if( ( -fAccThreshold > 0.05 )
&& ( mvOccupied->CategoryFlag == 1 ) ) {
fBrakeDist = mvOccupied->Vel * mvOccupied->Vel / 25.92 / -fAccThreshold;
fBrakeDist = velceil * velceil / 25.92 / -fAccThreshold;
}
if( mvOccupied->BrakeDelayFlag == bdelay_G ) {
// dla nastawienia G koniecznie należy wydłużyć drogę na czas reakcji
fBrakeDist += 2 * mvOccupied->Vel;
fBrakeDist += 2 * velceil;
}
if( ( mvOccupied->Vel > 0.05 )
if( ( mvOccupied->Vel > 15.0 )
&& ( mvControlling->EngineType == TEngineType::ElectricInductionMotor )
&& ( ( mvControlling->TrainType & dt_EZT ) != 0 ) ) {
// HACK: make the induction motor powered EMUs start braking slightly earlier
@@ -4213,7 +4251,12 @@ TController::UpdateSituation(double dt) {
// towards coupler 1
routescandirection = end::rear;
}
/*
if( pVehicle->MoverParameters->ActiveCab < 0 ) {
// flip the scan direction in the rear cab
routescandirection ^= routescandirection;
}
*/
Obstacle = neighbour_data();
auto const lookup { frontvehicle->find_vehicle( routescandirection, routescanrange ) };
@@ -4223,14 +4266,11 @@ TController::UpdateSituation(double dt) {
Obstacle.vehicle_end = std::get<int>( lookup );
Obstacle.distance = std::get<double>( lookup );
if( Obstacle.distance < ( mvOccupied->CategoryFlag == 2 ? 25 : 100 ) ) {
if( Obstacle.distance < ( mvOccupied->CategoryFlag == 2 ? 50 : 100 ) ) {
// at short distances (re)calculate range between couplers directly
Obstacle.distance = TMoverParameters::CouplerDist( frontvehicle->MoverParameters, Obstacle.vehicle->MoverParameters );
}
}
else {
Obstacle.distance = 10000; // legacy value. TBD, TODO: use standard -1 instead?
}
}
// tu bedzie logika sterowania
if (AIControllFlag) {
@@ -4280,7 +4320,7 @@ TController::UpdateSituation(double dt) {
}
}
switch (OrderList[OrderPos])
switch (OrderCurrentGet())
{ // ustalenie prędkości przy doczepianiu i odczepianiu, dystansów w pozostałych przypadkach
case Connect: {
// podłączanie do składu
@@ -4351,6 +4391,13 @@ TController::UpdateSituation(double dt) {
fVelMinus = std::min( 0.1 * fShuntVelocity, 3.0 );
break;
}
case Loose_shunt: {
fMinProximityDist = -1.0;
fMaxProximityDist = 0.0; //[m] dojechać maksymalnie
fVelPlus = 2.0; // dopuszczalne przekroczenie prędkości na ograniczeniu bez hamowania
fVelMinus = 0.5; // margines prędkości powodujący załączenie napędu
break;
}
case Obey_train: {
// na jaka odleglosc i z jaka predkoscia ma podjechac do przeszkody
if( mvOccupied->CategoryFlag & 1 ) {
@@ -4400,6 +4447,10 @@ TController::UpdateSituation(double dt) {
}
break;
}
case Bank: {
// TODO: implement
break;
}
default: {
fMinProximityDist = 5.0;
fMaxProximityDist = 10.0; //[m]
@@ -4408,7 +4459,7 @@ TController::UpdateSituation(double dt) {
}
} // switch OrderList[OrderPos]
switch (OrderList[OrderPos])
switch (OrderCurrentGet())
{ // co robi maszynista
case Prepare_engine: // odpala silnik
// if (AIControllFlag)
@@ -4442,13 +4493,16 @@ TController::UpdateSituation(double dt) {
break;
case Wait_for_orders: // jeśli czeka, też ma skanować, żeby odpalić się od semafora
case Shunt:
case Loose_shunt:
case Obey_train:
case Bank:
case Connect:
case Disconnect:
case Change_direction: // tryby wymagające jazdy
case Change_direction | Shunt: // zmiana kierunku podczas manewrów
case Change_direction | Loose_shunt:
case Change_direction | Connect: // zmiana kierunku podczas podłączania
if (OrderList[OrderPos] != Obey_train) // spokojne manewry
if ((OrderCurrentGet() & ( Obey_train | Bank )) == 0) // spokojne manewry
{
VelSignal = min_speed( VelSignal, 40.0 ); // jeśli manewry, to ograniczamy prędkość
@@ -4470,14 +4524,14 @@ TController::UpdateSituation(double dt) {
else
SetDriverPsyche(); // Ra: było w PrepareEngine(), potrzebne tu?
if (OrderList[OrderPos] & (Shunt | Obey_train | Connect)) {
if (OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank | Connect )) {
// odjechać sam może tylko jeśli jest w trybie jazdy
// automatyczne ruszanie po odstaniu albo spod SBL
if( ( VelSignal == 0.0 )
&& ( WaitingTime > 0.0 )
&& ( mvOccupied->RunningTrack.Velmax != 0.0 ) ) {
// jeśli stoi, a upłynął czas oczekiwania i tor ma niezerową prędkość
if( ( OrderList[ OrderPos ] & ( Obey_train | Shunt ) )
if( ( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) )
&& ( iDrivigFlags & moveStopHere ) ) {
// zakaz ruszania z miejsca bez otrzymania wolnej drogi
WaitingTime = -WaitingExpireTime;
@@ -4520,14 +4574,14 @@ TController::UpdateSituation(double dt) {
} // koniec samoistnego odjeżdżania
if( ( true == AIControllFlag)
&& ( true == TestFlag( OrderList[ OrderPos ], Change_direction ) ) ) {
&& ( true == TestFlag( OrderCurrentGet(), Change_direction ) ) ) {
// sprobuj zmienic kierunek (może być zmieszane z jeszcze jakąś komendą)
if( mvOccupied->Vel < 0.1 ) {
// jeśli się zatrzymał, to zmieniamy kierunek jazdy, a nawet kabinę/człon
Activation(); // ustawienie zadanego wcześniej kierunku i ewentualne przemieszczenie AI
PrepareEngine();
JumpToNextOrder(); // następnie robimy, co jest do zrobienia (Shunt albo Obey_train)
if( OrderList[ OrderPos ] & ( Shunt | Connect ) ) {
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Connect ) ) {
// jeśli dalej mamy manewry
if( false == TestFlag( iDrivigFlags, moveStopHere ) ) {
// o ile nie ma stać w miejscu,
@@ -4541,7 +4595,7 @@ TController::UpdateSituation(double dt) {
if( ( true == AIControllFlag )
&& ( iEngineActive == 0 )
&& ( OrderList[ OrderPos ] & ( Change_direction | Connect | Disconnect | Shunt | Obey_train ) ) ) {
&& ( OrderCurrentGet() & ( Change_direction | Connect | Disconnect | Shunt | Loose_shunt | Obey_train | Bank ) ) ) {
// jeśli coś ma robić to niech odpala do skutku
PrepareEngine();
}
@@ -4580,21 +4634,18 @@ TController::UpdateSituation(double dt) {
if (iDrivigFlags & moveStopCloser)
VelSignal = -1.0; // ma czekać na sygnał z sygnalizatora!
case TCommandType::cm_SetVelocity: // od wersji 357 semafor nie budzi wyłączonej lokomotywy
if (!(OrderList[OrderPos] &
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders
if (fabs(VelSignal) >=
1.0) // 0.1 nie wysyła się do samochodow, bo potem nie ruszą
if( ( OrderCurrentGet() & ~( Shunt | Loose_shunt | Obey_train | Bank ) ) == 0 ) // jedzie w dowolnym trybie albo Wait_for_orders
if (fabs(VelSignal) >= 1.0) // 0.1 nie wysyła się do samochodow, bo potem nie ruszą
PutCommand("SetVelocity", VelSignal, VelNext, nullptr); // komenda robi dodatkowe operacje
break;
case TCommandType::cm_ShuntVelocity: // od wersji 357 Tm nie budzi wyłączonej lokomotywy
if (!(OrderList[OrderPos] &
~(Obey_train | Shunt))) // jedzie w dowolnym trybie albo Wait_for_orders
if( ( OrderCurrentGet() & ~( Shunt | Loose_shunt | Obey_train | Bank ) ) == 0 ) // jedzie w dowolnym trybie albo Wait_for_orders
PutCommand("ShuntVelocity", VelSignal, VelNext, nullptr);
else if (iCoupler) // jeśli jedzie w celu połączenia
SetVelocity(VelSignal, VelNext);
break;
case TCommandType::cm_Command: // komenda z komórki
if( !( OrderList[ OrderPos ] & ~( Obey_train | Shunt ) ) ) {
if( ( OrderCurrentGet() & ~( Shunt | Loose_shunt | Obey_train | Bank ) ) == 0 ) {
// jedzie w dowolnym trybie albo Wait_for_orders
if( mvOccupied->Vel < 0.1 ) {
// dopiero jak stanie
@@ -4611,138 +4662,152 @@ TController::UpdateSituation(double dt) {
}
// disconnect mode potentially overrides scan results
// TBD: when in this mode skip scanning altogether?
if( ( OrderCurrentGet() & Disconnect ) != 0 ) {
if( ( true == AIControllFlag )
&& ( ( OrderCurrentGet() & Disconnect ) != 0 ) ) {
if (AIControllFlag) {
if (iVehicleCount >= 0) {
// jeśli była podana ilość wagonów
if (iDrivigFlags & movePress) {
// jeśli dociskanie w celu odczepienia
// 3. faza odczepiania.
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
if ((mvControlling->MainCtrlPos > 0) ||
(mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)) // jeśli jazda
{
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
TDynamicObject *p =
pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
int n = iVehicleCount; // ile wagonów ma zostać
do
{ // szukanie pojazdu do odczepienia
d = p->DirectionGet() > 0 ?
0 :
1; // numer sprzęgu od strony czoła składu
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
// //jeśli sprzęg typu wózek (za mało)
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
// (ustalić po czym poznać taki tor)
++n; // to liczymy człony jako jeden
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
if (n)
{ // jeśli jeszcze nie koniec
p = p->Prev(); // kolejny w stronę czoła składu (licząc od
// tyłu), bo dociskamy
if (!p)
iVehicleCount = -2,
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
} else if ( p->Dettach(d) == coupling::faux ) {
// tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2;
} // a jak nie, to dociskać dalej
}
if (iVehicleCount >= 0) // zmieni się po odczepieniu
if (!mvOccupied->DecLocalBrakeLevel(1))
{ // dociśnij sklad
WriteLog( mvOccupied->Name + " dociskanie..." );
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
IncSpeed(); // dla (Ready)==false nie ruszy
if (iVehicleCount >= 0) {
// jeśli była podana ilość wagonów
if (iDrivigFlags & movePress) {
// jeśli dociskanie w celu odczepienia
// 3. faza odczepiania.
SetVelocity(2, 0); // jazda w ustawionym kierunku z prędkością 2
if( ( mvControlling->MainCtrlPos > 0 )
|| ( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) {
// jeśli jazda
WriteLog(mvOccupied->Name + " odczepianie w kierunku " + std::to_string(mvOccupied->DirAbsolute));
TDynamicObject *p = pVehicle; // pojazd do odczepienia, w (pVehicle) siedzi AI
int d; // numer sprzęgu, który sprawdzamy albo odczepiamy
int n = iVehicleCount; // ile wagonów ma zostać
do
{ // szukanie pojazdu do odczepienia
d = p->DirectionGet() > 0 ?
end::front :
end::rear; // numer sprzęgu od strony czoła składu
// if (p->MoverParameters->Couplers[d].CouplerType==Articulated)
// //jeśli sprzęg typu wózek (za mało)
if (p->MoverParameters->Couplers[d].CouplingFlag & ctrain_depot) // jeżeli sprzęg zablokowany
// if (p->GetTrack()->) //a nie stoi na torze warsztatowym
// (ustalić po czym poznać taki tor)
++n; // to liczymy człony jako jeden
p->MoverParameters->BrakeReleaser(1); // wyluzuj pojazd, aby dało się dopychać
p->MoverParameters->BrakeLevelSet(0); // hamulec na zero, aby nie hamował
if (n)
{ // jeśli jeszcze nie koniec
p = p->Prev(); // kolejny w stronę czoła składu (licząc od tyłu), bo dociskamy
if (!p)
iVehicleCount = -2,
n = 0; // nie ma co dalej sprawdzać, doczepianie zakończone
}
} while (n--);
// write down what vehicle we're uncoupling, we might need to fiddle with remainder of the consist afterwards
if( ( p == nullptr )
|| ( p->MoverParameters->Couplers[ d ].Connected == nullptr ) ) {
// no target, or already just virtual coupling
WriteLog( mvOccupied->Name + " didn't find anything to disconnect." );
iVehicleCount = -2; // odczepiono, co było do odczepienia
} else if ( p->Dettach(d) == coupling::faux ) {
// tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2;
} // a jak nie, to dociskać dalej
}
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
// powino zostać wyłączone)
// WriteLog("Zahamowanie składu");
mvOccupied->BrakeLevelSet(
mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
1 :
3 );
double p = mvOccupied->BrakePressureActual.PipePressureVal;
if( p < 3.9 ) {
// tu może być 0 albo -1 nawet
// TODO: zabezpieczenie przed dziwnymi CHK do czasu wyjaśnienia sensu 0 oraz -1 w tym miejscu
p = 3.9;
if (iVehicleCount >= 0) // zmieni się po odczepieniu
if (!mvOccupied->DecLocalBrakeLevel(1))
{ // dociśnij sklad
WriteLog( mvOccupied->Name + " dociskanie..." );
// mvOccupied->BrakeReleaser(); //wyluzuj lokomotywę
// Ready=true; //zamiast sprawdzenia odhamowania całego składu
IncSpeed(); // dla (Ready)==false nie ruszy
}
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
mvOccupied->BrakePress > 2 :
mvOccupied->PipePress < p + 0.1)
{ // jeśli w miarę został zahamowany (ciśnienie mniejsze niż podane na
// pozycji 3, zwyle 0.37)
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic)
mvOccupied->BrakeLevelSet(0); // wyłączenie EP, gdy wystarczy (może
// nie być potrzebne, bo na początku jest)
WriteLog("Luzowanie lokomotywy i zmiana kierunku");
mvOccupied->BrakeReleaser(1); // wyluzuj lokomotywę; a ST45?
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca
iDrivigFlags |= movePress; // następnie będzie dociskanie
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
/*
// NOTE: disabled to prevent closing the door before passengers can disembark
fStopTime = 0.0; // nie ma na co czekać z odczepianiem
*/
}
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
{ // 2. faza odczepiania: zmień kierunek na przeciwny i dociśnij
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
// powino zostać wyłączone)
// WriteLog("Zahamowanie składu");
mvOccupied->BrakeLevelSet(
mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
1 :
3 );
double p = mvOccupied->BrakePressureActual.PipePressureVal;
if( p < 3.9 ) {
// tu może być 0 albo -1 nawet
// TODO: zabezpieczenie przed dziwnymi CHK do czasu wyjaśnienia sensu 0 oraz -1 w tym miejscu
p = 3.9;
}
if (mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ?
mvOccupied->BrakePress > 2 :
mvOccupied->PipePress < p + 0.1)
{ // jeśli w miarę został zahamowany (ciśnienie mniejsze niż podane na pozycji 3, zwyle 0.37)
if( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) {
// wyłączenie EP, gdy wystarczy (może nie być potrzebne, bo na początku jest)
mvOccupied->BrakeLevelSet( 0 );
}
WriteLog("Luzowanie lokomotywy i zmiana kierunku");
mvOccupied->BrakeReleaser(1); // wyluzuj lokomotywę; a ST45?
mvOccupied->DecLocalBrakeLevel(LocalBrakePosNo); // zwolnienie hamulca
iDrivigFlags |= movePress; // następnie będzie dociskanie
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na przeciwny (dociskanie)
CheckVehicles(); // od razu zmienić światła (zgasić) - bez tego się nie odczepi
}
else {
if( mvOccupied->Vel > 0.01 ) {
// 1st phase(?)
// bring it to stop if it's not already stopped
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
}
}
} // odczepiania
else // to poniżej jeśli ilość wagonów ujemna
if (iDrivigFlags & movePress)
{ // 4. faza odczepiania: zwolnij i zmień kierunek
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie
if (!DecSpeed()) // jeśli już bardziej wyłączyć się nie da
{ // ponowna zmiana kierunku
WriteLog( mvOccupied->Name + " ponowna zmiana kierunku" );
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na właściwy
iDrivigFlags &= ~movePress; // koniec dociskania
JumpToNextOrder(); // zmieni światła
TableClear(); // skanowanie od nowa
iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem
SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy
}
else {
if( mvOccupied->Vel > 0.01 ) {
// 1st phase(?)
// bring it to stop if it's not already stopped
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
}
}
} // odczepiania
else // to poniżej jeśli ilość wagonów ujemna
if (iDrivigFlags & movePress)
{ // 4. faza odczepiania: zwolnij i zmień kierunek
SetVelocity(0, 0, stopJoin); // wyłączyć przyspieszanie
if (!DecSpeed()) // jeśli już bardziej wyłączyć się nie da
{ // ponowna zmiana kierunku
WriteLog( mvOccupied->Name + " ponowna zmiana kierunku" );
DirectionForward(mvOccupied->ActiveDir < 0); // zmiana kierunku jazdy na właściwy
iDrivigFlags &= ~movePress; // koniec dociskania
JumpToNextOrder(); // zmieni światła
TableClear(); // skanowanie od nowa
iDrivigFlags &= ~moveStartHorn; // bez trąbienia przed ruszeniem
SetVelocity(fShuntVelocity, fShuntVelocity); // ustawienie prędkości jazdy
}
}
}
if( true == TestFlag( OrderList[ OrderPos ], Change_direction ) ) {
// when loose shunting try to detect situations where engaged brakes in a consist to be pushed prevent movement
if( ( true == AIControllFlag )
&& ( ( OrderCurrentGet() & Loose_shunt ) != 0 )
&& ( Obstacle.distance < 1.0 )
&& ( AccDesired > 0.1 )
&& ( mvOccupied->Vel < 1.0 ) ){
auto *vehicle { Obstacle.vehicle };
auto const direction { ( vehicle->Prev() != nullptr ? end::front : end::rear ) };
while( vehicle != nullptr ) {
if( vehicle->MoverParameters->BrakePress > 0.2 ) {
vehicle->MoverParameters->BrakeLevelSet( 0 ); // hamulec na zero, aby nie hamował
vehicle->MoverParameters->BrakeReleaser( 1 ); // wyluzuj pojazd, aby dało się dopychać
}
// NOTE: we trust the consist to be arranged in a valid chain
// TBD, TODO: traversal direction validation?
vehicle = ( direction == end::front ? vehicle->Prev() : vehicle->Next() );
}
}
if( true == TestFlag( OrderCurrentGet(), Change_direction ) ) {
// if ordered to change direction, try to stop
SetVelocity( 0, 0, stopDir );
}
if( VelNext == 0.0 ) {
if( !( OrderList[ OrderPos ] & ~( Shunt | Connect ) ) ) {
if( !( OrderCurrentGet() & ~( Shunt | Loose_shunt | Connect ) ) ) {
// jedzie w Shunt albo Connect, albo Wait_for_orders
// w trybie Connect skanować do tyłu tylko jeśli przed kolejnym sygnałem nie ma taboru do podłączenia
// Ra 2F1H: z tym (fTrackBlock) to nie jest najlepszy pomysł, bo lepiej by
// było porównać z odległością od sygnalizatora z przodu
if( ( ( OrderList[ OrderPos ] & Connect ) == 0 )
if( ( ( OrderCurrentGet() & Connect ) == 0 )
|| ( Obstacle.distance > std::min( 2000.0, FirstSemaphorDist ) ) ) {
if( ( comm = BackwardScan() ) != TCommandType::cm_Unknown ) {
@@ -4756,7 +4821,7 @@ TController::UpdateSituation(double dt) {
}
iDirectionOrder = -iDirection; // zmiana kierunku jazdy
// zmiana kierunku bez psucia kolejnych komend
OrderList[ OrderPos ] = TOrders( OrderList[ OrderPos ] | Change_direction );
OrderList[ OrderPos ] = TOrders( OrderCurrentGet() | Change_direction );
}
}
}
@@ -4768,6 +4833,7 @@ TController::UpdateSituation(double dt) {
if (VelDesired < 0.0)
VelDesired = fVelMax; // bo VelDesired<0 oznacza prędkość maksymalną
// Ra: jazda na widoczność
// Ra: jazda na widoczność
if( Obstacle.distance < 5000 ) {
// mamy coś z przodu
@@ -4805,16 +4871,16 @@ TController::UpdateSituation(double dt) {
// jeśli odległość jest zbyt mała
if( k < 10.0 ) // k - prędkość tego z przodu
{ // jeśli tamten porusza się z niewielką prędkością albo stoi
if( OrderCurrentGet() & Connect ) {
if( ( OrderCurrentGet() & ( Connect | Loose_shunt ) ) != 0 ) {
// jeśli spinanie, to jechać dalej
AccPreferred = std::min( 0.35, AccPreferred ); // nie hamuj
VelDesired =
VelDesired = std::floor(
min_speed(
VelDesired,
( Obstacle.distance > 150 ?
20.0:
4.0 ) );
VelNext = 2.0; // i pakuj się na tamtego
k + 20.0:
std::min( 8.0, k + 4.0 ) ) ) );
VelNext = std::floor( std::min( 8.0, k + 2.0 ) ); // i pakuj się na tamtego
}
else {
// a normalnie to hamować
@@ -4917,7 +4983,7 @@ TController::UpdateSituation(double dt) {
}
}
if( ( OrderCurrentGet() & ( Shunt | Obey_train ) ) != 0 ) {
if( ( OrderCurrentGet() & ( Shunt | Loose_shunt | Obey_train | Bank ) ) != 0 ) {
// w Connect nie, bo moveStopHere odnosi się do stanu po połączeniu
if( ( ( iDrivigFlags & moveStopHere ) != 0 )
&& ( vel < 0.01 )
@@ -5387,7 +5453,7 @@ TController::UpdateSituation(double dt) {
// wyluzuj lokomotywę - może być więcej!
mvOccupied->BrakeReleaser( 1 );
}
else if( OrderList[ OrderPos ] != Disconnect ) {
else if( OrderCurrentGet() != Disconnect ) {
// przy odłączaniu nie zwalniamy tu hamulca
if( ( fAccGravity * fAccGravity < 0.001 ?
true :
@@ -5460,7 +5526,7 @@ TController::UpdateSituation(double dt) {
// hamować bardziej, gdy aktualne opóźnienie hamowania mniejsze niż (AccDesired)
IncBrake();
}
else if( OrderList[ OrderPos ] != Disconnect ) {
else if( OrderCurrentGet() != Disconnect ) {
// przy odłączaniu nie zwalniamy tu hamulca
if( AbsAccS < AccDesired - 0.05 ) {
// jeśli opóźnienie większe od wymaganego (z histerezą) luzowanie, gdy za dużo
@@ -5505,7 +5571,7 @@ TController::UpdateSituation(double dt) {
if ((AccDesired < fAccGravity - 0.05) && (AbsAccS < AccDesired - fBrake_a1[0]*0.51)) {
// jak hamuje, to nie tykaj kranu za często
// yB: luzuje hamulec dopiero przy różnicy opóźnień rzędu 0.2
if( OrderList[ OrderPos ] != Disconnect ) {
if( OrderCurrentGet() != Disconnect ) {
// przy odłączaniu nie zwalniamy tu hamulca
DecBrake(); // tutaj zmniejszało o 1 przy odczepianiu
}
@@ -5548,7 +5614,7 @@ TController::UpdateSituation(double dt) {
}
if (AIControllFlag)
{ // odhamowywanie składu po zatrzymaniu i zabezpieczanie lokomotywy
if( ( ( OrderList[ OrderPos ] & ( Disconnect | Connect ) ) == 0 )
if( ( ( OrderCurrentGet() & ( Disconnect | Connect ) ) == 0 )
&& ( std::abs( fAccGravity ) < 0.01 ) ) {
// przy (p)odłączaniu nie zwalniamy tu hamulca
// only do this on flats, on slopes keep applied the train brake
@@ -5629,9 +5695,7 @@ void TController::JumpToNextOrder()
if (OrderList[OrderPos] & Change_direction) // jeśli zmiana kierunku
if (OrderList[OrderPos] != Change_direction) // ale nałożona na coś
{
OrderList[OrderPos] =
TOrders(OrderList[OrderPos] &
~Change_direction); // usunięcie zmiany kierunku z innej komendy
OrderList[OrderPos] = TOrders(OrderList[OrderPos] & ~Change_direction); // usunięcie zmiany kierunku z innej komendy
OrderCheck();
return;
}
@@ -5662,14 +5726,14 @@ void TController::JumpToFirstOrder()
void TController::OrderCheck()
{ // reakcja na zmianę rozkazu
if( OrderList[ OrderPos ] != Obey_train ) {
if( OrderCurrentGet() != Obey_train ) {
// reset light hints
m_lighthints[ end::front ] = m_lighthints[ end::rear ] = -1;
}
if( OrderList[ OrderPos ] & ( Shunt | Connect | Obey_train ) ) {
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Connect | Obey_train | Bank ) ) {
CheckVehicles(); // sprawdzić światła
}
if( OrderList[ OrderPos ] & ( Shunt | Connect ) ) {
if( OrderCurrentGet() & ( Shunt | Loose_shunt | Connect ) ) {
// HACK: ensure consist doors will be closed on departure
iDrivigFlags |= moveDoorOpened;
}
@@ -5694,7 +5758,7 @@ void TController::OrderNext(TOrders NewOrder)
OrderTop = OrderPos; // ale może jest czymś zajęty na razie
if (NewOrder >= Shunt) // jeśli ma jechać
{ // ale może być zajęty chwilowymi operacjami
while (OrderList[OrderTop] ? OrderList[OrderTop] < Shunt : false) // jeśli coś robi
while ((OrderList[OrderTop] != Wait_for_orders) && (OrderList[OrderTop] < Shunt)) // jeśli coś robi
++OrderTop; // pomijamy wszystkie tymczasowe prace
}
else
@@ -5739,16 +5803,6 @@ void TController::OrdersDump()
}
};
inline TOrders TController::OrderCurrentGet()
{
return OrderList[OrderPos];
}
inline TOrders TController::OrderNextGet()
{
return OrderList[OrderPos + 1];
}
void TController::OrdersInit(double fVel)
{ // wypełnianie tabelki rozkazów na podstawie rozkładu
// ustawienie kolejności komend, niezależnie kto prowadzi
@@ -5989,7 +6043,7 @@ TCommandType TController::BackwardScan()
// dzięki temu będzie można stawać za wskazanym sygnalizatorem, a zwłaszcza jeśli będzie jazda na kozioł
// ograniczenia prędkości nie są wtedy istotne, również koniec toru jest do niczego nie przydatny
// zwraca true, jeśli należy odwrócić kierunek jazdy pojazdu
if( ( OrderList[ OrderPos ] & ~( Shunt | Connect ) ) ) {
if( ( OrderCurrentGet() & ~( Shunt | Loose_shunt | Connect ) ) ) {
// skanowanie sygnałów tylko gdy jedzie w trybie manewrowym albo czeka na rozkazy
return TCommandType::cm_Unknown;
}
@@ -6054,14 +6108,14 @@ TCommandType TController::BackwardScan()
bool move = false; // czy AI w trybie manewerowym ma dociągnąć pod S1
if( e->input_command() == TCommandType::cm_SetVelocity ) {
if( ( vmechmax == 0.0 ) ?
( OrderCurrentGet() & ( Shunt | Connect ) ) :
( OrderCurrentGet() & ( Shunt | Loose_shunt | Connect ) ) :
( OrderCurrentGet() & Connect ) ) { // przy podczepianiu ignorować wyjazd?
move = true; // AI w trybie manewerowym ma dociągnąć pod S1
}
else {
if( ( scandist > fMinProximityDist )
&& ( ( mvOccupied->Vel > 0.0 )
&& ( OrderCurrentGet() != Shunt ) ) ) {
&& ( ( OrderCurrentGet() & ( Shunt | Loose_shunt ) ) == 0 ) ) ) {
// jeśli semafor jest daleko, a pojazd jedzie, to informujemy o zmianie prędkości
// jeśli jedzie manewrowo, musi dostać SetVelocity, żeby sie na pociągowy przełączył
#if LOGBACKSCAN
@@ -6093,14 +6147,13 @@ TCommandType TController::BackwardScan()
}
}
}
if (OrderCurrentGet() ? OrderCurrentGet() & (Shunt | Connect) :
if (OrderCurrentGet() ? OrderCurrentGet() & (Shunt | Loose_shunt | Connect) :
true) // w Wait_for_orders też widzi tarcze
{ // reakcja AI w trybie manewrowym dodatkowo na sygnały manewrowe
if (move ? true : e->input_command() == TCommandType::cm_ShuntVelocity)
{ // jeśli powyżej było SetVelocity 0 0, to dociągamy pod S1
if ((scandist > fMinProximityDist) ?
(mvOccupied->Vel > 0.0) || (vmechmax == 0.0) :
false)
if ((scandist > fMinProximityDist) &&
(mvOccupied->Vel > 0.0) || (vmechmax == 0.0) )
{ // jeśli tarcza jest daleko, to:
//- jesli pojazd jedzie, to informujemy o zmianie prędkości
//- jeśli stoi, to z własnej inicjatywy może podjechać pod zamkniętą
@@ -6211,11 +6264,13 @@ void TController::TakeControl(bool yes)
if (OrderCurrentGet()) // jeśli coś robi
PrepareEngine(); // niech sprawdzi stan silnika
else // jeśli nic nie robi
if (pVehicle->iLights[mvOccupied->CabNo < 0 ? 1 : 0] &
21) // któreś ze świateł zapalone?
if (pVehicle->iLights[ ( mvOccupied->CabNo < 0 ?
end::rear :
end::front ) ]
& (light::headlight_left | light::headlight_right | light::headlight_upper)) // któreś ze świateł zapalone?
{ // od wersji 357 oczekujemy podania komend dla AI przez scenerię
OrderNext(Prepare_engine);
if (pVehicle->iLights[mvOccupied->CabNo < 0 ? 1 : 0] & 4) // górne światło zapalone
if (pVehicle->iLights[mvOccupied->CabNo < 0 ? end::rear : end::front] & light::headlight_upper) // górne światło zapalone
OrderNext(Obey_train); // jazda pociągowa
else
OrderNext(Shunt); // jazda manewrowa
@@ -6224,27 +6279,8 @@ void TController::TakeControl(bool yes)
else
iDrivigFlags |= moveStopHere; // a jak stoi, to niech czeka
}
/* od wersji 357 oczekujemy podania komend dla AI przez scenerię
if (OrderCurrentGet())
{if (OrderCurrentGet()<Shunt)
{OrderNext(Prepare_engine);
if (pVehicle->iLights[mvOccupied->CabNo<0?1:0]&4) //górne światło
OrderNext(Obey_train); //jazda pociągowa
else
OrderNext(Shunt); //jazda manewrowa
}
}
else //jeśli jest w stanie Wait_for_orders
JumpToFirstOrder(); //uruchomienie?
// czy dac ponizsze? to problematyczne
//SetVelocity(pVehicle->GetVelocity(),-1); //utrzymanie dotychczasowej?
if (pVehicle->GetVelocity()>0.0)
SetVelocity(-1,-1); //AI ustali sobie odpowiednią prędkość
*/
// Activation(); //przeniesie użytkownika w ostatnio wybranym kierunku
CheckVehicles(); // ustawienie świateł
TableClear(); // ponowne utworzenie tabelki, bo człowiek mógł pojechać niezgodnie z
// sygnałami
TableClear(); // ponowne utworzenie tabelki, bo człowiek mógł pojechać niezgodnie z sygnałami
}
else
{ // a teraz użytkownik

View File

@@ -19,15 +19,18 @@ enum TOrders
{ // rozkazy dla AI
Wait_for_orders = 0, // czekanie na dostarczenie następnych rozkazów
// operacje tymczasowe
Prepare_engine = 1, // włączenie silnika
Release_engine = 2, // wyłączenie silnika
Change_direction = 4, // zmiana kierunku (bez skanowania sygnalizacji)
Connect = 8, // podłączanie wagonów (z częściowym skanowaniem sygnalizacji)
Disconnect = 0x10, // odłączanie wagonów (bez skanowania sygnalizacji)
Prepare_engine = 1 << 0, // włączenie silnika
Release_engine = 1 << 1, // wyłączenie silnika
Change_direction = 1 << 2, // zmiana kierunku (bez skanowania sygnalizacji)
Connect = 1 << 3, // podłączanie wagonów (z częściowym skanowaniem sygnalizacji)
Disconnect = 1 << 4, // odłączanie wagonów (bez skanowania sygnalizacji)
// jazda
Shunt = 0x20, // tryb manewrowy
Obey_train = 0x40, // tryb pociągowy
Jump_to_first_order = 0x60 // zapęlenie do pierwszej pozycji (po co?)
Shunt = 1 << 5, // tryb manewrowy
Loose_shunt = 1 << 6, // coupling-free shunting mode
Obey_train = 1 << 7, // tryb pociągowy
Bank = 1 << 8, // assist mode
// others
Jump_to_first_order = 1 << 9 // zapęlenie do pierwszej pozycji (po co?)
};
enum TMovementStatus
@@ -193,6 +196,7 @@ public:
TMoverParameters const *Controlling() const {
return mvControlling; }
void DirectionInitial();
void DirectionChange();
inline
int Direction() const {
return iDirection; }
@@ -314,8 +318,8 @@ private:
void JumpToFirstOrder();
void OrderPush(TOrders NewOrder);
void OrderNext(TOrders NewOrder);
inline TOrders OrderCurrentGet();
inline TOrders OrderNextGet();
inline TOrders OrderCurrentGet() const;
inline TOrders OrderNextGet() const;
void OrderCheck();
void OrdersInit(double fVel);
void OrdersClear();
@@ -449,3 +453,11 @@ private:
*/
};
inline TOrders TController::OrderCurrentGet() const {
return OrderList[ OrderPos ];
}
inline TOrders TController::OrderNextGet() const {
return OrderList[ OrderPos + 1 ];
}

View File

@@ -5869,7 +5869,7 @@ TDynamicObject::update_neighbours() {
neighbour.vehicle_end = std::get<int>( lookup );
neighbour.distance = std::get<double>( lookup );
if( neighbour.distance < ( neighbour.vehicle->MoverParameters->CategoryFlag == 2 ? 25 : 50 ) ) {
if( neighbour.distance < ( neighbour.vehicle->MoverParameters->CategoryFlag == 2 ? 50 : 100 ) ) {
// at short distances (re)calculate range between couplers directly
neighbour.distance = TMoverParameters::CouplerDist( MoverParameters, neighbour.vehicle->MoverParameters );
}

View File

@@ -635,7 +635,7 @@ struct TCoupling {
struct neighbour_data {
TDynamicObject *vehicle { nullptr }; // detected obstacle
int vehicle_end { -1 }; // facing end of the obstacle
float distance { -1.f }; // distance to the obstacle
float distance { 10000.f }; // distance to the obstacle // NOTE: legacy value. TBD, TODO: use standard -1 instead?
};

View File

@@ -518,13 +518,16 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "unit_no", iUnitNo );
for( int i = 0; i < 20; i++ ) {
dict->insert( ( "doors_" + std::to_string( i + 1 ) ), bDoors[ i ][ 0 ] );
dict->insert( ( "doors_r_" + std::to_string( i + 1 ) ), bDoors[ i ][ 1 ] );
dict->insert( ( "doors_l_" + std::to_string( i + 1 ) ), bDoors[ i ][ 2 ] );
dict->insert( ( "doors_no_" + std::to_string( i + 1 ) ), iDoorNo[ i ] );
dict->insert( ( "code_" + std::to_string( i + 1 ) ), ( std::to_string( iUnits[ i ] ) + cCode[ i ] ) );
dict->insert( ( "car_name" + std::to_string( i + 1 ) ), asCarName[ i ] );
dict->insert( ( "slip_" + std::to_string( i + 1 ) ), bSlip[ i ] );
auto const caridx { std::to_string( i + 1 ) };
dict->insert( ( "doors_" + caridx ), bDoors[ i ][ 0 ] );
dict->insert( ( "doors_l_" + caridx ), bDoors[ i ][ 1 ] );
dict->insert( ( "doors_r_" + caridx ), bDoors[ i ][ 2 ] );
dict->insert( ( "doorstep_l_" + caridx ), bDoors[ i ][ 3 ] );
dict->insert( ( "doorstep_r_" + caridx ), bDoors[ i ][ 4 ] );
dict->insert( ( "doors_no_" + caridx ), iDoorNo[ i ] );
dict->insert( ( "code_" + caridx ), ( std::to_string( iUnits[ i ] ) + cCode[ i ] ) );
dict->insert( ( "car_name" + caridx ), asCarName[ i ] );
dict->insert( ( "slip_" + caridx ), bSlip[ i ] );
}
// ai state data
auto const *driver = DynamicObject->Mechanik;
@@ -1588,7 +1591,7 @@ void TTrain::OnCommand_reverserincrease( TTrain *Train, command_data const &Comm
if( ( Train->mvOccupied->ActiveDir )
&& ( Train->DynamicObject->Mechanik ) ) {
Train->DynamicObject->Mechanik->CheckVehicles( Change_direction );
Train->DynamicObject->Mechanik->DirectionChange();
}
}
}
@@ -1603,7 +1606,7 @@ void TTrain::OnCommand_reverserdecrease( TTrain *Train, command_data const &Comm
if( ( Train->mvOccupied->ActiveDir )
&& ( Train->DynamicObject->Mechanik ) ) {
Train->DynamicObject->Mechanik->CheckVehicles( Change_direction );
Train->DynamicObject->Mechanik->DirectionChange();;
}
}
}
@@ -1634,7 +1637,7 @@ void TTrain::OnCommand_reverserforward( TTrain *Train, command_data const &Comma
if( ( Train->mvOccupied->ActiveDir == 1 )
&& ( Train->DynamicObject->Mechanik ) ) {
Train->DynamicObject->Mechanik->CheckVehicles( Change_direction );
Train->DynamicObject->Mechanik->DirectionChange();
}
}
}
@@ -1669,7 +1672,7 @@ void TTrain::OnCommand_reverserbackward( TTrain *Train, command_data const &Comm
if( ( Train->mvOccupied->ActiveDir == -1 )
&& ( Train->DynamicObject->Mechanik ) ) {
Train->DynamicObject->Mechanik->CheckVehicles( Change_direction );
Train->DynamicObject->Mechanik->DirectionChange();
}
}
}
@@ -4153,12 +4156,12 @@ void TTrain::OnCommand_generictoggle( TTrain *Train, command_data const &Command
if( item.GetDesiredValue() < 0.5 ) {
// turn on
// visual feedback
item.UpdateValue( 1.0, Train->dsbSwitch );
item.UpdateValue( 1.0 );
}
else {
// turn off
// visual feedback
item.UpdateValue( 0.0, Train->dsbSwitch );
item.UpdateValue( 0.0 );
}
}
}
@@ -5186,8 +5189,10 @@ bool TTrain::Update( double const Deltatime )
fPress[i][0] = p->MoverParameters->BrakePress;
fPress[i][1] = p->MoverParameters->PipePress;
fPress[i][2] = p->MoverParameters->ScndPipePress;
bDoors[i][1] = ( false == p->MoverParameters->Doors.instances[ side::right ].is_closed );
bDoors[i][2] = ( false == p->MoverParameters->Doors.instances[ side::left ].is_closed );
bDoors[i][1] = ( false == p->MoverParameters->Doors.instances[ side::left ].is_closed );
bDoors[i][2] = ( false == p->MoverParameters->Doors.instances[ side::right ].is_closed );
bDoors[i][3] = ( p->MoverParameters->Doors.instances[ side::left ].step_position > 0.0 );
bDoors[i][4] = ( p->MoverParameters->Doors.instances[ side::right ].step_position > 0.0 );
bDoors[i][0] = ( bDoors[i][1] || bDoors[i][2] );
iDoorNo[i] = p->iAnimType[ANIM_DOORS];
iUnits[i] = iUnitNo;
@@ -5234,12 +5239,16 @@ bool TTrain::Update( double const Deltatime )
}
else
{
fPress[i][0] = 0;
fPress[i][1] = 0;
fPress[i][2] = 0;
bDoors[i][0] = false;
bDoors[i][1] = false;
bDoors[i][2] = false;
fPress[i][0]
= fPress[i][1]
= fPress[i][2]
= 0;
bDoors[i][0]
= bDoors[i][1]
= bDoors[i][2]
= bDoors[i][3]
= bDoors[i][4]
= false;
bSlip[i] = false;
iUnits[i] = 0;
cCode[i] = 0; //'0';
@@ -6493,7 +6502,7 @@ bool TTrain::CabChange(int iDirection)
DynamicObject->asBaseDir + DynamicObject->MoverParameters->TypeName + ".mmd" ) ) {
// zmiana kabiny w ramach tego samego pojazdu
DynamicObject->MoverParameters->CabActivisation(); // załączenie rozrządu (wirtualne kabiny)
DynamicObject->Mechanik->CheckVehicles( Change_direction );
DynamicObject->Mechanik->DirectionChange();
return true; // udało się zmienić kabinę
}
}

View File

@@ -643,7 +643,7 @@ private:
float fHCurrent[ 4 ] = { 0.0f, 0.0f, 0.0f, 0.0f }; // pr?dy: suma i amperomierze 1,2,3
float fEngine[ 4 ] = { 0.0f, 0.0f, 0.0f, 0.0f }; // obroty te? trzeba pobra?
int iCarNo, iPowerNo, iUnitNo; // liczba pojazdow, czlonow napednych i jednostek spiętych ze sobą
bool bDoors[20][3]; // drzwi dla wszystkich czlonow
bool bDoors[20][5]; // drzwi dla wszystkich czlonow; left+right, left, right, step_left, step_right
int iUnits[20]; // numer jednostki
int iDoorNo[20]; // liczba drzwi
char cCode[20]; // kod pojazdu

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 19
#define VERSION_MINOR 227
#define VERSION_MINOR 303
#define VERSION_REVISION 0