mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 22:09:19 +02:00
lpt diagnostics, tempomat configuration enhancements, ai cargo train driving logic tweaks, partial ai support for universal controller in diesel-electric vehicles
This commit is contained in:
@@ -9,6 +9,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "LPT.h"
|
||||
#include "Logs.h"
|
||||
|
||||
// LPT na USB:
|
||||
// USB\VID_067B&PID_2305&REV_0200
|
||||
@@ -24,6 +25,8 @@ OutPortType OutPort;
|
||||
|
||||
bool TLPT::Connect(int port)
|
||||
{
|
||||
WriteLog( "LPT: trying to access port " + std::to_string(port) );
|
||||
|
||||
// ladowanie dll-ki
|
||||
hDLL = LoadLibrary("inpout32.dll");
|
||||
if (hDLL)
|
||||
@@ -32,9 +35,11 @@ bool TLPT::Connect(int port)
|
||||
OutPort = (OutPortType)GetProcAddress(hDLL, "Out32");
|
||||
}
|
||||
else
|
||||
return false; // MessageBox(NULL,"ERROR","Błąd przy ładowaniu pliku",MB_OK);
|
||||
address =
|
||||
port; //&0xFFFFFC; //ostatnie 2 bity mają być zerowe -> a niech sobie OUT-ują, gdzie chcą
|
||||
{
|
||||
WriteLog("LPT: failed to load inpout32");
|
||||
return false;
|
||||
}
|
||||
address = port;
|
||||
switch (address) // nie dotyczy 0x3BC
|
||||
{
|
||||
case 0x0378:
|
||||
@@ -45,6 +50,9 @@ bool TLPT::Connect(int port)
|
||||
case 0xBD00:
|
||||
OutPort(address + 0x006, 0); // 0xBC06? czysta improwizacja
|
||||
}
|
||||
|
||||
WriteLog("LPT: setup complete");
|
||||
|
||||
return OutPort != 0;
|
||||
};
|
||||
|
||||
|
||||
122
Driver.cpp
122
Driver.cpp
@@ -153,6 +153,8 @@ const double EasyReactionTime = 0.5; //[s] przebłyski świadomości dla zwykłe
|
||||
const double HardReactionTime = 0.2;
|
||||
const double EasyAcceleration = 0.85; //[m/ss]
|
||||
const double HardAcceleration = 9.81;
|
||||
const double CargoTrainAcceleration = 0.25;
|
||||
const double HeavyCargoTrainAcceleration = 0.10;
|
||||
const double PrepareTime = 2.0; //[s] przebłyski świadomości przy odpalaniu
|
||||
bool WriteLogFlag = false;
|
||||
double const deltalog = 0.05; // przyrost czasu
|
||||
@@ -1822,7 +1824,7 @@ void TController::OrdersClear()
|
||||
for (int b = 0; b < maxorders; b++)
|
||||
OrderList[b] = Wait_for_orders;
|
||||
#if LOGORDERS
|
||||
WriteLog("--> OrdersClear");
|
||||
OrdersDump("OrdersClear", false);
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -2052,7 +2054,7 @@ void TController::AutoRewident()
|
||||
}
|
||||
|
||||
IsCargoTrain = ( mvOccupied->CategoryFlag == 1 ) && ( ( mvOccupied->BrakeDelayFlag & bdelay_G ) != 0 );
|
||||
IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 );
|
||||
IsHeavyCargoTrain = ( true == IsCargoTrain ) && ( fBrake_a0[ 1 ] > 0.4 ) && ( iVehicles - ControlledEnginesCount > 0 ) && ( fMass / iVehicles > 50000 );
|
||||
|
||||
BrakingInitialLevel = (
|
||||
IsHeavyCargoTrain ? 1.25 :
|
||||
@@ -3176,6 +3178,10 @@ bool TController::IncSpeed()
|
||||
// gdy jest nakaz poczekać z jazdą, to nie ruszać
|
||||
return false;
|
||||
}
|
||||
if( IsAnyCouplerStretched ) {
|
||||
// train is already stretched past its limits, don't pull even harder
|
||||
return false;
|
||||
}
|
||||
bool OK = true;
|
||||
if( ( iDrivigFlags & moveDoorOpened )
|
||||
&& ( VelDesired > 0.0 ) ) { // to prevent door shuffle on stop
|
||||
@@ -3221,8 +3227,8 @@ bool TController::IncSpeed()
|
||||
// if the power station is heavily burdened,
|
||||
// if it generates enough traction force
|
||||
// to build up speed to 30/40 km/h for passenger/cargo train (10 km/h less if going uphill)
|
||||
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 125 : 100 ) * 1000.0 };
|
||||
auto const sufficientacceleration { AbsAccS_pub >= ( IsHeavyCargoTrain ? 0.02 : 0.04 ) };
|
||||
auto const sufficienttractionforce { std::abs( mvControlling->Ft ) > ( IsHeavyCargoTrain ? 75 : 50 ) * 1000.0 };
|
||||
auto const sufficientacceleration { AbsAccS_pub >= ( IsHeavyCargoTrain ? 0.03 : IsCargoTrain ? 0.06 : 0.09 ) };
|
||||
auto const seriesmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 ) };
|
||||
auto const parallelmodefieldshunting { ( mvControlling->ScndCtrlPos > 0 ) && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 ) };
|
||||
auto const useseriesmodevoltage {
|
||||
@@ -3233,9 +3239,9 @@ bool TController::IncSpeed()
|
||||
auto const useseriesmode = (
|
||||
( mvControlling->Imax > mvControlling->ImaxLo )
|
||||
|| ( fVoltage < useseriesmodevoltage )
|
||||
|| ( ( true == sufficienttractionforce )
|
||||
&& ( true == sufficientacceleration )
|
||||
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 35 : 25 ) + ( seriesmodefieldshunting ? 5 : 0 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) ) );
|
||||
|| ( ( true == sufficientacceleration )
|
||||
&& ( true == sufficienttractionforce )
|
||||
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 40 : 30 ) + ( seriesmodefieldshunting ? 5 : 0 ) - ( ( fAccGravity < -0.025 ) ? 10 : 0 ) ) ) );
|
||||
// when not in series mode use the first available parallel mode configuration until 50/60 km/h for passenger/cargo train
|
||||
// (if there's only one parallel mode configuration it'll be used regardless of current speed)
|
||||
auto const usefieldshunting = (
|
||||
@@ -3243,9 +3249,9 @@ bool TController::IncSpeed()
|
||||
&& ( mvControlling->RList[ mvControlling->MainCtrlPos ].R < 0.01 )
|
||||
&& ( useseriesmode ?
|
||||
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn == 1 :
|
||||
( ( true == sufficienttractionforce )
|
||||
&& ( true == sufficientacceleration )
|
||||
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 55 : 45 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ?
|
||||
( ( true == sufficientacceleration )
|
||||
&& ( true == sufficienttractionforce )
|
||||
&& ( mvOccupied->Vel <= ( IsCargoTrain ? 60 : 50 ) + ( parallelmodefieldshunting ? 5 : 0 ) ) ?
|
||||
mvControlling->RList[ mvControlling->MainCtrlPos ].Bn > 1 :
|
||||
mvControlling->MainCtrlPos == mvControlling->MainCtrlPosNo ) ) );
|
||||
|
||||
@@ -3282,7 +3288,7 @@ bool TController::IncSpeed()
|
||||
mvControlling->RList[ std::min( mvControlling->MainCtrlPos + 1, mvControlling->MainCtrlPosNo ) ].Bn == 1 ?
|
||||
mvControlling->EnginePowerSource.CollectorParameters.MinV :
|
||||
useseriesmodevoltage )
|
||||
> ( IsHeavyCargoTrain ? 80.0 : 60.0 ) * ControlledEnginesCount };
|
||||
> ( IsHeavyCargoTrain ? 100.0 : 75.0 ) * ControlledEnginesCount };
|
||||
|
||||
OK = (
|
||||
( sufficientpowermargin && ( false == mvControlling->DelayCtrlFlag ) ) ?
|
||||
@@ -3425,20 +3431,20 @@ bool TController::DecSpeed(bool force)
|
||||
iDrivigFlags &= ~moveIncSpeed; // usunięcie flagi jazdy
|
||||
if (force) // przy aktywacji kabiny jest potrzeba natychmiastowego wyzerowania
|
||||
if (mvControlling->MainCtrlPosNo > 0) // McZapkie-041003: wagon sterowniczy, np. EZT
|
||||
mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 1 ? 2 : 1));
|
||||
mvControlling->DecMainCtrl( std::min( mvControlling->MainCtrlPowerPos(), 2 ) );
|
||||
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
|
||||
return false;
|
||||
case TEngineType::ElectricSeriesMotor:
|
||||
OK = mvControlling->DecScndCtrl(2); // najpierw bocznik na zero
|
||||
if (!OK)
|
||||
OK = mvControlling->DecMainCtrl((mvControlling->MainCtrlPowerPos() > 1 ? 2 : 1));
|
||||
OK = mvControlling->DecMainCtrl( std::min( mvControlling->MainCtrlPowerPos(), 2 ) );
|
||||
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
|
||||
break;
|
||||
case TEngineType::Dumb:
|
||||
case TEngineType::DieselElectric:
|
||||
OK = mvControlling->DecScndCtrl(2);
|
||||
if (!OK)
|
||||
OK = mvControlling->DecMainCtrl(2 + (mvControlling->MainCtrlPowerPos() / 2));
|
||||
OK = mvControlling->DecMainCtrl( std::min( mvControlling->MainCtrlPowerPos(), ( 2 + (mvControlling->MainCtrlPowerPos() / 2) ) ) );
|
||||
break;
|
||||
case TEngineType::ElectricInductionMotor:
|
||||
OK = DecSpeedEIM();
|
||||
@@ -3515,13 +3521,13 @@ bool TController::IncSpeedEIM() {
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool TController::DecSpeedEIM()
|
||||
bool TController::DecSpeedEIM( int const Amount )
|
||||
{ // zmniejszenie prędkości (ale nie hamowanie)
|
||||
bool OK = false; // domyślnie false, aby wyszło z pętli while
|
||||
switch (mvControlling->EIMCtrlType)
|
||||
{
|
||||
case 0:
|
||||
OK = mvControlling->DecMainCtrl(1);
|
||||
OK = mvControlling->DecMainCtrl( Amount );
|
||||
break;
|
||||
case 1:
|
||||
OK = mvControlling->MainCtrlPos > 4;
|
||||
@@ -3909,6 +3915,38 @@ void TController::SetTimeControllers()
|
||||
}
|
||||
}
|
||||
}
|
||||
// 5.5 universal control for diesel electric vehicles
|
||||
if ((mvControlling->EngineType == TEngineType::DieselElectric) && (mvControlling->EIMCtrlType == 3))
|
||||
{
|
||||
// NOTE: partial implementation for speedinc/dec
|
||||
// TBD, TODO: implement fully?
|
||||
if( ( AccDesired >= 0.0 )
|
||||
&& ( mvControlling->StLinFlag ) ) {
|
||||
|
||||
auto const PosInc { mvControlling->MainCtrlPosNo };
|
||||
auto PosKeep { 0 };
|
||||
auto PosDec{ 0 };
|
||||
for( int i = PosInc; i >= 0; --i ) {
|
||||
if( mvControlling->UniCtrlList[ i ].SetCtrlVal <= 0 ) {
|
||||
if( mvControlling->UniCtrlList[ i ].SpeedDown == 0.0 ) {
|
||||
PosKeep = i;
|
||||
}
|
||||
if( mvControlling->UniCtrlList[ i ].SpeedDown > 0.01 ) {
|
||||
PosDec = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto const DesiredPos { (
|
||||
AccDesired > AbsAccS_pub + 0.05 ? PosInc :
|
||||
AccDesired < AbsAccS_pub - 0.05 ? PosDec :
|
||||
PosKeep ) };
|
||||
|
||||
while( ( mvControlling->MainCtrlPos > DesiredPos ) && mvControlling->DecMainCtrl( 1 ) ) { ; }
|
||||
while( ( mvControlling->MainCtrlPos < DesiredPos ) && mvControlling->IncMainCtrl( 1 ) ) { ; }
|
||||
}
|
||||
}
|
||||
//6. UniversalBrakeButtons
|
||||
//6.1. Checking flags for Over pressure
|
||||
if (std::abs(BrakeCtrlPosition - gbh_FS)<0.5) {
|
||||
@@ -4493,8 +4531,7 @@ bool TController::PutCommand( std::string NewCommand, double NewValue1, double N
|
||||
OrderPos = 1;
|
||||
}
|
||||
#if LOGORDERS
|
||||
WriteLog("--> Jump_to_order");
|
||||
OrdersDump();
|
||||
OrdersDump("Jump_to_order");
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
@@ -4658,6 +4695,7 @@ TController::UpdateSituation(double dt) {
|
||||
fAccGravity = 0.0; // przyspieszenie wynikające z pochylenia
|
||||
double dy; // składowa styczna grawitacji, w przedziale <0,1>
|
||||
double AbsAccS = 0;
|
||||
IsAnyCouplerStretched = false;
|
||||
IsAnyDoorOpen[ side::right ] = IsAnyDoorOpen[ side::left ] = false;
|
||||
ConsistShade = 0.0;
|
||||
TDynamicObject *p = pVehicles[0]; // pojazd na czole składu
|
||||
@@ -4696,6 +4734,11 @@ TController::UpdateSituation(double dt) {
|
||||
// ciężar razy składowa styczna grawitacji
|
||||
fAccGravity -= vehicle->TotalMassxg * dy * ( p->DirectionGet() == iDirection ? 1 : -1 );
|
||||
}
|
||||
// check coupler state
|
||||
IsAnyCouplerStretched =
|
||||
IsAnyCouplerStretched
|
||||
|| ( vehicle->Couplers[ end::front ].stretch_duration > 0.0 )
|
||||
|| ( vehicle->Couplers[ end::rear ].stretch_duration > 0.0 );
|
||||
// check door state
|
||||
auto const switchsides { p->DirectionGet() != iDirection };
|
||||
IsAnyDoorOpen[ side::right ] =
|
||||
@@ -5385,8 +5428,7 @@ TController::UpdateSituation(double dt) {
|
||||
else
|
||||
++OrderPos;
|
||||
#if LOGORDERS
|
||||
WriteLog("--> Jump_to_first_order");
|
||||
OrdersDump();
|
||||
OrdersDump("Jump_to_first_order");
|
||||
#endif
|
||||
break;
|
||||
case Wait_for_orders: // jeśli czeka, też ma skanować, żeby odpalić się od semafora
|
||||
@@ -6174,6 +6216,14 @@ TController::UpdateSituation(double dt) {
|
||||
*/
|
||||
}
|
||||
}
|
||||
// HACK: limit acceleration for cargo trains, to reduce probability of breaking couplers on sudden jolts
|
||||
// TBD: expand this behaviour to all trains with car(s) exceeding certain weight?
|
||||
if( IsCargoTrain ) {
|
||||
AccDesired = std::min( AccDesired, CargoTrainAcceleration );
|
||||
}
|
||||
if( IsHeavyCargoTrain ) {
|
||||
AccDesired = std::min( AccDesired, HeavyCargoTrainAcceleration );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// for cars the older version works better
|
||||
@@ -6283,7 +6333,7 @@ TController::UpdateSituation(double dt) {
|
||||
if( vel < VelDesired ) {
|
||||
// don't adjust acceleration when going above current goal speed
|
||||
if( -AccDesired * BrakeAccFactor() < (
|
||||
( ( fReady > ( ( mvOccupied->Vel > 5.0 ) ? 0.5 : 0.4 ) )
|
||||
( ( fReady > ( IsHeavyCargoTrain ? 0.4 : ( mvOccupied->Vel > 5.0 ) ? 0.45 : 0.4 ) )
|
||||
|| ( VelNext > vel - 40.0 ) ) ?
|
||||
fBrake_a0[ 0 ] * 0.8 :
|
||||
-fAccThreshold )
|
||||
@@ -6386,6 +6436,7 @@ TController::UpdateSituation(double dt) {
|
||||
", VelSignal=" + AnsiString(VelSignal) + ", VelNext=" +
|
||||
AnsiString(VelNext));
|
||||
#endif
|
||||
/*
|
||||
if( ( vel < 10.0 )
|
||||
&& ( AccDesired > 0.1 ) ) {
|
||||
// Ra 2F1H: jeśli prędkość jest mała, a można przyspieszać,
|
||||
@@ -6393,6 +6444,7 @@ TController::UpdateSituation(double dt) {
|
||||
// przy małych prędkościach może być trudno utrzymać
|
||||
AccDesired = std::max( 0.9, AccDesired );
|
||||
}
|
||||
*/
|
||||
// małe przyspieszenie
|
||||
// Ra 2F1I: wyłączyć kiedyś to uśrednianie i przeanalizować skanowanie, czemu migocze
|
||||
if (AccDesired > -0.05) // hamowania lepeiej nie uśredniać
|
||||
@@ -6454,10 +6506,11 @@ TController::UpdateSituation(double dt) {
|
||||
else if( ( vel > VelDesired + SpeedCtrlMargin)
|
||||
|| ( fAccGravity < -0.01 ?
|
||||
AccDesired < 0.0 :
|
||||
(AbsAccS > AccDesired && AccDesired < 0.75) ) ) {
|
||||
(AbsAccS > AccDesired + 0.05) )
|
||||
|| ( IsAnyCouplerStretched ) ) {
|
||||
// jak za bardzo przyspiesza albo prędkość przekroczona
|
||||
// dodany wyjatek na "pelna w przod"
|
||||
DecSpeed(); // pojedyncze cofnięcie pozycji, bo na zero to przesada
|
||||
DecSpeed();
|
||||
}
|
||||
}
|
||||
if( mvOccupied->TrainType == dt_EZT ) {
|
||||
@@ -6669,8 +6722,7 @@ void TController::JumpToNextOrder()
|
||||
}
|
||||
OrderCheck();
|
||||
#if LOGORDERS
|
||||
WriteLog("--> JumpToNextOrder");
|
||||
OrdersDump(); // normalnie nie ma po co tego wypisywać
|
||||
OrdersDump("JumpToNextOrder"); // normalnie nie ma po co tego wypisywać
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -6681,8 +6733,7 @@ void TController::JumpToFirstOrder()
|
||||
OrderTop = 1;
|
||||
OrderCheck();
|
||||
#if LOGORDERS
|
||||
WriteLog("--> JumpToFirstOrder");
|
||||
OrdersDump(); // normalnie nie ma po co tego wypisywać
|
||||
OrdersDump("JumpToFirstOrder"); // normalnie nie ma po co tego wypisywać
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -6733,8 +6784,7 @@ void TController::OrderNext(TOrders NewOrder)
|
||||
}
|
||||
OrderList[OrderTop++] = NewOrder; // dodanie rozkazu jako następnego
|
||||
#if LOGORDERS
|
||||
WriteLog("--> OrderNext");
|
||||
OrdersDump(); // normalnie nie ma po co tego wypisywać
|
||||
OrdersDump( "OrderNext" ); // normalnie nie ma po co tego wypisywać
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -6749,17 +6799,17 @@ void TController::OrderPush(TOrders NewOrder)
|
||||
if (OrderTop >= maxorders)
|
||||
ErrorLog("Commands overflow: The program will now crash");
|
||||
#if LOGORDERS
|
||||
WriteLog("--> OrderPush: [" + Order2Str( NewOrder ) + "]");
|
||||
OrdersDump(); // normalnie nie ma po co tego wypisywać
|
||||
OrdersDump( "OrderPush: [" + Order2Str( NewOrder ) + "]" ); // normalnie nie ma po co tego wypisywać
|
||||
#endif
|
||||
}
|
||||
|
||||
void TController::OrdersDump()
|
||||
void TController::OrdersDump( std::string const Neworder, bool const Verbose )
|
||||
{ // wypisanie kolejnych rozkazów do logu
|
||||
WriteLog("Orders for " + pVehicle->asName + ":");
|
||||
WriteLog( "New order for [" + pVehicle->asName + "]: " + Neworder );
|
||||
if( false == Verbose ) { return; }
|
||||
for (int b = 0; b < maxorders; ++b)
|
||||
{
|
||||
WriteLog((std::to_string(b) + ": " + Order2Str(OrderList[b]) + (OrderPos == b ? " <-" : "")));
|
||||
WriteLog( ( OrderPos == b ? ">" : " " ) + (std::to_string(b) + ": " + Order2Str(OrderList[b])));
|
||||
if (b) // z wyjątkiem pierwszej pozycji
|
||||
if (OrderList[b] == Wait_for_orders) // jeśli końcowa komenda
|
||||
break; // dalej nie trzeba
|
||||
@@ -6848,10 +6898,8 @@ void TController::OrdersInit(double fVel)
|
||||
SetVelocity(0, 0, stopSleep); // prędkość w przedziale (0;1) oznacza, że ma stać
|
||||
}
|
||||
#if LOGORDERS
|
||||
WriteLog("--> OrdersInit");
|
||||
OrdersDump( "OrdersInit", DebugModeFlag ); // wypisanie kontrolne tabelki rozkazów
|
||||
#endif
|
||||
if (DebugModeFlag) // normalnie nie ma po co tego wypisywać
|
||||
OrdersDump(); // wypisanie kontrolne tabelki rozkazów
|
||||
// McZapkie! - zeby w ogole AI ruszyl to musi wykonac powyzsze rozkazy
|
||||
// Ale mozna by je zapodac ze scenerii
|
||||
};
|
||||
|
||||
5
Driver.h
5
Driver.h
@@ -240,7 +240,7 @@ private:
|
||||
bool IncBrakeEIM();
|
||||
bool DecBrakeEIM();
|
||||
bool IncSpeedEIM();
|
||||
bool DecSpeedEIM();
|
||||
bool DecSpeedEIM( int const Amount = 1 );
|
||||
void BrakeLevelSet( double b );
|
||||
bool BrakeLevelAdd( double b );
|
||||
void SpeedSet();
|
||||
@@ -370,7 +370,7 @@ private:
|
||||
void OrderCheck();
|
||||
void OrdersInit( double fVel );
|
||||
void OrdersClear();
|
||||
void OrdersDump();
|
||||
void OrdersDump( std::string const Neworder, bool const Verbose = true );
|
||||
std::string Order2Str( TOrders Order ) const;
|
||||
// members
|
||||
std::string m_assignment;
|
||||
@@ -484,6 +484,7 @@ private:
|
||||
bool IsAnyMotorOverloadRelayOpen{ false }; // state of motor overload relays in all vehicles under control
|
||||
bool IsAnyGroundRelayOpen{ false };
|
||||
bool IsAnyCompressorEnabled{ false };
|
||||
bool IsAnyCouplerStretched{ false }; // whether there's a coupler in the consist stretched above limit
|
||||
|
||||
// logs
|
||||
// methods
|
||||
|
||||
50
DynObj.cpp
50
DynObj.cpp
@@ -1552,7 +1552,7 @@ TDynamicObject::uncouple( int const Side ) {
|
||||
}
|
||||
|
||||
bool
|
||||
TDynamicObject::attach_coupler_adapter( int const Side ) {
|
||||
TDynamicObject::attach_coupler_adapter( int const Side, bool const Enforce ) {
|
||||
|
||||
auto &coupler { MoverParameters->Couplers[ Side ] };
|
||||
// sanity check(s)
|
||||
@@ -1572,7 +1572,8 @@ TDynamicObject::attach_coupler_adapter( int const Side ) {
|
||||
// explicit coupler adapter definition overrides default parameters
|
||||
adapterdata = neighbour->m_coupleradapter;
|
||||
}
|
||||
if( MoverParameters->Neighbours[ Side ].distance - adapterdata.position.x < 0.5 ) {
|
||||
if( ( MoverParameters->Neighbours[ Side ].distance - adapterdata.position.x < 0.5 )
|
||||
&& ( false == Enforce ) ) {
|
||||
// arbitrary amount of free room required to install the adapter
|
||||
// NOTE: this also covers cases with established physical connection
|
||||
return false;
|
||||
@@ -2483,13 +2484,51 @@ void TDynamicObject::Move(double fDistance)
|
||||
}
|
||||
};
|
||||
|
||||
void TDynamicObject::AttachPrev(TDynamicObject *Object, int iType)
|
||||
void TDynamicObject::AttachNext(TDynamicObject *Object, int iType)
|
||||
{ // Ra: doczepia Object na końcu składu (nazwa funkcji może być myląca)
|
||||
// Ra: używane tylko przy wczytywaniu scenerii
|
||||
MoverParameters->Attach( iDirection, Object->iDirection ^ 1, Object->MoverParameters, iType, true, false );
|
||||
auto const vehicleend { iDirection };
|
||||
auto const othervehicleend { Object->iDirection ^ 1 };
|
||||
|
||||
MoverParameters->Attach( vehicleend, othervehicleend, Object->MoverParameters, iType, true, false );
|
||||
// update neighbour data for both affected vehicles
|
||||
update_neighbours();
|
||||
Object->update_neighbours();
|
||||
|
||||
// potentially attach automatic coupler adapter to allow the connection
|
||||
// HACK: we're doing it after establishin actual connection, as the method needs valid neighbour data
|
||||
auto &coupler { MoverParameters->Couplers[ vehicleend ] };
|
||||
auto &othercoupler { Object->MoverParameters->Couplers[ ( othervehicleend != 2 ? othervehicleend : coupler.ConnectedNr ) ] };
|
||||
|
||||
if( coupler.type() != othercoupler.type() ) {
|
||||
if( othercoupler.type() == TCouplerType::Automatic ) {
|
||||
// try to attach adapter to the vehicle
|
||||
attach_coupler_adapter(
|
||||
vehicleend,
|
||||
true );
|
||||
}
|
||||
else if( coupler.type() == TCouplerType::Automatic ) {
|
||||
// try to attach adapter to the other vehicle
|
||||
Object->attach_coupler_adapter(
|
||||
( othervehicleend != 2 ? othervehicleend : coupler.ConnectedNr ),
|
||||
true );
|
||||
}
|
||||
// update distance to neighbours on account of potentially attached adapter
|
||||
update_neighbours();
|
||||
Object->update_neighbours();
|
||||
}
|
||||
// potentially adjust vehicle position to avoid collision at the simulation start
|
||||
if( MoverParameters->Neighbours[ vehicleend ].distance > -0.001 ) { return; }
|
||||
|
||||
Object->Move( MoverParameters->Neighbours[ vehicleend ].distance * Object->DirectionGet() );
|
||||
// HACK: manually update vehicle position as it's used by neighbour distance update we do next
|
||||
Object->MoverParameters->Loc = {
|
||||
-Object->vPosition.x,
|
||||
Object->vPosition.z,
|
||||
Object->vPosition.y };
|
||||
// update neighbour distance data after moving our vehicle
|
||||
update_neighbours();
|
||||
Object->update_neighbours();
|
||||
}
|
||||
|
||||
bool TDynamicObject::UpdateForce(double dt)
|
||||
@@ -3063,7 +3102,8 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
if (((MoverParameters->ShuntMode) && (Frj < 0.0015 * masa)) ||
|
||||
(MoverParameters->V * MoverParameters->DirAbsolute < -0.2))
|
||||
{
|
||||
Fzad = std::max(MoverParameters->StopBrakeDecc * masa, Fzad);
|
||||
auto const sbd { ( ( MoverParameters->SpringBrake.IsActive && MoverParameters->ReleaseParkingBySpringBrake ) ? 0.0 : MoverParameters->StopBrakeDecc ) };
|
||||
Fzad = std::max( Fzad, sbd * masa );
|
||||
}
|
||||
if ((Fzad > 1) && (!MEDLogFile.is_open()) && (MoverParameters->Vel > 1))
|
||||
{
|
||||
|
||||
4
DynObj.h
4
DynObj.h
@@ -564,7 +564,7 @@ private:
|
||||
int init_sections( TModel3d const *Model, std::string const &Nameprefix, bool const Overrideselfillum );
|
||||
bool init_destination( TModel3d *Model );
|
||||
void create_controller( std::string const Type, bool const Trainset );
|
||||
void AttachPrev(TDynamicObject *Object, int iType = 1);
|
||||
void AttachNext(TDynamicObject *Object, int iType = 1);
|
||||
bool UpdateForce(double dt);
|
||||
// initiates load change by specified amounts, with a platform on specified side
|
||||
void LoadExchange( int const Disembark, int const Embark, int const Platform );
|
||||
@@ -660,7 +660,7 @@ private:
|
||||
|
||||
void couple( int const Side );
|
||||
int uncouple( int const Side );
|
||||
bool attach_coupler_adapter( int const Side );
|
||||
bool attach_coupler_adapter( int const Side, bool const Enforce = false );
|
||||
bool remove_coupler_adapter( int const Side );
|
||||
void RadioStop();
|
||||
void Damage(char flag);
|
||||
|
||||
@@ -121,12 +121,12 @@ static int const dtrain_axle = 64;
|
||||
static int const dtrain_out = 128; /*wykolejenie*/
|
||||
|
||||
/*wagi prawdopodobienstwa dla funkcji FuzzyLogic*/
|
||||
#define p_elengproblem (1.000000E-02)
|
||||
#define p_elengdamage (1.000000E-01)
|
||||
#define p_coupldmg (2.000000E-02)
|
||||
#define p_derail (1.000000E-03)
|
||||
#define p_accn (1.000000E-01)
|
||||
#define p_slippdmg (1.000000E-03)
|
||||
#define p_elengproblem (1e-02)
|
||||
#define p_elengdamage (1e-01)
|
||||
#define p_coupldmg (2e-03)
|
||||
#define p_derail (1e-03)
|
||||
#define p_accn (1e-01)
|
||||
#define p_slippdmg (1e-03)
|
||||
|
||||
/*typ sprzegu*/
|
||||
static int const ctrain_virtual = 0; //gdy pojazdy na tym samym torze się widzą wzajemnie
|
||||
@@ -759,6 +759,8 @@ struct speed_control {
|
||||
double FactorIpos = 0.0;
|
||||
double FactorIneg = 0.0;
|
||||
double BrakeInterventionVel = 30.0;
|
||||
double PowerUpSpeed = 1000;
|
||||
double PowerDownSpeed = 1000;
|
||||
};
|
||||
|
||||
class TMoverParameters
|
||||
@@ -1127,6 +1129,7 @@ public:
|
||||
int ScndInMain{ 0 }; /*zaleznosc bocznika od nastawnika*/
|
||||
bool MBrake = false; /*Czy jest hamulec reczny*/
|
||||
double StopBrakeDecc = 0.0;
|
||||
bool ReleaseParkingBySpringBrake { false };
|
||||
TSecuritySystem SecuritySystem;
|
||||
int EmergencyBrakeWarningSignal{ 0 }; // combined with basic WarningSignal when manual emergency brake is active
|
||||
TUniversalCtrlTable UniCtrlList; /*lista pozycji uniwersalnego nastawnika*/
|
||||
@@ -1602,7 +1605,7 @@ public:
|
||||
// obsługa sprzęgów
|
||||
static double CouplerDist( TMoverParameters const *Left, TMoverParameters const *Right );
|
||||
static double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2);
|
||||
bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false, bool Audible = true);
|
||||
bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Enforce = false, bool Audible = true);
|
||||
int DettachStatus(int ConnectNo);
|
||||
bool Dettach(int ConnectNo);
|
||||
void damage_coupler( int const End );
|
||||
@@ -1645,8 +1648,8 @@ public:
|
||||
bool RunCommand( std::string Command, double CValue1, double CValue2, int const Couplertype = ctrain_controll );
|
||||
bool RunInternalCommand();
|
||||
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation);
|
||||
bool CabActivisation( bool const Force = false );
|
||||
bool CabDeactivisation( bool const Force = false );
|
||||
bool CabActivisation( bool const Enforce = false );
|
||||
bool CabDeactivisation( bool const Enforce = false );
|
||||
|
||||
/*! funkcje zwiekszajace/zmniejszajace nastawniki*/
|
||||
/*! glowny nastawnik:*/
|
||||
|
||||
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "Globals.h"
|
||||
#include "Logs.h"
|
||||
#include "parser.h"
|
||||
#include "simulation.h"
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Ra: tu należy przenosić funcje z mover.pas, które nie są z niego wywoływane.
|
||||
@@ -426,7 +427,7 @@ double TMoverParameters::CouplerDist(TMoverParameters const *Left, TMoverParamet
|
||||
Left->Dim, Right->Dim); // odległość pomiędzy sprzęgami (kula!)
|
||||
};
|
||||
|
||||
bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced, bool Audible)
|
||||
bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Enforce, bool Audible)
|
||||
{ //łączenie do swojego sprzęgu (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr)
|
||||
// Ra: zwykle wykonywane dwukrotnie, dla każdego pojazdu oddzielnie
|
||||
// Ra: trzeba by odróżnić wymóg dociśnięcia od uszkodzenia sprzęgu przy podczepianiu AI do składu
|
||||
@@ -441,7 +442,7 @@ bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *
|
||||
auto const distance { CouplerDist( this, ConnectTo ) - ( coupler.adapter_length + othercoupler.adapter_length ) };
|
||||
|
||||
auto const couplercheck {
|
||||
( Forced )
|
||||
( Enforce )
|
||||
|| ( ( distance <= dEpsilon )
|
||||
&& ( coupler.type() != TCouplerType::NoCoupler )
|
||||
&& ( coupler.type() == othercoupler.type() ) ) };
|
||||
@@ -1044,12 +1045,14 @@ void TMoverParameters::CollisionDetect(int const End, double const dt)
|
||||
}
|
||||
}
|
||||
|
||||
if( ( coupler.Dist < 0 )
|
||||
if( ( -coupler.Dist >= coupler.DmaxB )
|
||||
&& ( FuzzyLogic( std::abs( CCF ), 5.0 * ( coupler.FmaxC + 1.0 ), p_coupldmg ) ) ) {
|
||||
// small chance to smash the coupler if it's hit with excessive force
|
||||
damage_coupler( End );
|
||||
}
|
||||
|
||||
if( ( coupler.CouplingFlag == coupling::faux
|
||||
|| ( true == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) ) { // HACK: limit excessive speed derailment checks to vehicles which aren't part of the same consist
|
||||
auto const safevelocitylimit { 15.0 };
|
||||
auto const velocitydifference {
|
||||
glm::length(
|
||||
@@ -1071,6 +1074,7 @@ void TMoverParameters::CollisionDetect(int const End, double const dt)
|
||||
othervehicle->derail( 5 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adjust velocity and acceleration of affected vehicles
|
||||
if( false == TestFlag( DamageFlag, dtrain_out ) ) {
|
||||
@@ -2291,6 +2295,9 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed)
|
||||
// nie ma sterowania
|
||||
OK = false;
|
||||
}
|
||||
else if( CtrlSpeed == 0 ) {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TBD, TODO: replace with mainctrlpowerpos() check?
|
||||
@@ -2324,7 +2331,7 @@ bool TMoverParameters::DecMainCtrl(int CtrlSpeed)
|
||||
}
|
||||
}
|
||||
else if (CtrlSpeed > 1)
|
||||
OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1);
|
||||
OK = (DecMainCtrl(1) && DecMainCtrl(CtrlSpeed - 1)); // CtrlSpeed-1);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2569,11 +2576,11 @@ bool TMoverParameters::DecScndCtrl(int CtrlSpeed)
|
||||
// Q: 20160710
|
||||
// załączenie rozrządu
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::CabActivisation( bool const Force )
|
||||
bool TMoverParameters::CabActivisation( bool const Enforce )
|
||||
{
|
||||
bool OK = false;
|
||||
|
||||
OK = Force || (CabActive == 0); // numer kabiny, z której jest sterowanie
|
||||
OK = Enforce || (CabActive == 0); // numer kabiny, z której jest sterowanie
|
||||
if (OK)
|
||||
{
|
||||
CabActive = CabOccupied; // sterowanie jest z kabiny z obsadą
|
||||
@@ -2588,11 +2595,11 @@ bool TMoverParameters::CabActivisation( bool const Force )
|
||||
// Q: 20160710
|
||||
// wyłączenie rozrządu
|
||||
// *************************************************************************************************
|
||||
bool TMoverParameters::CabDeactivisation( bool const Force )
|
||||
bool TMoverParameters::CabDeactivisation( bool const Enforce )
|
||||
{
|
||||
bool OK = false;
|
||||
|
||||
OK = Force || (CabActive == CabOccupied); // o ile obsada jest w kabinie ze sterowaniem
|
||||
OK = Enforce || (CabActive == CabOccupied); // o ile obsada jest w kabinie ze sterowaniem
|
||||
if (OK)
|
||||
{
|
||||
CabActive = 0;
|
||||
@@ -7065,6 +7072,7 @@ void TMoverParameters::CheckSpeedCtrl(double dt)
|
||||
}
|
||||
if ((EIMCtrlType >= 3)&&(UniCtrlList[MainCtrlPos].SpeedUp <= 0)) {
|
||||
accfactor = 0.0;
|
||||
eimicSpeedCtrl = 0;
|
||||
}
|
||||
}
|
||||
if (SpeedCtrlUnit.IsActive) {//speed control
|
||||
@@ -7079,7 +7087,7 @@ void TMoverParameters::CheckSpeedCtrl(double dt)
|
||||
bool retarder_not_work = (EngineType != TEngineType::DieselEngine) || (Vel < SpeedCtrlUnit.BrakeInterventionVel);
|
||||
if (eSCP < -1.0)
|
||||
{
|
||||
SpeedCtrlUnit.BrakeInterventionBraking = (eSCP < -1.1) && retarder_not_work;
|
||||
SpeedCtrlUnit.BrakeInterventionBraking = (eSCP < -1.1) && retarder_not_work && (eimicSpeedCtrl < -0.99 * SpeedCtrlUnit.DesiredPower);
|
||||
eSCP = -1.0;
|
||||
}
|
||||
SpeedCtrlUnit.BrakeInterventionUnbraking = (eSCP > 0.0) || (Vel == 0.0);
|
||||
@@ -7092,7 +7100,11 @@ void TMoverParameters::CheckSpeedCtrl(double dt)
|
||||
else {
|
||||
eimicSpeedCtrlIntegral = 0;
|
||||
}
|
||||
eimicSpeedCtrl = clamp(eimicSpeedCtrlIntegral + eSCP, -SpeedCtrlUnit.DesiredPower, accfactor);
|
||||
auto const DesiredeimicSpeedCtrl { clamp( eimicSpeedCtrlIntegral + eSCP, -SpeedCtrlUnit.DesiredPower, accfactor ) };
|
||||
eimicSpeedCtrl = clamp(
|
||||
DesiredeimicSpeedCtrl,
|
||||
eimicSpeedCtrl - SpeedCtrlUnit.PowerDownSpeed * dt,
|
||||
eimicSpeedCtrl + SpeedCtrlUnit.PowerUpSpeed * dt );
|
||||
if (Vel < SpeedCtrlUnit.FullPowerVelocity) {
|
||||
eimicSpeedCtrl = std::min(eimicSpeedCtrl, SpeedCtrlUnit.InitialPower);
|
||||
}
|
||||
@@ -10090,6 +10102,7 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
0;
|
||||
|
||||
extract_value( StopBrakeDecc, "SBD", line, "" );
|
||||
extract_value( ReleaseParkingBySpringBrake, "ReleaseParkingBySpringBrake", line, "" );
|
||||
|
||||
std::map<std::string, start_t> starts {
|
||||
{ "Disabled", start_t::disabled },
|
||||
@@ -10368,8 +10381,8 @@ void TMoverParameters::LoadFIZ_SpeedControl(std::string const &Line) {
|
||||
extract_value(SpeedCtrlUnit.FactorIpos, "kIpos", Line, "");
|
||||
extract_value(SpeedCtrlUnit.FactorIneg, "kIneg", Line, "");
|
||||
extract_value(SpeedCtrlUnit.BrakeInterventionVel, "BrakeIntMaxVel", Line, "");
|
||||
|
||||
|
||||
extract_value(SpeedCtrlUnit.PowerUpSpeed, "PowerUpSpeed", Line, "" );
|
||||
extract_value(SpeedCtrlUnit.PowerDownSpeed, "PowerDownSpeed", Line, "" );
|
||||
}
|
||||
|
||||
void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
|
||||
|
||||
@@ -199,7 +199,7 @@ auto python_taskqueue::init() -> bool {
|
||||
// release the lock, save the state for future use
|
||||
m_mainthread = PyEval_SaveThread();
|
||||
|
||||
WriteLog( "Python Interpreter setup complete" );
|
||||
WriteLog( "Python Interpreter: setup complete" );
|
||||
|
||||
// init workers
|
||||
for( auto &worker : m_workers ) {
|
||||
|
||||
@@ -689,7 +689,7 @@ state_serializer::deserialize_endtrainset( cParser &Input, scene::scratch_data &
|
||||
}
|
||||
if( vehicleindex > 0 ) {
|
||||
// from second vehicle on couple it with the previous one
|
||||
Scratchpad.trainset.vehicles[ vehicleindex - 1 ]->AttachPrev(
|
||||
Scratchpad.trainset.vehicles[ vehicleindex - 1 ]->AttachNext(
|
||||
vehicle,
|
||||
Scratchpad.trainset.couplings[ vehicleindex - 1 ] );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user