16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-23 07:29:19 +02:00

Merge branch 'gfx-work' into sim

This commit is contained in:
milek7
2019-07-13 01:47:36 +02:00
34 changed files with 1304 additions and 688 deletions

View File

@@ -1390,6 +1390,12 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
fVelDes = v; fVelDes = v;
} }
} }
if( ( true == TestFlag( sSpeedTable[ i ].iFlags, spEnd ) )
&& ( mvOccupied->CategoryFlag & 1 ) ) {
// if the railway track ends here set the velnext accordingly as well
// TODO: test this with turntables and such
fNext = 0.0;
}
} }
else if (sSpeedTable[i].iFlags & spTrack) // jeśli tor else if (sSpeedTable[i].iFlags & spTrack) // jeśli tor
{ // tor ogranicza prędkość, dopóki cały skład nie przejedzie, { // tor ogranicza prędkość, dopóki cały skład nie przejedzie,
@@ -1401,12 +1407,6 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
// ograniczenie aktualnej prędkości aż do wyjechania za ograniczenie // ograniczenie aktualnej prędkości aż do wyjechania za ograniczenie
fVelDes = v; fVelDes = v;
} }
if( ( sSpeedTable[ i ].iFlags & spEnd )
&& ( mvOccupied->CategoryFlag & 1 ) ) {
// if the railway track ends here set the velnext accordingly as well
// TODO: test this with turntables and such
fNext = 0.0;
}
// if (v==0.0) fAcc=-0.9; //hamowanie jeśli stop // if (v==0.0) fAcc=-0.9; //hamowanie jeśli stop
continue; // i tyle wystarczy continue; // i tyle wystarczy
} }
@@ -2129,7 +2129,10 @@ bool TController::CheckVehicles(TOrders user)
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly // NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
p->MoverParameters->BatterySwitch( true ); p->MoverParameters->BatterySwitch( true );
} }
// enable heating and converter in carriages with can be heated }
// enable heating and converter in carriages with can be heated
// NOTE: don't touch the controlled vehicle, let the user/ai handle it explicitly
if( p->MoverParameters != mvControlling ) {
if( p->MoverParameters->HeatingPower > 0 ) { if( p->MoverParameters->HeatingPower > 0 ) {
p->MoverParameters->HeatingAllow = true; p->MoverParameters->HeatingAllow = true;
p->MoverParameters->ConverterSwitch( true, range_t::local ); p->MoverParameters->ConverterSwitch( true, range_t::local );
@@ -2264,6 +2267,12 @@ bool TController::CheckVehicles(TOrders user)
// zmiana czoła przez manewry // zmiana czoła przez manewry
iDrivigFlags &= ~movePushPull; iDrivigFlags &= ~movePushPull;
} }
if( ( user == Connect )
|| ( user == Disconnect ) ) {
// HACK: force route table update on consist change, new consist length means distances to points of interest are now wrong
iTableDirection = 0;
}
} // blok wykonywany, gdy aktywnie prowadzi } // blok wykonywany, gdy aktywnie prowadzi
return true; return true;
} }
@@ -2452,7 +2461,7 @@ bool TController::PrepareEngine()
mvOccupied->PantRear( true ); mvOccupied->PantRear( true );
if (mvControlling->PantPress < 4.2) { if (mvControlling->PantPress < 4.2) {
// załączenie małej sprężarki // załączenie małej sprężarki
if( mvControlling->TrainType != dt_EZT ) { if( false == mvControlling->PantAutoValve ) {
// odłączenie zbiornika głównego, bo z nim nie da rady napompować // odłączenie zbiornika głównego, bo z nim nie da rady napompować
mvControlling->bPantKurek3 = false; mvControlling->bPantKurek3 = false;
} }
@@ -2525,14 +2534,14 @@ bool TController::PrepareEngine()
} }
else { else {
OK = ( OrderDirectionChange( iDirection, mvOccupied ) == -1 ); OK = ( OrderDirectionChange( iDirection, mvOccupied ) == -1 );
mvOccupied->ConverterSwitch( true ); mvControlling->ConverterSwitch( true );
// w EN57 sprężarka w ra jest zasilana z silnikowego // w EN57 sprężarka w ra jest zasilana z silnikowego
mvOccupied->CompressorSwitch( true ); mvControlling->CompressorSwitch( true );
// enable motor blowers // enable motor blowers
mvOccupied->MotorBlowersSwitchOff( false, end::front ); mvControlling->MotorBlowersSwitchOff( false, end::front );
mvOccupied->MotorBlowersSwitch( true, end::front ); mvControlling->MotorBlowersSwitch( true, end::front );
mvOccupied->MotorBlowersSwitchOff( false, end::rear ); mvControlling->MotorBlowersSwitchOff( false, end::rear );
mvOccupied->MotorBlowersSwitch( true, end::rear ); mvControlling->MotorBlowersSwitch( true, end::rear );
// enable train brake if it's off // enable train brake if it's off
if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) { if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) ); mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) );
@@ -2546,6 +2555,14 @@ bool TController::PrepareEngine()
if( lookup != brakepositions.end() ) { if( lookup != brakepositions.end() ) {
BrakeLevelSet( lookup->second ); // GBH BrakeLevelSet( lookup->second ); // GBH
} }
// enable train heating
// HACK: to account for su-45/-46 shortcomings diesel-powered engines only activate heating in cold conditions
// TODO: take instead into account presence of converters in attached cars, once said presence is possible to specify
mvControlling->HeatingAllow = (
( ( mvControlling->EngineType == TEngineType::DieselElectric )
|| ( mvControlling->EngineType == TEngineType::DieselEngine ) ) ?
( Global.AirTemperature < 10 ) :
true );
} }
} }
else else
@@ -2628,7 +2645,9 @@ bool TController::ReleaseEngine() {
mvOccupied->OperateDoors( side::left, false ); mvOccupied->OperateDoors( side::left, false );
if( true == mvControlling->Mains ) { if( true == mvControlling->Mains ) {
mvControlling->CompressorSwitch( false ); // heating
mvControlling->HeatingAllow = false;
// devices
mvControlling->ConverterSwitch( false ); mvControlling->ConverterSwitch( false );
// line breaker/engine // line breaker/engine
OK = mvControlling->MainSwitch( false ); OK = mvControlling->MainSwitch( false );
@@ -3123,6 +3142,14 @@ bool TController::IncSpeed()
{ // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga zerowania kierunku) { // dla 2Ls150 można zmienić tryb pracy, jeśli jest w liniowym i nie daje rady (wymaga zerowania kierunku)
// mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0); // mvControlling->ShuntMode=(OrderList[OrderPos]&Shunt)||(fMass>224000.0);
} }
if (mvControlling->EIMCtrlType > 0) {
if (true == Ready)
{
DizelPercentage = (mvControlling->Vel > mvControlling->dizel_minVelfullengage ? 100 : 1);
}
break;
}
else
if( true == Ready ) { if( true == Ready ) {
if( ( mvControlling->Vel > mvControlling->dizel_minVelfullengage ) if( ( mvControlling->Vel > mvControlling->dizel_minVelfullengage )
&& ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn > 0 ) ) { && ( mvControlling->RList[ mvControlling->MainCtrlPos ].Mn > 0 ) ) {
@@ -3185,6 +3212,12 @@ bool TController::DecSpeed(bool force)
mvControlling->DecMainCtrl(3 + 3 * floor(0.5 + fabs(AccDesired))); mvControlling->DecMainCtrl(3 + 3 * floor(0.5 + fabs(AccDesired)));
break; break;
case TEngineType::DieselEngine: case TEngineType::DieselEngine:
if (mvControlling->EIMCtrlType > 0)
{
DizelPercentage = 0;
break;
}
if ((mvControlling->Vel > mvControlling->dizel_minVelfullengage)) if ((mvControlling->Vel > mvControlling->dizel_minVelfullengage))
{ {
if (mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0) if (mvControlling->RList[mvControlling->MainCtrlPos].Mn > 0)
@@ -3508,6 +3541,64 @@ void TController::SetTimeControllers()
} }
} }
//5. Check Main Controller in Dizels //5. Check Main Controller in Dizels
//5.1. Digital controller in DMUs with hydro
if ((mvControlling->EngineType == TEngineType::DieselEngine) && (mvControlling->EIMCtrlType == 3))
{
DizelPercentage_Speed = DizelPercentage; //wstepnie procenty
auto MinVel{ std::min(mvControlling->hydro_TC_LockupSpeed, mvControlling->Vmax / 6) }; //minimal velocity
if (VelDesired > MinVel) //more power for faster ride
{
auto const Factor{ 10 * (mvControlling->Vmax) / (mvControlling->Vmax + 3 * mvControlling->Vel) };
auto DesiredPercentage{ clamp(
(VelDesired > mvControlling->Vel ?
(VelDesired - mvControlling->Vel) / Factor :
0),
0.0, 1.0) }; //correction for reaching desired velocity
if ((VelDesired < 0.5 * mvControlling->Vmax) //low velocity and reaching desired
&& (VelDesired - mvControlling->Vel < 10)) {
DesiredPercentage = std::min(DesiredPercentage, 0.75);
}
DizelPercentage_Speed = std::round(DesiredPercentage * DizelPercentage);
}
else
{
DizelPercentage_Speed = std::min(DizelPercentage, mvControlling->Vel < 0.99 * VelDesired ? 1 : 0);
}
auto const DizelActualPercentage { int(100.4 * mvControlling->eimic_real) };
auto const PosInc { mvControlling->MainCtrlPosNo };
auto PosDec { 0 };
for( int i = PosInc; i >= 0; --i ) {
if( ( mvControlling->UniCtrlList[ i ].SetCtrlVal <= 0 )
&& ( mvControlling->UniCtrlList[ i ].SpeedDown > 0.01 ) ) {
PosDec = i;
break;
}
}
if( std::abs( DizelPercentage_Speed - DizelActualPercentage ) > ( DizelPercentage > 1 ? 0 : 0 ) ) {
if( ( PosDec > 0 )
&& ( ( DizelActualPercentage - DizelPercentage_Speed > 50 )
|| ( ( DizelPercentage_Speed == 0 )
&& ( DizelActualPercentage > 10 ) ) ) ) {
//one position earlier should be fast decreasing
PosDec -= 1;
}
auto const DesiredPos { (
DizelPercentage_Speed > DizelActualPercentage ?
PosInc :
PosDec ) };
while( mvControlling->MainCtrlPos > DesiredPos ) { mvControlling->DecMainCtrl( 1 ); }
while( mvControlling->MainCtrlPos < DesiredPos ) { mvControlling->IncMainCtrl( 1 ); }
}
if (BrakeCtrlPosition < 0.1) //jesli nie hamuje
mvOccupied->BrakeLevelSet(mvControlling->UniCtrlList[mvControlling->MainCtrlPos].mode); //zeby nie bruzdzilo machanie zespolonym
}
else
//5.2. Analog direct controller
if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->Vmax>30)) if ((mvControlling->EngineType == TEngineType::DieselEngine)&&(mvControlling->Vmax>30))
{ {
int MaxPos = mvControlling->MainCtrlPosNo; int MaxPos = mvControlling->MainCtrlPosNo;
@@ -3567,6 +3658,28 @@ void TController::CheckTimeControllers()
mvOccupied->ScndCtrlPos = 2; mvOccupied->ScndCtrlPos = 2;
} }
} }
//5. Check Main Controller in Dizels
//5.1. Digital controller in DMUs with hydro
if ((mvControlling->EngineType == TEngineType::DieselEngine) && (mvControlling->EIMCtrlType == 3))
{
int DizelActualPercentage = 100.4 * mvControlling->eimic_real;
int NeutralPos = mvControlling->MainCtrlPosNo - 1; //przedostatnia powinna wstrzymywać - hipoteza robocza
for (int i = mvControlling->MainCtrlPosNo; i >= 0; i--)
if ((mvControlling->UniCtrlList[i].SetCtrlVal <= 0) && (mvControlling->UniCtrlList[i].SpeedDown < 0.01)) //niby zero, ale nie zmniejsza procentów
{
NeutralPos = i;
break;
}
if (BrakeCtrlPosition < 0.1) //jesli nie hamuje
{
if ((DizelActualPercentage >= DizelPercentage_Speed) && (mvControlling->MainCtrlPos > NeutralPos))
while (mvControlling->MainCtrlPos > NeutralPos) mvControlling->DecMainCtrl(1);
if ((DizelActualPercentage <= DizelPercentage_Speed) && (mvControlling->MainCtrlPos < NeutralPos))
while (mvControlling->MainCtrlPos < NeutralPos) mvControlling->IncMainCtrl(1);
mvOccupied->BrakeLevelSet(mvControlling->UniCtrlList[mvControlling->MainCtrlPos].mode); //zeby nie bruzdzilo machanie zespolonym
}
}
}; };
// otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT // otwieranie/zamykanie drzwi w składzie albo (tylko AI) EZT
@@ -4748,7 +4861,7 @@ TController::UpdateSituation(double dt) {
iCoupler = 0; // dalsza jazda manewrowa już bez łączenia iCoupler = 0; // dalsza jazda manewrowa już bez łączenia
iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania iDrivigFlags &= ~moveConnect; // zdjęcie flagi doczepiania
SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie SetVelocity( 0, 0, stopJoin ); // wyłączyć przyspieszanie
CheckVehicles(); // sprawdzić światła nowego składu CheckVehicles( Connect ); // sprawdzić światła nowego składu
JumpToNextOrder(); // wykonanie następnej komendy JumpToNextOrder(); // wykonanie następnej komendy
} }
} }
@@ -5115,6 +5228,7 @@ TController::UpdateSituation(double dt) {
// tylko jeśli odepnie // tylko jeśli odepnie
WriteLog( mvOccupied->Name + " odczepiony." ); WriteLog( mvOccupied->Name + " odczepiony." );
iVehicleCount = -2; iVehicleCount = -2;
CheckVehicles( Disconnect ); // update trainset state
} // a jak nie, to dociskać dalej } // a jak nie, to dociskać dalej
} }
if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress)) if ((mvOccupied->Vel < 0.01) && !(iDrivigFlags & movePress))
@@ -5122,6 +5236,7 @@ TController::UpdateSituation(double dt) {
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach // za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
// powino zostać wyłączone) // powino zostać wyłączone)
// WriteLog("Zahamowanie składu"); // WriteLog("Zahamowanie składu");
AccDesired = std::min( AccDesired, -0.9 ); // HACK: make sure the ai doesn't try to release the brakes to accelerate
if( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) { if( mvOccupied->BrakeSystem == TBrakeSystem::ElectroPneumatic ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_EPB ) ); mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_EPB ) );
} }
@@ -5369,7 +5484,8 @@ TController::UpdateSituation(double dt) {
exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() ); exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() );
vehicle = vehicle->Next(); vehicle = vehicle->Next();
} }
if( exchangetime > 0 ) { if( ( exchangetime > 0 )
|| ( mvOccupied->Vel > 2.0 ) ) { // HACK: force timer reset if the load exchange is cancelled due to departure
WaitingSet( exchangetime ); WaitingSet( exchangetime );
} }
} }

View File

@@ -265,6 +265,8 @@ public:
int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami
int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
int DizelPercentage = 0; // oczekiwane procenty jazdy/hamowania szynobusem
int DizelPercentage_Speed = 0; // oczekiwane procenty jazdy/hamowania szynobusem w związku z osiąganiem VelDesired
private: private:
bool Psyche = false; bool Psyche = false;
int HelperState = 0; //stan pomocnika maszynisty int HelperState = 0; //stan pomocnika maszynisty

View File

@@ -2720,10 +2720,11 @@ bool TDynamicObject::Update(double dt, double dt1)
if (v == 0.0) { if (v == 0.0) {
v = MoverParameters->PantFrontVolt; v = MoverParameters->PantFrontVolt;
if( v == 0.0 ) { if( v == 0.0 ) {
if( MoverParameters->TrainType & ( dt_EZT | dt_ET40 | dt_ET41 | dt_ET42 ) ) { // if( MoverParameters->TrainType & ( dt_EZT | dt_ET40 | dt_ET41 | dt_ET42 ) ) {
// dwuczłony mogą mieć sprzęg WN // dwuczłony mogą mieć sprzęg WN
// NOTE: condition disabled, other vehicles types can have power cables as well
v = MoverParameters->GetTrainsetVoltage(); // ostatnia szansa v = MoverParameters->GetTrainsetVoltage(); // ostatnia szansa
} // }
} }
} }
if (v != 0.0) if (v != 0.0)
@@ -2776,7 +2777,14 @@ bool TDynamicObject::Update(double dt, double dt1)
if (Mechanik) if (Mechanik)
{ // Ra 2F3F: do Driver.cpp to przenieść? { // Ra 2F3F: do Driver.cpp to przenieść?
MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG MoverParameters->EqvtPipePress = GetEPP(); // srednie cisnienie w PG
if( ( Mechanik->Primary() ) if ((Mechanik->Primary())
&& (MoverParameters->EngineType == TEngineType::DieselEngine)
&& (MoverParameters->EIMCtrlType > 0)) {
MoverParameters->CheckEIMIC(dt1);
MoverParameters->eimic_real = MoverParameters->eimic;
MoverParameters->SendCtrlToNext("EIMIC", MoverParameters->eimic, MoverParameters->CabNo);
}
if( ( Mechanik->Primary() )
&& ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) { && ( MoverParameters->EngineType == TEngineType::ElectricInductionMotor ) ) {
// jesli glowny i z asynchronami, to niech steruje hamulcem i napedem lacznie dla calego pociagu/ezt // jesli glowny i z asynchronami, to niech steruje hamulcem i napedem lacznie dla calego pociagu/ezt
auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0); auto const kier = (DirectionGet() * MoverParameters->ActiveCab > 0);
@@ -5828,23 +5836,28 @@ TDynamicObject::LoadMMediaFile_mdload( std::string const &Name ) const {
TModel3d *loadmodel { nullptr }; TModel3d *loadmodel { nullptr };
// check if we don't have model override for this load type // check if we don't have model override for this load type
auto const lookup { LoadModelOverrides.find( Name ) }; {
if( lookup != LoadModelOverrides.end() ) { auto const lookup { LoadModelOverrides.find( Name ) };
loadmodel = TModelsManager::GetModel( asBaseDir + lookup->second, true ); if( lookup != LoadModelOverrides.end() ) {
// if the override was succesfully loaded call it a day loadmodel = TModelsManager::GetModel( asBaseDir + lookup->second, true );
if( loadmodel != nullptr ) { return loadmodel; } // if the override was succesfully loaded call it a day
if( loadmodel != nullptr ) { return loadmodel; }
}
} }
// regular routine if there's no override or it couldn't be loaded // regular routine if there's no override or it couldn't be loaded
// try first specialized version of the load model, vehiclename_loadname // try first specialized version of the load model, vehiclename_loadname
auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + Name }; {
if( ( true == FileExists( specializedloadfilename + ".e3d" ) ) auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + Name };
|| ( true == FileExists( specializedloadfilename + ".t3d" ) ) ) { loadmodel = TModelsManager::GetModel( specializedloadfilename, true, false );
loadmodel = TModelsManager::GetModel( specializedloadfilename, true ); if( loadmodel != nullptr ) { return loadmodel; }
} }
if( loadmodel == nullptr ) { // try generic version of the load model next, loadname
// if this fails, try generic load model {
loadmodel = TModelsManager::GetModel( asBaseDir + Name, true ); auto const genericloadfilename { asBaseDir + Name };
loadmodel = TModelsManager::GetModel( genericloadfilename, true, false );
if( loadmodel != nullptr ) { return loadmodel; }
} }
// if we're still here, give up
return loadmodel; return loadmodel;
} }
@@ -6689,7 +6702,7 @@ TDynamicObject::powertrain_sounds::render( TMoverParameters const &Vehicle, doub
// youBy - przenioslem, bo diesel tez moze miec turbo // youBy - przenioslem, bo diesel tez moze miec turbo
if( Vehicle.TurboTest > 0 ) { if( Vehicle.TurboTest > 0 ) {
// udawanie turbo: // udawanie turbo:
auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 0 }; auto const pitch_diesel { Vehicle.EngineType == TEngineType::DieselEngine ? Vehicle.enrot / Vehicle.dizel_nmax : 1 };
auto const goalpitch { std::max( 0.025, ( engine_volume * pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) }; auto const goalpitch { std::max( 0.025, ( engine_volume * pitch_diesel + engine_turbo.m_frequencyoffset ) * engine_turbo.m_frequencyfactor ) };
auto const goalvolume { ( auto const goalvolume { (
( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ? ( ( Vehicle.MainCtrlPos >= Vehicle.TurboTest ) && ( Vehicle.enrot > 0.1 ) ) ?

View File

@@ -59,12 +59,25 @@ bool TEventLauncher::Load(cParser *parser)
dRadius *= dRadius; // do kwadratu, pod warunkiem, że nie jest ujemne dRadius *= dRadius; // do kwadratu, pod warunkiem, że nie jest ujemne
parser->getTokens(); // klawisz sterujący parser->getTokens(); // klawisz sterujący
*parser >> token; *parser >> token;
if (token != "none") if (token != "none") {
{
if( token.size() == 1 ) if( token.size() == 1 ) {
// single char, assigned activation key
iKey = vk_to_glfw_key( token[ 0 ] ); iKey = vk_to_glfw_key( token[ 0 ] );
else }
iKey = vk_to_glfw_key(stol_def( token, 0 )); // a jak więcej, to jakby numer klawisza jest else {
// this launcher may be activated by radio message
std::map<std::string, int> messages {
{ "radio_call1", radio_message::call1 },
{ "radio_call3", radio_message::call3 }
};
auto lookup = messages.find( token );
iKey = (
lookup != messages.end() ?
lookup->second :
// a jak więcej, to jakby numer klawisza jest
vk_to_glfw_key( stol_def( token, 0 ) ) );
}
} }
parser->getTokens(); parser->getTokens();
*parser >> DeltaTime; *parser >> DeltaTime;
@@ -139,6 +152,8 @@ bool TEventLauncher::Load(cParser *parser)
} }
bool TEventLauncher::check_activation_key() { bool TEventLauncher::check_activation_key() {
if (iKey <= 0)
return false;
char key = iKey & 0xff; char key = iKey & 0xff;
@@ -146,9 +161,9 @@ bool TEventLauncher::check_activation_key() {
char modifier = iKey >> 8; char modifier = iKey >> 8;
if (modifier & GLFW_MOD_SHIFT) if (modifier & GLFW_MOD_SHIFT)
result |= Global.shiftState; result &= Global.shiftState;
if (modifier & GLFW_MOD_CONTROL) if (modifier & GLFW_MOD_CONTROL)
result |= Global.ctrlState; result &= Global.ctrlState;
return result; return result;
} }
@@ -213,6 +228,11 @@ bool TEventLauncher::IsGlobal() const {
&& ( dRadius < 0.0 ) ); // bez ograniczenia zasięgu && ( dRadius < 0.0 ) ); // bez ograniczenia zasięgu
} }
bool TEventLauncher::IsRadioActivated() const {
return ( iKey < 0 );
}
// radius() subclass details, calculates node's bounding radius // radius() subclass details, calculates node's bounding radius
float float
TEventLauncher::radius_() { TEventLauncher::radius_() {

View File

@@ -14,6 +14,12 @@ http://mozilla.org/MPL/2.0/.
#include "Classes.h" #include "Classes.h"
#include "scenenode.h" #include "scenenode.h"
// radio-transmitted event launch messages
enum radio_message {
call3 = -3,
call1 = -1
};
class TEventLauncher : public scene::basic_node { class TEventLauncher : public scene::basic_node {
public: public:
@@ -28,7 +34,11 @@ public:
bool check_activation(); bool check_activation();
// checks conditions associated with the event. returns: true if the conditions are met // checks conditions associated with the event. returns: true if the conditions are met
bool check_conditions(); bool check_conditions();
inline
auto key() const {
return iKey; }
bool IsGlobal() const; bool IsGlobal() const;
bool IsRadioActivated() const;
// members // members
std::string asEvent1Name; std::string asEvent1Name;
std::string asEvent2Name; std::string asEvent2Name;

View File

@@ -1034,7 +1034,7 @@ logvalues_event::export_as_text_( std::ostream &Output ) const {
void void
multi_event::init() { multi_event::init() {
auto const conditiontchecksmemcell { m_conditions.flags & ( flags::text | flags::value_1 | flags::value_2 ) }; auto const conditiontchecksmemcell { ( m_conditions.flags & ( flags::text | flags::value_1 | flags::value_2 ) ) != 0 };
// not all multi-events have memory cell checks, for the ones which don't we can keep quiet about it // not all multi-events have memory cell checks, for the ones which don't we can keep quiet about it
init_targets( simulation::Memory, "memory cell", conditiontchecksmemcell ); init_targets( simulation::Memory, "memory cell", conditiontchecksmemcell );
if( m_ignored ) { if( m_ignored ) {
@@ -1964,6 +1964,22 @@ event_manager::queue( TEventLauncher *Launcher ) {
m_launcherqueue.emplace_back( Launcher ); m_launcherqueue.emplace_back( Launcher );
} }
// inserts in the event query events assigned to event launchers capable of receiving specified radio message sent from specified location
void
event_manager::queue_receivers( radio_message const Message, glm::dvec3 const &Location ) {
for( auto *launcher : m_radiodrivenlaunchers.sequence() ) {
if( ( launcher->key() == Message )
&& ( ( launcher->dRadius < 0 )
|| ( glm::length2( launcher->location() - Location ) < launcher->dRadius ) )
&& ( true == launcher->check_conditions() ) ) {
// NOTE: only execution of event1 is supported for radio messages
// TBD, TODO: consider ability/way to execute event2
simulation::Events.AddToQuery( launcher->Event1, nullptr );
}
}
}
// legacy method, updates event queues // legacy method, updates event queues
void void
event_manager::update() { event_manager::update() {
@@ -2187,32 +2203,39 @@ event_manager::InitEvents() {
void void
event_manager::InitLaunchers() { event_manager::InitLaunchers() {
for( auto *launcher : m_launchers.sequence() ) { std::vector<basic_table<TEventLauncher> *> launchertables {
&m_inputdrivenlaunchers,
&m_radiodrivenlaunchers
};
if( launcher->iCheckMask != 0 ) { for( auto *launchertable : launchertables ) {
if( launcher->asMemCellName != "none" ) { for( auto *launcher : launchertable->sequence() ) {
// jeśli jest powiązana komórka pamięci
launcher->MemCell = simulation::Memory.find( launcher->asMemCellName ); if( launcher->iCheckMask != 0 ) {
if( launcher->MemCell == nullptr ) { if( launcher->asMemCellName != "none" ) {
ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find memcell \"" + launcher->asMemCellName + "\"" ); // jeśli jest powiązana komórka pamięci
launcher->MemCell = simulation::Memory.find( launcher->asMemCellName );
if( launcher->MemCell == nullptr ) {
ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find memcell \"" + launcher->asMemCellName + "\"" );
}
}
else {
launcher->MemCell = nullptr;
} }
} }
else {
launcher->MemCell = nullptr;
}
}
if( launcher->asEvent1Name != "none" ) { if( launcher->asEvent1Name != "none" ) {
launcher->Event1 = simulation::Events.FindEvent( launcher->asEvent1Name ); launcher->Event1 = simulation::Events.FindEvent( launcher->asEvent1Name );
if( launcher->Event1 == nullptr ) { if( launcher->Event1 == nullptr ) {
ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent1Name + "\"" ); ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent1Name + "\"" );
}
} }
}
if( launcher->asEvent2Name != "none" ) { if( launcher->asEvent2Name != "none" ) {
launcher->Event2 = simulation::Events.FindEvent( launcher->asEvent2Name ); launcher->Event2 = simulation::Events.FindEvent( launcher->asEvent2Name );
if( launcher->Event2 == nullptr ) { if( launcher->Event2 == nullptr ) {
ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent2Name + "\"" ); ErrorLog( "Bad scenario: event launcher \"" + launcher->name() + "\" can't find event \"" + launcher->asEvent2Name + "\"" );
}
} }
} }
} }
@@ -2228,8 +2251,14 @@ event_manager::export_as_text( std::ostream &Output ) const {
event->export_as_text( Output ); event->export_as_text( Output );
} }
} }
Output << "// event launchers\n"; Output << "// event launchers, basic\n";
for( auto const *launcher : m_launchers.sequence() ) { for( auto const *launcher : m_inputdrivenlaunchers.sequence() ) {
if( launcher->group() == null_handle ) {
launcher->export_as_text( Output );
}
}
Output << "// event launchers, radio driven\n";
for( auto const *launcher : m_radiodrivenlaunchers.sequence() ) {
if( launcher->group() == null_handle ) { if( launcher->group() == null_handle ) {
launcher->export_as_text( Output ); launcher->export_as_text( Output );
} }
@@ -2239,7 +2268,7 @@ event_manager::export_as_text( std::ostream &Output ) const {
std::vector<TEventLauncher*> event_manager::find_eventlaunchers(glm::vec2 center, float radius) const { std::vector<TEventLauncher*> event_manager::find_eventlaunchers(glm::vec2 center, float radius) const {
std::vector<TEventLauncher *> results; std::vector<TEventLauncher *> results;
for (auto &launcher : m_launchers.sequence()) { for (auto &launcher : m_inputdrivenlaunchers.sequence()) {
glm::dvec3 location = launcher->location(); glm::dvec3 location = launcher->location();
if (glm::distance2(glm::vec2(location.x, location.z), center) < radius) if (glm::distance2(glm::vec2(location.x, location.z), center) < radius)
results.push_back(launcher); results.push_back(launcher);

20
Event.h
View File

@@ -578,6 +578,9 @@ public:
// adds specified event launcher to the list of global launchers // adds specified event launcher to the list of global launchers
void void
queue( TEventLauncher *Launcher ); queue( TEventLauncher *Launcher );
// inserts in the event query events assigned to event launchers capable of receiving specified radio message sent from specified location
void
queue_receivers( radio_message const Message, glm::dvec3 const &Location );
// legacy method, updates event queues // legacy method, updates event queues
void void
update(); update();
@@ -588,10 +591,13 @@ public:
inline inline
bool bool
insert( TEventLauncher *Launcher ) { insert( TEventLauncher *Launcher ) {
return m_launchers.insert( Launcher ); } return (
inline void purge (TEventLauncher *Launcher) { Launcher->IsRadioActivated() ?
m_launchers.purge(Launcher); m_radiodrivenlaunchers.insert( Launcher ) :
} m_inputdrivenlaunchers.insert( Launcher ) ); }
inline void purge (TEventLauncher *Launcher) {
m_radiodrivenlaunchers.purge(Launcher);
m_inputdrivenlaunchers.purge(Launcher); }
// returns first event in the queue // returns first event in the queue
inline inline
basic_event * basic_event *
@@ -607,7 +613,8 @@ public:
basic_event * basic_event *
FindEvent( std::string const &Name ); FindEvent( std::string const &Name );
inline TEventLauncher* FindEventlauncher(std::string const &Name) { inline TEventLauncher* FindEventlauncher(std::string const &Name) {
return m_launchers.find(Name); auto ptr = m_inputdrivenlaunchers.find(Name);
return ptr ? ptr : m_radiodrivenlaunchers.find(Name);
} }
// legacy method, inserts specified event in the event query // legacy method, inserts specified event in the event query
bool bool
@@ -643,7 +650,8 @@ private:
basic_event *QueryRootEvent { nullptr }; basic_event *QueryRootEvent { nullptr };
basic_event *m_workevent { nullptr }; basic_event *m_workevent { nullptr };
event_map m_eventmap; event_map m_eventmap;
basic_table<TEventLauncher> m_launchers; basic_table<TEventLauncher> m_inputdrivenlaunchers;
basic_table<TEventLauncher> m_radiodrivenlaunchers;
eventlauncher_sequence m_launcherqueue; eventlauncher_sequence m_launcherqueue;
command_relay m_relay; command_relay m_relay;
}; };

View File

@@ -183,6 +183,7 @@ TGauge::Load_mapping( cParser &Input ) {
m_type = ( m_type = (
gaugetype == "impulse" ? TGaugeType::push : gaugetype == "impulse" ? TGaugeType::push :
gaugetype == "return" ? TGaugeType::push : gaugetype == "return" ? TGaugeType::push :
gaugetype == "delayed" ? TGaugeType::push_delayed :
TGaugeType::toggle ); // default TGaugeType::toggle ); // default
} }
else if( key == "soundinc:" ) { else if( key == "soundinc:" ) {

View File

@@ -23,7 +23,8 @@ enum class TGaugeAnimation {
enum class TGaugeType { enum class TGaugeType {
toggle, toggle,
push push,
push_delayed
}; };
// animowany wskaźnik, mogący przyjmować wiele stanów pośrednich // animowany wskaźnik, mogący przyjmować wiele stanów pośrednich

View File

@@ -59,7 +59,7 @@ global_settings::ConfigParse(cParser &Parser) {
Parser.getTokens( 1, false ); Parser.getTokens( 1, false );
Parser >> FieldOfView; Parser >> FieldOfView;
// guard against incorrect values // guard against incorrect values
FieldOfView = clamp( FieldOfView, 15.0f, 75.0f ); FieldOfView = clamp( FieldOfView, 10.0f, 75.0f );
} }
else if (token == "width") else if (token == "width")
{ {

View File

@@ -377,7 +377,7 @@ struct TBrakePressure
typedef std::map<int,TBrakePressure> TBrakePressureTable; typedef std::map<int,TBrakePressure> TBrakePressureTable;
/*typy napedow*/ /*typy napedow*/
enum class TEngineType { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine, SteamEngine, DieselElectric }; enum class TEngineType { None, Dumb, WheelsDriven, ElectricSeriesMotor, ElectricInductionMotor, DieselEngine, SteamEngine, DieselElectric, Main };
/*postac dostarczanej energii*/ /*postac dostarczanej energii*/
enum class TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower }; enum class TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower };
/*rodzaj paliwa*/ /*rodzaj paliwa*/
@@ -431,10 +431,22 @@ struct TCurrentCollector {
//} //}
}; };
/*typy źródeł mocy*/ /*typy źródeł mocy*/
enum class TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector, PowerCable, Heater }; enum class TPowerSource { NotDefined, InternalSource, Transducer, Generator, Accumulator, CurrentCollector, PowerCable, Heater, Main };
struct engine_generator {
// ld inputs
double *engine_revolutions; // revs per second of the prime mover
// config
double revolutions_min; // min working revolutions rate, in revs per second
double revolutions_max; // max working revolutions rate, in revs per second
double voltage_min; // voltage generated at min working revolutions
double voltage_max; // voltage generated at max working revolutions
// ld outputs
double revolutions;
double voltage;
};
struct _mover__1 struct TAccumulator
{ {
double MaxCapacity; double MaxCapacity;
TPowerSource RechargeSource; TPowerSource RechargeSource;
@@ -444,7 +456,7 @@ struct _mover__1
//} //}
}; };
struct _mover__2 struct TPowerCable
{ {
TPowerType PowerTrans; TPowerType PowerTrans;
double SteamPressure; double SteamPressure;
@@ -454,12 +466,17 @@ struct _mover__2
//} //}
}; };
struct _mover__3 struct THeater
{ {
TGrateType Grate; TGrateType Grate;
TBoilerType Boiler; TBoilerType Boiler;
}; };
struct TTransducer {
// ld inputs
double InputVoltage;
};
/*parametry źródeł mocy*/ /*parametry źródeł mocy*/
struct TPowerParameters struct TPowerParameters
{ {
@@ -471,11 +488,11 @@ struct TPowerParameters
{ {
struct struct
{ {
_mover__3 RHeater; THeater RHeater;
}; };
struct struct
{ {
_mover__2 RPowerCable; TPowerCable RPowerCable;
}; };
struct struct
{ {
@@ -483,15 +500,15 @@ struct TPowerParameters
}; };
struct struct
{ {
_mover__1 RAccumulator; TAccumulator RAccumulator;
}; };
struct struct
{ {
TEngineType GeneratorEngine; engine_generator EngineGenerator;
}; };
struct struct
{ {
double InputVoltage; TTransducer Transducer;
}; };
struct struct
{ {
@@ -633,7 +650,8 @@ enum class TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic
struct power_coupling { struct power_coupling {
double current{ 0.0 }; double current{ 0.0 };
double voltage{ 0.0 }; double voltage{ 0.0 };
bool local{ false }; // whether the power comes from external or onboard source bool is_local{ false }; // whether the power comes from external or onboard source
bool is_live{ false }; // whether the coupling with next vehicle is live
}; };
struct TCoupling { struct TCoupling {
@@ -1037,7 +1055,11 @@ public:
/* dizel_auto_min, dizel_auto_max: real; {predkosc obrotowa przelaczania automatycznej skrzyni biegow*/ /* dizel_auto_min, dizel_auto_max: real; {predkosc obrotowa przelaczania automatycznej skrzyni biegow*/
double dizel_nmax_cutoff = 0.0; /*predkosc obrotowa zadzialania ogranicznika predkosci*/ double dizel_nmax_cutoff = 0.0; /*predkosc obrotowa zadzialania ogranicznika predkosci*/
double dizel_nmin = 0.0; /*najmniejsza dopuszczalna predkosc obrotowa*/ double dizel_nmin = 0.0; /*najmniejsza dopuszczalna predkosc obrotowa*/
double dizel_nmin_hdrive = 0.0; /*najmniejsza dopuszczalna predkosc obrotowa w czasie jazdy na hydro */
double dizel_nmin_hdrive_factor = 0.0; /*wspolczynnik wzrostu obrotow minimalnych hydro zaleznosci od zadanego procentu*/
double dizel_nmin_retarder = 0.0; /*obroty pracy podczas hamowania retarderem*/
double dizel_minVelfullengage = 0.0; /*najmniejsza predkosc przy jezdzie ze sprzeglem bez poslizgu*/ double dizel_minVelfullengage = 0.0; /*najmniejsza predkosc przy jezdzie ze sprzeglem bez poslizgu*/
double dizel_maxVelANS = 3.0; /*predkosc progowa rozlaczenia przetwornika momentu*/
double dizel_AIM = 1.0; /*moment bezwladnosci walu itp*/ double dizel_AIM = 1.0; /*moment bezwladnosci walu itp*/
double dizel_engageDia = 0.5; double dizel_engageMaxForce = 6000.0; double dizel_engagefriction = 0.5; /*parametry sprzegla*/ double dizel_engageDia = 0.5; double dizel_engageMaxForce = 6000.0; double dizel_engagefriction = 0.5; /*parametry sprzegla*/
double engagedownspeed = 0.9; double engagedownspeed = 0.9;
@@ -1065,6 +1087,7 @@ public:
double hydro_R_FillRateInc = 1.0; /*szybkosc napelniania sprzegla*/ double hydro_R_FillRateInc = 1.0; /*szybkosc napelniania sprzegla*/
double hydro_R_FillRateDec = 1.0; /*szybkosc oprozniania sprzegla*/ double hydro_R_FillRateDec = 1.0; /*szybkosc oprozniania sprzegla*/
double hydro_R_MinVel = 1.0; /*minimalna predkosc, przy ktorej retarder dziala*/ double hydro_R_MinVel = 1.0; /*minimalna predkosc, przy ktorej retarder dziala*/
double hydro_R_EngageVel = 1.0; /*minimalna predkosc hamowania, przy ktorej sprzeglo jest wciaz wlaczone*/
/*- dla lokomotyw spalinowo-elektrycznych -*/ /*- dla lokomotyw spalinowo-elektrycznych -*/
double AnPos = 0.0; // pozycja sterowania dokladnego (analogowego) double AnPos = 0.0; // pozycja sterowania dokladnego (analogowego)
bool AnalogCtrl = false; // bool AnalogCtrl = false; //
@@ -1096,10 +1119,10 @@ public:
double MED_EPVC_Time = 7; // czas korekcji sily hamowania EP, gdy nie ma dostepnego ED double MED_EPVC_Time = 7; // czas korekcji sily hamowania EP, gdy nie ma dostepnego ED
bool MED_Ncor = 0; // czy korekcja sily hamowania z uwzglednieniem nacisku bool MED_Ncor = 0; // czy korekcja sily hamowania z uwzglednieniem nacisku
int DCEMUED_CC; //na którym sprzęgu sprawdzać działanie ED int DCEMUED_CC { 0 }; //na którym sprzęgu sprawdzać działanie ED
double DCEMUED_EP_max_Vel; //maksymalna prędkość, przy której działa EP przy włączonym ED w jednostce (dla tocznych) double DCEMUED_EP_max_Vel{ 0.0 }; //maksymalna prędkość, przy której działa EP przy włączonym ED w jednostce (dla tocznych)
double DCEMUED_EP_min_Im; //minimalny prąd, przy którym EP nie działa przy włączonym ED w członie (dla silnikowych) double DCEMUED_EP_min_Im{ 0.0 }; //minimalny prąd, przy którym EP nie działa przy włączonym ED w członie (dla silnikowych)
double DCEMUED_EP_delay; //opóźnienie włączenia hamulca EP przy hamowaniu ED - zwłoka wstępna double DCEMUED_EP_delay{ 0.0 }; //opóźnienie włączenia hamulca EP przy hamowaniu ED - zwłoka wstępna
/*-dla wagonow*/ /*-dla wagonow*/
struct load_attributes { struct load_attributes {
@@ -1240,6 +1263,8 @@ public:
/*-zmienne dla lokomotyw*/ /*-zmienne dla lokomotyw*/
bool Mains = false; /*polozenie glownego wylacznika*/ bool Mains = false; /*polozenie glownego wylacznika*/
double MainsInitTime{ 0.0 }; // config, initialization time (in seconds) of the main circuit after it receives power, before it can be closed
double MainsInitTimeCountdown{ 0.0 }; // current state of main circuit initialization, remaining time (in seconds) until it's ready
int MainCtrlPos = 0; /*polozenie glownego nastawnika*/ int MainCtrlPos = 0; /*polozenie glownego nastawnika*/
int ScndCtrlPos = 0; /*polozenie dodatkowego nastawnika*/ int ScndCtrlPos = 0; /*polozenie dodatkowego nastawnika*/
int LightsPos = 0; int LightsPos = 0;
@@ -1305,6 +1330,7 @@ public:
double dizel_engagedeltaomega = 0.0; /*roznica predkosci katowych tarcz sprzegla*/ double dizel_engagedeltaomega = 0.0; /*roznica predkosci katowych tarcz sprzegla*/
double dizel_n_old = 0.0; /*poredkosc na potrzeby obliczen sprzegiel*/ double dizel_n_old = 0.0; /*poredkosc na potrzeby obliczen sprzegiel*/
double dizel_Torque = 0.0; /*poredkosc na potrzeby obliczen sprzegiel*/ double dizel_Torque = 0.0; /*poredkosc na potrzeby obliczen sprzegiel*/
double dizel_nreg_min = 0.0; /*predkosc regulatora minimalna, zmienna w hydro*/
/* - zmienne dla przetowrnika momentu */ /* - zmienne dla przetowrnika momentu */
double hydro_TC_Fill = 0.0; /*napelnienie*/ double hydro_TC_Fill = 0.0; /*napelnienie*/
@@ -1385,6 +1411,7 @@ public:
double fBrakeCtrlPos = -2.0; // płynna nastawa hamulca zespolonego double fBrakeCtrlPos = -2.0; // płynna nastawa hamulca zespolonego
bool bPantKurek3 = true; // kurek trójdrogowy (pantografu): true=połączenie z ZG, false=połączenie z małą sprężarką // domyślnie zbiornik pantografu połączony jest ze zbiornikiem głównym bool bPantKurek3 = true; // kurek trójdrogowy (pantografu): true=połączenie z ZG, false=połączenie z małą sprężarką // domyślnie zbiornik pantografu połączony jest ze zbiornikiem głównym
bool PantAutoValve { false }; // type of installed pantograph compressor valve
int iProblem = 0; // flagi problemów z taborem, aby AI nie musiało porównywać; 0=może jechać int iProblem = 0; // flagi problemów z taborem, aby AI nie musiało porównywać; 0=może jechać
int iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu int iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu
@@ -1517,7 +1544,9 @@ public:
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/ bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/
/*-funkcje typowe dla lokomotywy elektrycznej*/ /*-funkcje typowe dla lokomotywy elektrycznej*/
void ConverterCheck( double const Timestep ); // przetwornica void MainsCheck( double const Deltatime );
void PowerCouplersCheck( double const Deltatime );
void ConverterCheck( double const Timestep ); // przetwornica
void HeatingCheck( double const Timestep ); void HeatingCheck( double const Timestep );
void WaterPumpCheck( double const Timestep ); void WaterPumpCheck( double const Timestep );
void WaterHeaterCheck( double const Timestep ); void WaterHeaterCheck( double const Timestep );
@@ -1557,8 +1586,9 @@ public:
bool dizel_EngageSwitch(double state); bool dizel_EngageSwitch(double state);
bool dizel_EngageChange(double dt); bool dizel_EngageChange(double dt);
bool dizel_AutoGearCheck(void); bool dizel_AutoGearCheck(void);
double dizel_fillcheck(int mcp); double dizel_fillcheck(int mcp, double dt);
double dizel_Momentum(double dizel_fill, double n, double dt); double dizel_Momentum(double dizel_fill, double n, double dt);
double dizel_MomentumRetarder(double n, double dt); // moment hamowania retardera
void dizel_HeatSet( float const Value ); void dizel_HeatSet( float const Value );
void dizel_Heat( double const dt ); void dizel_Heat( double const dt );
bool dizel_StartupCheck(); bool dizel_StartupCheck();

View File

@@ -781,7 +781,7 @@ void TMoverParameters::UpdatePantVolume(double dt)
// Ra 2014-07: kurek trójdrogowy łączy spr.pom. z pantografami i wyłącznikiem ciśnieniowym WS // Ra 2014-07: kurek trójdrogowy łączy spr.pom. z pantografami i wyłącznikiem ciśnieniowym WS
// Ra 2014-07: zbiornika rozrządu nie pompuje się tu, tylko pantografy; potem można zamknąć // Ra 2014-07: zbiornika rozrządu nie pompuje się tu, tylko pantografy; potem można zamknąć
// WS i odpalić resztę // WS i odpalić resztę
if ((TrainType == dt_EZT) ? if (PantAutoValve ?
(PantPress < ScndPipePress) : (PantPress < ScndPipePress) :
bPantKurek3) // kurek zamyka połączenie z ZG bPantKurek3) // kurek zamyka połączenie z ZG
{ // zbiornik pantografu połączony ze zbiornikiem głównym - małą sprężarką się tego nie napompuje { // zbiornik pantografu połączony ze zbiornikiem głównym - małą sprężarką się tego nie napompuje
@@ -1181,85 +1181,6 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
const double Vepsilon = 1e-5; const double Vepsilon = 1e-5;
const double Aepsilon = 1e-3; // ASBSpeed=0.8; const double Aepsilon = 1e-3; // ASBSpeed=0.8;
// T_MoverParameters::ComputeMovement(dt, dt1, Shape, Track, ElectricTraction, NewLoc, NewRot);
// // najpierw kawalek z funkcji w pliku mover.pas
TotalCurrent = 0;
double hvc =
std::max(
std::max(
PantFrontVolt,
PantRearVolt ),
ElectricTraction.TractionVoltage * 0.9 );
for( int side = 0; side < 2; ++side ) {
// przekazywanie napiec
auto const oppositeside { ( side == end::front ? end::rear : end::front ) };
auto const liveconnection{
( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].Connected->Heating ) ) };
if( liveconnection ) {
auto const &connectedcoupler = Couplers[ side ].Connected->Couplers[ Couplers[ side ].ConnectedNr ];
Couplers[ oppositeside ].power_high.voltage =
std::max(
std::abs( hvc ),
connectedcoupler.power_high.voltage - Couplers[ side ].power_high.current * 0.02 );
}
else {
Couplers[ oppositeside ].power_high.voltage = std::abs( hvc ) - Couplers[ side ].power_high.current * 0.02;
}
}
hvc = Couplers[ end::front ].power_high.voltage + Couplers[ end::rear ].power_high.voltage;
if( std::abs( PantFrontVolt ) + std::abs( PantRearVolt ) < 1.0 ) {
// bez napiecia...
if( hvc != 0.0 ) {
// ...ale jest cos na sprzegach:
// przekazywanie pradow
for( int side = 0; side < 2; ++side ) {
Couplers[ side ].power_high.local = false; // power, if any, will be from external source
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].Connected->Heating ) ) ) {
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == end::front ?
end::rear :
end::front ) ];
Couplers[ side ].power_high.current =
connectedcoupler.power_high.current
+ Itot * Couplers[ side ].power_high.voltage / hvc; // obciążenie rozkladane stosownie do napiec
}
else {
Couplers[ side ].power_high.current = Itot * Couplers[ side ].power_high.voltage / hvc;
}
}
}
}
else
{
for( int side = 0; side < 2; ++side ) {
Couplers[ side ].power_high.local = true; // power is coming from local pantographs
if( ( Couplers[ side ].CouplingFlag & ctrain_power )
|| ( ( Couplers[ side ].CouplingFlag & ctrain_heating )
&& ( Couplers[ side ].Connected->Heating ) ) ) {
auto const &connectedcoupler =
Couplers[ side ].Connected->Couplers[
( Couplers[ side ].ConnectedNr == end::front ?
end::rear :
end::front ) ];
TotalCurrent += connectedcoupler.power_high.current;
Couplers[ side ].power_high.current = 0.0;
}
}
}
if (!TestFlag(DamageFlag, dtrain_out)) if (!TestFlag(DamageFlag, dtrain_out))
{ // Ra: to przepisywanie tu jest bez sensu { // Ra: to przepisywanie tu jest bez sensu
RunningShape = Shape; RunningShape = Shape;
@@ -1499,10 +1420,11 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
RunInternalCommand(); RunInternalCommand();
// automatyczny rozruch // automatyczny rozruch
if (EngineType == TEngineType::ElectricSeriesMotor) if( EngineType == TEngineType::ElectricSeriesMotor ) {
if( AutoRelayCheck() ) {
if (AutoRelayCheck()) SetFlag( SoundFlag, sound::relay );
SetFlag(SoundFlag, sound::relay); }
}
if( ( EngineType == TEngineType::DieselEngine ) if( ( EngineType == TEngineType::DieselEngine )
|| ( EngineType == TEngineType::DieselElectric ) ) { || ( EngineType == TEngineType::DieselElectric ) ) {
@@ -1510,6 +1432,12 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
SetFlag( SoundFlag, sound::relay ); SetFlag( SoundFlag, sound::relay );
} }
} }
// TODO: gather and move current calculations to dedicated method
TotalCurrent = 0;
// main circuit
MainsCheck( Deltatime );
// traction motors // traction motors
MotorBlowersCheck( Deltatime ); MotorBlowersCheck( Deltatime );
// uklady hamulcowe: // uklady hamulcowe:
@@ -1547,6 +1475,145 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
BrakeSlippingTimer += Deltatime; BrakeSlippingTimer += Deltatime;
// automatic doors // automatic doors
update_doors( Deltatime ); update_doors( Deltatime );
PowerCouplersCheck( Deltatime );
}
void TMoverParameters::MainsCheck( double const Deltatime ) {
// TODO: move other main circuit checks here
if( MainsInitTime == 0.0 ) { return; }
if( MainsInitTimeCountdown > 0.0 ) {
MainsInitTimeCountdown -= Deltatime;
}
// TBD, TODO: move voltage calculation to separate method and use also in power coupler state calculation?
auto localvoltage { 0.0 };
switch( EnginePowerSource.SourceType ) {
case TPowerSource::CurrentCollector: {
localvoltage =
std::max(
localvoltage,
std::max(
PantFrontVolt,
PantRearVolt ) );
break;
}
default: {
break;
}
}
if( ( localvoltage == 0.0 )
&& ( GetTrainsetVoltage() == 0 ) ) {
MainsInitTimeCountdown = MainsInitTime;
}
}
void TMoverParameters::PowerCouplersCheck( double const Deltatime ) {
// TODO: add support for other power sources
auto localvoltage { 0.0 };
// heating power sources
if( Heating ) {
switch( HeatingPowerSource.SourceType ) {
case TPowerSource::Generator: {
localvoltage = HeatingPowerSource.EngineGenerator.voltage - TotalCurrent * 0.02;
break;
}
case TPowerSource::Main: {
localvoltage = ( true == Mains ? Voltage : 0.0 );
break;
}
default: {
break;
}
}
}
// high voltage power sources
switch( EnginePowerSource.SourceType ) {
case TPowerSource::CurrentCollector: {
localvoltage =
std::max(
localvoltage,
std::max(
PantFrontVolt,
PantRearVolt ) );
break;
}
default: {
break;
}
}
auto const abslocalvoltage { std::abs( localvoltage ) };
auto const localpowersource { ( abslocalvoltage > 1.0 ) };
/*
auto const localpowersource { ( std::abs( PantFrontVolt ) + std::abs( PantRearVolt ) > 1.0 ) };
auto hvc = std::max( PantFrontVolt, PantRearVolt );
*/
// przekazywanie napiec
for( auto side = 0; side < 2; ++side ) {
auto &coupler { Couplers[ side ] };
// NOTE: in the loop we actually update the state of the coupler on the opposite end of the vehicle
auto &oppositecoupler { Couplers[ ( side == end::front ? end::rear : end::front ) ] };
auto const oppositehighvoltagecoupling { ( oppositecoupler.CouplingFlag & coupling::highvoltage ) != 0 };
auto const oppositeheatingcoupling { ( oppositecoupler.CouplingFlag & coupling::heating ) != 0 };
// start with base voltage
oppositecoupler.power_high.voltage = abslocalvoltage;
oppositecoupler.power_high.is_live = false;
oppositecoupler.power_high.is_local = localpowersource; // indicate power source
// draw from external source
if( coupler.Connected != nullptr ) {
auto const &connectedcoupler { coupler.Connected->Couplers[ coupler.ConnectedNr ] };
auto const connectedvoltage { (
connectedcoupler.power_high.is_live ?
connectedcoupler.power_high.voltage :
0.0 ) };
oppositecoupler.power_high.voltage = std::max(
oppositecoupler.power_high.voltage,
connectedvoltage - coupler.power_high.current * 0.02 );
oppositecoupler.power_high.is_live =
( connectedvoltage > 0.1 )
&& ( oppositehighvoltagecoupling || oppositeheatingcoupling );
}
// draw from local source
if( localpowersource ) {
oppositecoupler.power_high.voltage = std::max(
oppositecoupler.power_high.voltage,
abslocalvoltage - coupler.power_high.current * 0.02 );
oppositecoupler.power_high.is_live |=
( abslocalvoltage > 0.1 )
&& ( oppositehighvoltagecoupling || ( oppositeheatingcoupling && localpowersource && Heating ) );
}
}
// przekazywanie pradow
auto couplervoltage { Couplers[ end::front ].power_high.voltage + Couplers[ end::rear ].power_high.voltage };
for( auto side = 0; side < 2; ++side ) {
auto &coupler { Couplers[ side ] };
auto const &connectedothercoupler { coupler.Connected->Couplers[ ( coupler.ConnectedNr == end::front ? end::rear : end::front ) ] };
coupler.power_high.current = 0.0;
if( false == localpowersource ) {
// bez napiecia...
if( couplervoltage != 0.0 ) {
// ...ale jest cos na sprzegach:
coupler.power_high.current = ( Itot + TotalCurrent ) * coupler.power_high.voltage / couplervoltage; // obciążenie rozkladane stosownie do napiec
if( true == coupler.power_high.is_live ) {
coupler.power_high.current += connectedothercoupler.power_high.current;
}
}
}
else {
if( true == coupler.power_high.is_live ) {
TotalCurrent += connectedothercoupler.power_high.current;
}
}
}
} }
double TMoverParameters::ShowEngineRotation(int VehN) double TMoverParameters::ShowEngineRotation(int VehN)
@@ -1603,12 +1670,70 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
// heating system status check // heating system status check
void TMoverParameters::HeatingCheck( double const Timestep ) { void TMoverParameters::HeatingCheck( double const Timestep ) {
Heating = ( // update heating devices
( true == HeatingAllow ) // TBD, TODO: move this to a separate method?
// powered vehicles are generally required to activate their power source to provide heating switch( HeatingPowerSource.SourceType ) {
// passive vehicles get a pass in this regard case TPowerSource::Generator: {
&& ( ( Power < 0.1 ) if( ( HeatingPowerSource.EngineGenerator.engine_revolutions != nullptr )
|| ( true == Mains ) ) ); && ( HeatingPowerSource.EngineGenerator.revolutions_max > 0 ) ) {
auto &generator { HeatingPowerSource.EngineGenerator };
// TBD, TODO: engine-generator transmission
generator.revolutions = *(generator.engine_revolutions);
auto const absrevolutions { std::abs( generator.revolutions ) };
generator.voltage = (
absrevolutions < generator.revolutions_min ? generator.voltage_min * absrevolutions / generator.revolutions_min :
// absrevolutions > generator.revolutions_max ? generator.voltage_max * absrevolutions / generator.revolutions_max :
interpolate(
generator.voltage_min, generator.voltage_max,
clamp(
( absrevolutions - generator.revolutions_min ) / ( generator.revolutions_max - generator.revolutions_min ),
0.0, 1.0 ) ) )
* sign( generator.revolutions );
}
break;
}
default: {
break;
}
}
// quick check first to avoid unnecessary calls...
if( false == HeatingAllow ) {
Heating = false;
return;
}
// ...detailed check if we're still here
auto const heatingpowerthreshold { 0.1 };
// start with external power sources
auto voltage { 0.0 };
// then try internal ones
switch( HeatingPowerSource.SourceType ) {
case TPowerSource::Generator: {
voltage = HeatingPowerSource.EngineGenerator.voltage;
break;
}
case TPowerSource::PowerCable: {
if( HeatingPowerSource.PowerType == TPowerType::ElectricPower ) {
voltage = GetTrainsetVoltage();
}
break;
}
case TPowerSource::Main: {
voltage = ( true == Mains ? Voltage : 0.0 );
break;
}
default: {
break;
}
}
Heating = ( std::abs( voltage ) > heatingpowerthreshold );
if( Heating ) {
TotalCurrent += 1000 * HeatingPower / voltage; // heater power cost presumably specified in kilowatts
}
} }
// water pump status check // water pump status check
@@ -2756,6 +2881,7 @@ void TMoverParameters::MainSwitch_( bool const State ) {
if( ( false == State ) if( ( false == State )
|| ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) ) || ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) )
&& ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) ) && ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) )
&& ( MainsInitTimeCountdown <= 0.0 )
&& ( true == NoVoltRelay ) && ( true == NoVoltRelay )
&& ( true == OvervoltageRelay ) && ( true == OvervoltageRelay )
&& ( LastSwitchingTime > CtrlDelay ) && ( LastSwitchingTime > CtrlDelay )
@@ -3874,7 +4000,6 @@ void TMoverParameters::ComputeConstans(void)
double BearingF, RollF, HideModifier; double BearingF, RollF, HideModifier;
double Curvature; // Ra 2014-07: odwrotność promienia double Curvature; // Ra 2014-07: odwrotność promienia
TotalCurrent = 0; // Ra 2014-04: tu zerowanie, aby EZT mogło pobierać prąd innemu członowi
TotalMass = ComputeMass(); TotalMass = ComputeMass();
TotalMassxg = TotalMass * g; // TotalMass*g TotalMassxg = TotalMass * g; // TotalMass*g
BearingF = 2.0 * (DamageFlag && dtrain_bearing); BearingF = 2.0 * (DamageFlag && dtrain_bearing);
@@ -4013,9 +4138,10 @@ void TMoverParameters::ComputeTotalForce(double dt) {
else else
Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo; Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo;
} // bo nie dzialalo } // bo nie dzialalo
// TODO: clean up this elseif to match changes in power coupling code
else if( ( EngineType == TEngineType::ElectricInductionMotor ) else if( ( EngineType == TEngineType::ElectricInductionMotor )
|| ( ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) == ctrain_power ) || ( ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) == ctrain_power )
|| ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) { || ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) == ctrain_power ) ) ) {
// potem ulepszyc! pantogtrafy! // potem ulepszyc! pantogtrafy!
Voltage = Voltage =
std::max( std::max(
@@ -4405,7 +4531,7 @@ double TMoverParameters::TractionForce( double dt ) {
tmp = DElist[ MainCtrlPos ].RPM / 60.0; tmp = DElist[ MainCtrlPos ].RPM / 60.0;
if( ( true == Heating ) if( ( true == HeatingAllow )
&& ( HeatingPower > 0 ) && ( HeatingPower > 0 )
&& ( EngineHeatingRPM > 0 ) ) { && ( EngineHeatingRPM > 0 ) ) {
// bump engine revolutions up if needed, when heating is on // bump engine revolutions up if needed, when heating is on
@@ -4559,7 +4685,7 @@ double TMoverParameters::TractionForce( double dt ) {
EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 ); EnginePower = ( 2 * dizel_Mstand + dmoment ) * enrot * ( 2.0 * M_PI / 1000.0 );
if( MainCtrlPowerPos() > 1 ) { if( MainCtrlPowerPos() > 1 ) {
// dodatkowe opory z powodu sprezarki} // dodatkowe opory z powodu sprezarki}
dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); // dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); //yB: skąd to w ogóle się bierze?!
} }
break; break;
} }
@@ -4742,6 +4868,8 @@ double TMoverParameters::TractionForce( double dt ) {
{ {
Mm = dmoment; //bylo * dizel_engage Mm = dmoment; //bylo * dizel_engage
Mw = Mm * dtrans; // dmoment i dtrans policzone przy okazji enginerotation Mw = Mm * dtrans; // dmoment i dtrans policzone przy okazji enginerotation
if ((hydro_R) && (hydro_R_Placement == 0))
Mw -= dizel_MomentumRetarder(nrot * Transmision.Ratio, dt) * Transmision.Ratio;
Fw = Mw * 2.0 / WheelDiameter / NPoweredAxles; Fw = Mw * 2.0 / WheelDiameter / NPoweredAxles;
Ft = Fw * NPoweredAxles; // sila trakcyjna Ft = Fw * NPoweredAxles; // sila trakcyjna
Ft = Ft * DirAbsolute; // ActiveDir*CabNo; Ft = Ft * DirAbsolute; // ActiveDir*CabNo;
@@ -5282,12 +5410,12 @@ double TMoverParameters::TractionForce( double dt ) {
Im = eimv[eimv_If]; Im = eimv[eimv_If];
if ((eimv[eimv_Ipoj] >= 0)) if ((eimv[eimv_Ipoj] >= 0))
Vadd *= (1.0 - 2.0 * dt); Vadd *= (1.0 - 2.0 * dt);
else if ((Voltage < EnginePowerSource.CollectorParameters.MaxV)) else if ((std::abs(Voltage) < EnginePowerSource.CollectorParameters.MaxV))
Vadd *= (1.0 - dt); Vadd *= (1.0 - dt);
else else
Vadd = Max0R( Vadd = Max0R(
Vadd * (1.0 - 0.2 * dt), Vadd * (1.0 - 0.2 * dt),
0.007 * (Voltage - (EnginePowerSource.CollectorParameters.MaxV - 100))); 0.007 * (std::abs(Voltage) - (EnginePowerSource.CollectorParameters.MaxV - 100)));
Itot = eimv[eimv_Ipoj] * (0.01 + Min0R(0.99, 0.99 - Vadd)); Itot = eimv[eimv_Ipoj] * (0.01 + Min0R(0.99, 0.99 - Vadd));
EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000; EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000;
@@ -6106,9 +6234,34 @@ void TMoverParameters::CheckEIMIC(double dt)
} }
break; break;
case 3: case 3:
eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedDown); //odejmuj do X if ((UniCtrlList[MainCtrlPos].mode != BrakeCtrlPos) && (MainCtrlActualPos == MainCtrlPos)) //there was no move of controller, but brake only
eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, dt * UniCtrlList[MainCtrlPos].SpeedUp); //dodawaj do X {
eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal); if (BrakeCtrlPos < UniCtrlList[MainCtrlPosNo].mode)
BrakeLevelSet(UniCtrlList[MainCtrlPosNo].mode); //bottom clamping
if (BrakeCtrlPos > UniCtrlList[0].mode)
BrakeLevelSet(UniCtrlList[0].mode); //top clamping
while (BrakeCtrlPos > UniCtrlList[MainCtrlPos].mode) DecMainCtrl(1); //find nearest position
while (BrakeCtrlPos < UniCtrlList[MainCtrlPos].mode) IncMainCtrl(1); //find nearest position
}
else //controller was moved
BrakeLevelSet(UniCtrlList[MainCtrlPos].mode);
if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay))
{
eimic -= clamp(-UniCtrlList[MainCtrlPos].SetCtrlVal + eimic, 0.0, (MainCtrlActualPos == MainCtrlPos ? dt * UniCtrlList[MainCtrlPos].SpeedDown : sign(UniCtrlList[MainCtrlPos].SpeedDown) * 0.01)); //odejmuj do X
eimic += clamp(UniCtrlList[MainCtrlPos].SetCtrlVal - eimic, 0.0, (MainCtrlActualPos == MainCtrlPos ? dt * UniCtrlList[MainCtrlPos].SpeedUp : sign(UniCtrlList[MainCtrlPos].SpeedUp) * 0.01)); //dodawaj do X
eimic = clamp(eimic, UniCtrlList[MainCtrlPos].MinCtrlVal, UniCtrlList[MainCtrlPos].MaxCtrlVal);
}
if (MainCtrlActualPos == MainCtrlPos)
LastRelayTime += dt;
else
{
LastRelayTime = 0;
MainCtrlActualPos = MainCtrlPos;
}
if (Hamulec->GetEDBCP() > 0.3 && eimic < 0) //when braking with pneumatic brake
eimic = 0; //shut off retarder
} }
auto const eimicpowerenabled { auto const eimicpowerenabled {
( ( true == Mains ) || ( Power == 0.0 ) ) ( ( true == Mains ) || ( Power == 0.0 ) )
@@ -6231,6 +6384,22 @@ bool TMoverParameters::dizel_AutoGearCheck(void)
if (Mains) if (Mains)
{ {
if (EIMCtrlType > 0) //sterowanie komputerowe
{
if (dizel_automaticgearstatus == 0)
{
if ((hydro_TC && hydro_TC_Fill > 0.01) || (eimic_real > 0.0))
dizel_EngageSwitch(1.0);
else
if (Vel > hydro_R_EngageVel && hydro_R && hydro_R_Fill > 0.01)
dizel_EngageSwitch(0.5);
else
dizel_EngageSwitch(0.0);
}
else
dizel_EngageSwitch(0.0);
}
else
if (dizel_automaticgearstatus == 0) // ustaw cisnienie w silowniku sprzegla} if (dizel_automaticgearstatus == 0) // ustaw cisnienie w silowniku sprzegla}
switch (RList[MainCtrlPos].Mn) switch (RList[MainCtrlPos].Mn)
{ {
@@ -6362,7 +6531,7 @@ bool TMoverParameters::dizel_Update(double dt) {
dizel_EngageChange( dt ); dizel_EngageChange( dt );
DU = dizel_AutoGearCheck(); DU = dizel_AutoGearCheck();
double const fillspeed { 2 }; double const fillspeed { 2 };
dizel_fill = dizel_fill + fillspeed * dt * ( dizel_fillcheck( MainCtrlPos ) - dizel_fill ); dizel_fill = dizel_fill + fillspeed * dt * ( dizel_fillcheck( MainCtrlPos , dt ) - dizel_fill );
} }
dizel_Heat( dt ); dizel_Heat( dt );
@@ -6374,7 +6543,7 @@ bool TMoverParameters::dizel_Update(double dt) {
// Q: 20160715 // Q: 20160715
// oblicza napelnienie, uzwglednia regulator obrotow // oblicza napelnienie, uzwglednia regulator obrotow
// ************************************************************************************************* // *************************************************************************************************
double TMoverParameters::dizel_fillcheck(int mcp) double TMoverParameters::dizel_fillcheck(int mcp, double dt)
{ {
auto realfill { 0.0 }; auto realfill { 0.0 };
@@ -6391,11 +6560,30 @@ double TMoverParameters::dizel_fillcheck(int mcp)
} }
else { else {
// napelnienie zalezne od MainCtrlPos // napelnienie zalezne od MainCtrlPos
realfill = RList[ mcp ].R; if (EIMCtrlType > 0)
{
realfill = std::max(0.0, eimic_real);
if (eimic_real>0 && !hydro_TC_Lockup)
{
dizel_nreg_min = std::min(dizel_nreg_min + 2.5 * dt, dizel_nmin_hdrive + eimic_real * dizel_nmin_hdrive_factor);
}
else
{
if (Vel < hydro_R_EngageVel && hydro_R && hydro_R_Fill > 0.01)
dizel_nreg_min = std::min(dizel_nreg_min + 5.0 * dt, dizel_nmin_retarder);
else
dizel_nreg_min = dizel_nmin;
}
}
else
realfill = RList[mcp].R;
} }
if (dizel_nmax_cutoff > 0) if (dizel_nmax_cutoff > 0)
{ {
auto nreg { 0.0 }; auto nreg { 0.0 };
if (EIMCtrlType > 0)
nreg = (eimic_real > 0 ? dizel_nmax : dizel_nmin);
else
switch (RList[MainCtrlPos].Mn) switch (RList[MainCtrlPos].Mn)
{ {
case 0: case 0:
@@ -6434,7 +6622,7 @@ double TMoverParameters::dizel_fillcheck(int mcp)
realfill = 0; realfill = 0;
if (enrot < nreg) //pod predkoscia regulatora dawka zadana if (enrot < nreg) //pod predkoscia regulatora dawka zadana
realfill = realfill; realfill = realfill;
if ((enrot < dizel_nmin * 0.98)&&(RList[mcp].R>0.001)) //jesli ponizej biegu jalowego i niezerowa dawka, to dawaj pelna if ((enrot < dizel_nreg_min)&&(RList[mcp].R>0.001)) //jesli ponizej biegu jalowego i niezerowa dawka, to dawaj pelna
realfill = 1; realfill = 1;
} }
} }
@@ -6460,6 +6648,8 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
if( enrot > 0 ) { if( enrot > 0 ) {
Moment = ( dizel_Mmax - ( dizel_Mmax - dizel_Mnmax ) * square( ( enrot - dizel_nMmax ) / ( dizel_nMmax - dizel_nmax ) ) ) * dizel_fill - dizel_Mstand; Moment = ( dizel_Mmax - ( dizel_Mmax - dizel_Mnmax ) * square( ( enrot - dizel_nMmax ) / ( dizel_nMmax - dizel_nmax ) ) ) * dizel_fill - dizel_Mstand;
if ((hydro_R) && (hydro_R_Placement == 2))
Moment -= dizel_MomentumRetarder(enrot, dt);
} }
else { else {
Moment = -dizel_Mstand; Moment = -dizel_Mstand;
@@ -6477,10 +6667,11 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
if (hydro_TC) //jesli przetwornik momentu if (hydro_TC) //jesli przetwornik momentu
{ {
//napelnianie przetwornika //napelnianie przetwornika
if ((MainCtrlPowerPos() > 0) && (Mains) && (enrot>dizel_nmin*0.9)) bool IsPower = (EIMCtrlType > 0 ? eimic_real > 0 : MainCtrlPowerPos() > 0);
if ((IsPower) && (Mains) && (enrot>dizel_nmin*0.9))
hydro_TC_Fill += hydro_TC_FillRateInc * dt; hydro_TC_Fill += hydro_TC_FillRateInc * dt;
//oproznianie przetwornika //oproznianie przetwornika
if (((IsMainCtrlNoPowerPos()) && (Vel<3)) if (((!IsPower) && (Vel<dizel_maxVelANS))
|| (!Mains) || (!Mains)
|| (enrot<dizel_nmin*0.8)) || (enrot<dizel_nmin*0.8))
hydro_TC_Fill -= hydro_TC_FillRateDec * dt; hydro_TC_Fill -= hydro_TC_FillRateDec * dt;
@@ -6488,10 +6679,10 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
hydro_TC_Fill = clamp(hydro_TC_Fill, 0.0, 1.0); hydro_TC_Fill = clamp(hydro_TC_Fill, 0.0, 1.0);
//blokowanie sprzegla blokującego //blokowanie sprzegla blokującego
if ((Vel > hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (MainCtrlPowerPos() > 0)) if ((Vel > hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (IsPower))
hydro_TC_LockupRate += hydro_TC_FillRateInc*dt; hydro_TC_LockupRate += hydro_TC_FillRateInc*dt;
//luzowanie sprzegla blokujacego //luzowanie sprzegla blokujacego
if ((Vel < (MainCtrlPowerPos() > 0 ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) if ((Vel < (IsPower ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin))
hydro_TC_LockupRate -= hydro_TC_FillRateDec*dt; hydro_TC_LockupRate -= hydro_TC_FillRateDec*dt;
//obcinanie zakresu //obcinanie zakresu
hydro_TC_LockupRate = clamp(hydro_TC_LockupRate, 0.0, 1.0); hydro_TC_LockupRate = clamp(hydro_TC_LockupRate, 0.0, 1.0);
@@ -6578,6 +6769,8 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
double enrot_max = enrot + (Min0R(TorqueC, TorqueL + abs(hydro_TC_TorqueIn)) + Moment) / dizel_AIM * dt; double enrot_max = enrot + (Min0R(TorqueC, TorqueL + abs(hydro_TC_TorqueIn)) + Moment) / dizel_AIM * dt;
enrot = clamp(n,enrot_min,enrot_max); enrot = clamp(n,enrot_min,enrot_max);
} }
if ((hydro_R) && (hydro_R_Placement == 1))
gearMoment -= dizel_MomentumRetarder(hydro_TC_nOut, dt);
if( ( enrot <= 0 ) && ( false == dizel_spinup ) ) { if( ( enrot <= 0 ) && ( false == dizel_spinup ) ) {
@@ -6590,6 +6783,40 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
return gearMoment; return gearMoment;
} }
double TMoverParameters::dizel_MomentumRetarder(double n, double dt)
{
double RetarderRequest = (Mains ? std::max(0.0, -eimic_real) : 0);
if (Vel < hydro_R_MinVel)
RetarderRequest = 0;
if ((hydro_R_Placement == 2) && (enrot < dizel_nmin))
{
RetarderRequest = 0;
}
hydro_R_n = n * 60;
if (hydro_R_Fill < RetarderRequest) //gdy zadane hamowanie
{
hydro_R_Fill = std::min(hydro_R_Fill + hydro_R_FillRateInc*dt, RetarderRequest);
}
else
{
hydro_R_Fill = std::max(hydro_R_Fill - hydro_R_FillRateDec*dt, RetarderRequest);
}
double Moment = hydro_R_MaxTorque;
double pwr = Moment * n * M_PI * 2 * 0.001;
if (pwr > hydro_R_MaxPower)
Moment = Moment * hydro_R_MaxPower / pwr;
double moment_in = n*n*hydro_R_TorqueInIn;
Moment = std::min(moment_in, Moment * hydro_R_Fill);
hydro_R_Torque = Moment;
return Moment;
}
// sets component temperatures to specified value // sets component temperatures to specified value
void TMoverParameters::dizel_HeatSet( float const Value ) { void TMoverParameters::dizel_HeatSet( float const Value ) {
@@ -6899,8 +7126,8 @@ bool TMoverParameters::ChangeDoorPermitPreset( int const Change, range_t const N
Doors.permit_preset = clamp<int>( Doors.permit_preset + Change, 0, Doors.permit_presets.size() - 1 ); Doors.permit_preset = clamp<int>( Doors.permit_preset + Change, 0, Doors.permit_presets.size() - 1 );
auto const doors { Doors.permit_presets[ Doors.permit_preset ] }; auto const doors { Doors.permit_presets[ Doors.permit_preset ] };
auto const permitleft = doors & 1; auto const permitleft { ( ( doors & 1 ) != 0 ) };
auto const permitright = doors & 2; auto const permitright { ( ( doors & 2 ) != 0 ) };
PermitDoors( ( CabNo > 0 ? side::left : side::right ), permitleft, Notify ); PermitDoors( ( CabNo > 0 ? side::left : side::right ), permitleft, Notify );
PermitDoors( ( CabNo > 0 ? side::right : side::left ), permitright, Notify ); PermitDoors( ( CabNo > 0 ? side::right : side::left ), permitright, Notify );
@@ -7358,15 +7585,11 @@ double TMoverParameters::GetTrainsetVoltage(void)
{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT {//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
return std::max( return std::max(
( ( ( Couplers[end::front].Connected ) ( ( ( Couplers[end::front].Connected )
&& ( ( Couplers[ end::front ].CouplingFlag & ctrain_power ) && ( Couplers[ end::front ].Connected->Couplers[ Couplers[ end::front ].ConnectedNr ].power_high.is_live ) ) ?
|| ( ( Couplers[ end::front ].CouplingFlag & ctrain_heating )
&& ( Couplers[ end::front ].Connected->Heating ) ) ) ) ?
Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage : Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
0.0 ), 0.0 ),
( ( ( Couplers[end::rear].Connected ) ( ( ( Couplers[end::rear].Connected )
&& ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power ) && ( Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.is_live ) ) ?
|| ( ( Couplers[ end::rear ].CouplingFlag & ctrain_heating )
&& ( Couplers[ end::rear ].Connected->Heating ) ) ) ) ?
Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage : Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
0.0 ) ); 0.0 ) );
} }
@@ -7808,13 +8031,19 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
std::string file = chkpath + TypeName + ".fiz"; std::string file = chkpath + TypeName + ".fiz";
WriteLog("LOAD FIZ FROM " + file); WriteLog("LOAD FIZ FROM " + file);
/*
std::ifstream in(file); std::ifstream in(file);
if (!in.is_open()) if (!in.is_open())
{ {
WriteLog("E8 - FIZ FILE NOT EXIST."); WriteLog("E8 - FIZ FILE NOT EXIST.");
return false; return false;
} }
*/
cParser fizparser( file, cParser::buffer_FILE );
if( false == fizparser.ok() ) {
WriteLog( "E8 - FIZ FILE NOT EXIST." );
return false;
}
ConversionError = 0; ConversionError = 0;
@@ -7822,8 +8051,13 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
std::unordered_map<std::string, std::string> fizlines; std::unordered_map<std::string, std::string> fizlines;
std::string inputline; std::string inputline;
/*
while (std::getline(in, inputline)) while (std::getline(in, inputline))
{ */
while( fizparser.ok() ) {
inputline = fizparser.getToken<std::string>( false, "\n" );
bool comment = ( ( inputline.find('#') != std::string::npos ) bool comment = ( ( inputline.find('#') != std::string::npos )
|| ( inputline.compare( 0, 2, "//" ) == 0 ) ); || ( inputline.compare( 0, 2, "//" ) == 0 ) );
if( true == comment ) { if( true == comment ) {
@@ -7857,7 +8091,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
startRLIST = false; startRLIST = false;
continue; continue;
} }
if (issection("END-RL", inputline)) { if (issection("END-UCL", inputline)) {
startBPT = false; startBPT = false;
startUCLIST = false; startUCLIST = false;
continue; continue;
@@ -8070,7 +8304,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
startBPT = false; startBPT = false;
fizlines.emplace("UCList", inputline); fizlines.emplace("UCList", inputline);
startUCLIST = true; LISTLINE = 0; startUCLIST = true; LISTLINE = 0;
LoadFIZ_RList(inputline); LoadFIZ_UCList(inputline);
continue; continue;
} }
@@ -8124,7 +8358,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue; continue;
} }
if (true == startUCLIST) { if (true == startUCLIST) {
readRList(inputline); readUCList(inputline);
continue; continue;
} }
if( true == startDLIST ) { if( true == startDLIST ) {
@@ -8144,8 +8378,9 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue; continue;
} }
} // while line } // while line
/*
in.close(); in.close();
*/
// Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie // Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie
// zaleznosci // zaleznosci
@@ -8756,6 +8991,8 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
false; false;
extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, ""); extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", line, "");
// main circuit
extract_value( MainsInitTime, "MainInitTime", line, "" );
// converter // converter
{ {
std::map<std::string, start_t> starts { std::map<std::string, start_t> starts {
@@ -8793,6 +9030,9 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
lookup->second : lookup->second :
start_t::manual; start_t::manual;
} }
// pantograph compressor valve
PantAutoValve = ( TrainType == dt_EZT ); // legacy code behaviour, automatic valve was initially installed in all EMUs
extract_value( PantAutoValve, "PantAutoValve", line, "" );
// fuel pump // fuel pump
{ {
auto lookup = starts.find( extract_value( "FuelStart", line ) ); auto lookup = starts.find( extract_value( "FuelStart", line ) );
@@ -8831,9 +9071,9 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
void TMoverParameters::LoadFIZ_Blending(std::string const &line) { void TMoverParameters::LoadFIZ_Blending(std::string const &line) {
extract_value(MED_Vmax, "MED_Vmax", line, to_string(Vmax)); extract_value(MED_Vmax, "MED_Vmax", line, to_string(Vmax));
extract_value(MED_Vmin, "MED_Vmin", line, "0"); extract_value(MED_Vmin, "MED_Vmin", line, "");
extract_value(MED_Vref, "MED_Vref", line, to_string(Vmax)); extract_value(MED_Vref, "MED_Vref", line, to_string(Vmax));
extract_value(MED_amax, "MED_amax", line, "9.81"); extract_value(MED_amax, "MED_amax", line, "");
extract_value(MED_EPVC, "MED_EPVC", line, ""); extract_value(MED_EPVC, "MED_EPVC", line, "");
extract_value(MED_Ncor, "MED_Ncor", line, ""); extract_value(MED_Ncor, "MED_Ncor", line, "");
@@ -8841,10 +9081,10 @@ void TMoverParameters::LoadFIZ_Blending(std::string const &line) {
void TMoverParameters::LoadFIZ_DCEMUED(std::string const &line) { void TMoverParameters::LoadFIZ_DCEMUED(std::string const &line) {
extract_value(DCEMUED_CC, "CouplerCheck", line, "0"); extract_value(DCEMUED_CC, "CouplerCheck", line, "");
extract_value(DCEMUED_EP_max_Vel, "EP_max_Vel", line, "0"); extract_value(DCEMUED_EP_max_Vel, "EP_max_Vel", line, "");
extract_value(DCEMUED_EP_min_Im, "EP_min_Im", line, "0"); extract_value(DCEMUED_EP_min_Im, "EP_min_Im", line, "");
extract_value(DCEMUED_EP_delay, "EP_delay", line, "0"); extract_value(DCEMUED_EP_delay, "EP_delay", line, "");
} }
@@ -8873,12 +9113,13 @@ void TMoverParameters::LoadFIZ_Power( std::string const &Line ) {
EnginePowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "EnginePower", Line ) ); EnginePowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "EnginePower", Line ) );
LoadFIZ_PowerParamsDecode( EnginePowerSource, "", Line ); LoadFIZ_PowerParamsDecode( EnginePowerSource, "", Line );
/*
if( ( EnginePowerSource.SourceType == TPowerSource::Generator ) if( ( EnginePowerSource.SourceType == TPowerSource::Generator )
&& ( EnginePowerSource.GeneratorEngine == TEngineType::WheelsDriven ) ) { && ( EnginePowerSource.GeneratorEngine == TEngineType::WheelsDriven ) ) {
// perpetuum mobile? // perpetuum mobile?
ConversionError = 666; ConversionError = 666;
} }
*/
if( Power == 0.0 ) { if( Power == 0.0 ) {
//jeśli nie ma mocy, np. rozrządcze EZT //jeśli nie ma mocy, np. rozrządcze EZT
EnginePowerSource.SourceType = TPowerSource::NotDefined; EnginePowerSource.SourceType = TPowerSource::NotDefined;
@@ -8934,6 +9175,19 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
extract_value( dizel_nmin, "nmin", Input, "" ); extract_value( dizel_nmin, "nmin", Input, "" );
dizel_nmin /= 60.0; dizel_nmin /= 60.0;
dizel_nreg_min = dizel_nmin * 0.98;
extract_value(dizel_nmin_hdrive, "nmin_hdrive", Input, "");
dizel_nmin_hdrive /= 60.0;
if (dizel_nmin_hdrive == 0.0) {
dizel_nmin_hdrive = dizel_nmin;
}
extract_value(dizel_nmin_hdrive_factor, "nmin_hdrive_factor", Input, "");
dizel_nmin_hdrive_factor /= 60.0;
extract_value(dizel_nmin_retarder, "nmin_retarder", Input, "");
dizel_nmin_retarder /= 60.0;
if (dizel_nmin_retarder == 0.0) {
dizel_nmin_retarder = dizel_nmin;
}
// TODO: unify naming scheme and sort out which diesel engine params are used where and how // TODO: unify naming scheme and sort out which diesel engine params are used where and how
extract_value( nmax, "nmax", Input, "" ); extract_value( nmax, "nmax", Input, "" );
nmax /= 60.0; nmax /= 60.0;
@@ -8968,6 +9222,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
extract_value(hydro_TC_TorqueOutOut, "TC_TOO", Input, ""); extract_value(hydro_TC_TorqueOutOut, "TC_TOO", Input, "");
extract_value(hydro_TC_LockupSpeed, "TC_LS", Input, ""); extract_value(hydro_TC_LockupSpeed, "TC_LS", Input, "");
extract_value(hydro_TC_UnlockSpeed, "TC_ULS", Input, ""); extract_value(hydro_TC_UnlockSpeed, "TC_ULS", Input, "");
extract_value(dizel_maxVelANS, "MaxVelANS", Input, "");
extract_value(hydro_R, "IsRetarder", Input, ""); extract_value(hydro_R, "IsRetarder", Input, "");
if (true == hydro_R) { if (true == hydro_R) {
@@ -8978,6 +9233,7 @@ void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) {
extract_value(hydro_R_FillRateInc, "R_FRI", Input, ""); extract_value(hydro_R_FillRateInc, "R_FRI", Input, "");
extract_value(hydro_R_FillRateDec, "R_FRD", Input, ""); extract_value(hydro_R_FillRateDec, "R_FRD", Input, "");
extract_value(hydro_R_MinVel, "R_MinVel", Input, ""); extract_value(hydro_R_MinVel, "R_MinVel", Input, "");
extract_value(hydro_R_EngageVel, "R_EngageVel", Input, "");
} }
} }
break; break;
@@ -9201,12 +9457,31 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet
} }
case TPowerSource::Transducer: { case TPowerSource::Transducer: {
extract_value( Powerparameters.InputVoltage, Prefix + "TransducerInputV", Line, "" ); extract_value( Powerparameters.Transducer.InputVoltage, Prefix + "TransducerInputV", Line, "" );
break; break;
} }
case TPowerSource::Generator: { case TPowerSource::Generator: {
// prime mover for the generator
auto &generatorparameters { Powerparameters.EngineGenerator };
Powerparameters.GeneratorEngine = LoadFIZ_EngineDecode( extract_value( Prefix + "GeneratorEngine", Line ) ); auto const enginetype { LoadFIZ_EngineDecode( extract_value( Prefix + "GeneratorEngine", Line ) ) };
if( enginetype == TEngineType::Main ) {
generatorparameters.engine_revolutions = &enrot;
}
else {
// TODO: for engine types other than Main create requested engine object and link to its revolutions
generatorparameters.engine_revolutions = nullptr;
generatorparameters.revolutions = 0;
generatorparameters.voltage = 0;
}
// config
extract_value( generatorparameters.voltage_min, Prefix + "GeneratorMinVoltage", Line, "0" );
extract_value( generatorparameters.voltage_max, Prefix + "GeneratorMaxVoltage", Line, "0" );
// NOTE: for consistency the fiz file specifies revolutions per minute
extract_value( generatorparameters.revolutions_min, Prefix + "GeneratorMinRPM", Line, "0" );
extract_value( generatorparameters.revolutions_max, Prefix + "GeneratorMaxRPM", Line, "0" );
generatorparameters.revolutions_min /= 60;
generatorparameters.revolutions_max /= 60;
break; break;
} }
case TPowerSource::Accumulator: { case TPowerSource::Accumulator: {
@@ -9293,7 +9568,8 @@ TPowerSource TMoverParameters::LoadFIZ_SourceDecode( std::string const &Source )
{ "CurrentCollector", TPowerSource::CurrentCollector }, { "CurrentCollector", TPowerSource::CurrentCollector },
{ "PowerCable", TPowerSource::PowerCable }, { "PowerCable", TPowerSource::PowerCable },
{ "Heater", TPowerSource::Heater }, { "Heater", TPowerSource::Heater },
{ "Internal", TPowerSource::InternalSource } { "Internal", TPowerSource::InternalSource },
{ "Main", TPowerSource::Main }
}; };
auto lookup = powersources.find( Source ); auto lookup = powersources.find( Source );
return return
@@ -9312,7 +9588,8 @@ TEngineType TMoverParameters::LoadFIZ_EngineDecode( std::string const &Engine )
{ "Dumb", TEngineType::Dumb }, { "Dumb", TEngineType::Dumb },
{ "DieselElectric", TEngineType::DieselElectric }, { "DieselElectric", TEngineType::DieselElectric },
{ "DumbDE", TEngineType::DieselElectric }, { "DumbDE", TEngineType::DieselElectric },
{ "ElectricInductionMotor", TEngineType::ElectricInductionMotor } { "ElectricInductionMotor", TEngineType::ElectricInductionMotor },
{ "Main", TEngineType::Main }
}; };
auto lookup = enginetypes.find( Engine ); auto lookup = enginetypes.find( Engine );
return return
@@ -9530,6 +9807,17 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
if( LightsPosNo > 0 ) if( LightsPosNo > 0 )
LightsPos = LightsDefPos; LightsPos = LightsDefPos;
// NOTE: legacy compatibility behaviour for vehicles without defined heating power source
if( ( EnginePowerSource.SourceType == TPowerSource::CurrentCollector )
&& ( HeatingPowerSource.SourceType == TPowerSource::NotDefined ) ) {
HeatingPowerSource.SourceType = TPowerSource::Main;
}
if( ( HeatingPowerSource.SourceType == TPowerSource::NotDefined )
&& ( HeatingPower > 0 ) ) {
HeatingPowerSource.SourceType = TPowerSource::PowerCable;
HeatingPowerSource.PowerType = TPowerType::ElectricPower;
}
// checking ready flag // checking ready flag
// to dac potem do init // to dac potem do init
if( ReadyFlag ) // gotowy do drogi if( ReadyFlag ) // gotowy do drogi

View File

@@ -57,7 +57,7 @@ TModelsManager::LoadModel(std::string const &Name, bool dynamic) {
} }
TModel3d * TModel3d *
TModelsManager::GetModel(std::string const &Name, bool const Dynamic) TModelsManager::GetModel(std::string const &Name, bool const Dynamic, bool const Logerrors )
{ // model może być we wpisie "node...model" albo "node...dynamic", a także być dodatkowym w dynamic { // model może być we wpisie "node...model" albo "node...dynamic", a także być dodatkowym w dynamic
// (kabina, wnętrze, ładunek) // (kabina, wnętrze, ładunek)
// dla "node...dynamic" mamy podaną ścieżkę w "\dynamic\" i musi być co najmniej 1 poziom, zwkle // dla "node...dynamic" mamy podaną ścieżkę w "\dynamic\" i musi być co najmniej 1 poziom, zwkle
@@ -106,7 +106,9 @@ TModelsManager::GetModel(std::string const &Name, bool const Dynamic)
} }
else { else {
// there's nothing matching in the databank nor on the disk, report failure... // there's nothing matching in the databank nor on the disk, report failure...
ErrorLog( "Bad file: failed do locate 3d model file \"" + filename + "\"", logtype::file ); if( Logerrors ) {
ErrorLog( "Bad file: failed do locate 3d model file \"" + filename + "\"", logtype::file );
}
// ...and link it with the error model slot // ...and link it with the error model slot
m_modelsmap.emplace( filename, null_handle ); m_modelsmap.emplace( filename, null_handle );
} }

View File

@@ -22,7 +22,7 @@ private:
class TModelsManager { class TModelsManager {
public: public:
// McZapkie: dodalem sciezke, notabene Path!=Patch :) // McZapkie: dodalem sciezke, notabene Path!=Patch :)
static TModel3d *GetModel( std::string const &Name, bool dynamic = false ); static TModel3d *GetModel( std::string const &Name, bool const dynamic = false, bool const Logerrors = true );
private: private:
// types: // types:

View File

@@ -86,16 +86,7 @@ Commands will be written in [`Bash`](https://www.gnu.org/software/bash/). No-Lin
- `_d` is debug flag. - `_d` is debug flag.
If you currently have MaSzyna assets, just copy executable to install directory. If you currently have MaSzyna assets, just copy executable to install directory.
Else you must download and unpack assets. You can download assets from [eu07.pl](https://eu07.pl/).
Links:
- http://eu07.pl/theme/MaSzyna1803.zip
- http://eu07.pl/theme/MaSzynaP1805.zip
- http://eu07.pl/theme/MaSzynaP1806.zip
- http://eu07.pl/theme/MaSzynaP1807.zip
- http://stuff.eu07.pl/MaSzynaP1810.zip
Override every file.
**Note:** Linux users may have issue, that `Rainsted` (third party starter), may not detect executable. In that case it is possible, to simulate Windows executable, by creation shell script, like this: **Note:** Linux users may have issue, that `Rainsted` (third party starter), may not detect executable. In that case it is possible, to simulate Windows executable, by creation shell script, like this:

View File

@@ -529,7 +529,7 @@ glm::vec3
TTraction::wire_color() const { TTraction::wire_color() const {
glm::vec3 color; glm::vec3 color;
if( !DebugModeFlag || GfxRenderer.settings.force_normal_traction_render ) if( !GfxRenderer.settings.traction_debug )
{ {
switch( Material ) { // Ra: kolory podzieliłem przez 2, bo po zmianie ambient za jasne były switch( Material ) { // Ra: kolory podzieliłem przez 2, bo po zmianie ambient za jasne były
// trzeba uwzględnić kierunek świecenia Słońca - tylko ze Słońcem widać kolor // trzeba uwzględnić kierunek świecenia Słońca - tylko ze Słońcem widać kolor

View File

@@ -15,6 +15,8 @@ http://mozilla.org/MPL/2.0/.
class TTractionPowerSource : public scene::basic_node { class TTractionPowerSource : public scene::basic_node {
friend class debug_panel;
public: public:
// constructor // constructor
TTractionPowerSource( scene::node_data const &Nodedata ); TTractionPowerSource( scene::node_data const &Nodedata );

View File

@@ -17,8 +17,9 @@ http://mozilla.org/MPL/2.0/.
#include "Globals.h" #include "Globals.h"
#include "simulation.h" #include "simulation.h"
#include "Camera.h" #include "Event.h"
#include "simulationtime.h" #include "simulationtime.h"
#include "Camera.h"
#include "Logs.h" #include "Logs.h"
#include "MdlMngr.h" #include "MdlMngr.h"
#include "Model3d.h" #include "Model3d.h"
@@ -340,6 +341,7 @@ TTrain::commandhandler_map const TTrain::m_commandhandlers = {
{ user_command::radiochanneldecrease, &TTrain::OnCommand_radiochanneldecrease }, { user_command::radiochanneldecrease, &TTrain::OnCommand_radiochanneldecrease },
{ user_command::radiostopsend, &TTrain::OnCommand_radiostopsend }, { user_command::radiostopsend, &TTrain::OnCommand_radiostopsend },
{ user_command::radiostoptest, &TTrain::OnCommand_radiostoptest }, { user_command::radiostoptest, &TTrain::OnCommand_radiostoptest },
{ user_command::radiocall3send, &TTrain::OnCommand_radiocall3send },
{ user_command::cabchangeforward, &TTrain::OnCommand_cabchangeforward }, { user_command::cabchangeforward, &TTrain::OnCommand_cabchangeforward },
{ user_command::cabchangebackward, &TTrain::OnCommand_cabchangebackward }, { user_command::cabchangebackward, &TTrain::OnCommand_cabchangebackward },
{ user_command::generictoggle0, &TTrain::OnCommand_generictoggle }, { user_command::generictoggle0, &TTrain::OnCommand_generictoggle },
@@ -457,6 +459,8 @@ dictionary_source *TTrain::GetTrainState() {
// basic systems state data // basic systems state data
dict->insert( "battery", mvControlled->Battery ); dict->insert( "battery", mvControlled->Battery );
dict->insert( "linebreaker", mvControlled->Mains ); dict->insert( "linebreaker", mvControlled->Mains );
dict->insert( "main_init", ( mvControlled->MainsInitTimeCountdown < mvControlled->MainsInitTime ) && ( mvControlled->MainsInitTimeCountdown > 0.0 ) );
dict->insert( "main_ready", ( false == mvControlled->Mains ) && ( fHVoltage > 0.0 ) && ( mvControlled->MainsInitTimeCountdown <= 0.0 ) );
dict->insert( "converter", mvControlled->ConverterFlag ); dict->insert( "converter", mvControlled->ConverterFlag );
dict->insert( "converter_overload", mvControlled->ConvOvldFlag ); dict->insert( "converter_overload", mvControlled->ConvOvldFlag );
dict->insert( "compress", mvControlled->CompressorFlag ); dict->insert( "compress", mvControlled->CompressorFlag );
@@ -4713,10 +4717,10 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
if( Train->mvOccupied->Doors.has_autowarning ) { if( Train->mvOccupied->Doors.has_autowarning ) {
// automatic departure signal delays actual door closing until the button is released
Train->mvOccupied->signal_departure( true ); Train->mvOccupied->signal_departure( true );
} }
else { if( Train->ggDoorAllOffButton.type() != TGaugeType::push_delayed ) {
// delays the action until the button is released
Train->mvOccupied->OperateDoors( side::right, false ); Train->mvOccupied->OperateDoors( side::right, false );
Train->mvOccupied->OperateDoors( side::left, false ); Train->mvOccupied->OperateDoors( side::left, false );
} }
@@ -4727,10 +4731,10 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
Train->ggDoorAllOffButton.UpdateValue( 1.0, Train->dsbSwitch ); Train->ggDoorAllOffButton.UpdateValue( 1.0, Train->dsbSwitch );
} }
else if( Command.action == GLFW_RELEASE ) { else if( Command.action == GLFW_RELEASE ) {
// release the button
if( Train->mvOccupied->Doors.has_autowarning ) { if( Train->mvOccupied->Doors.has_autowarning ) {
// automatic departure signal delays actual door closing until the button is released
Train->mvOccupied->signal_departure( false ); Train->mvOccupied->signal_departure( false );
}
if( Train->ggDoorAllOffButton.type() == TGaugeType::push_delayed ) {
// now we can actually close the door // now we can actually close the door
Train->mvOccupied->OperateDoors( side::right, false ); Train->mvOccupied->OperateDoors( side::right, false );
Train->mvOccupied->OperateDoors( side::left, false ); Train->mvOccupied->OperateDoors( side::left, false );
@@ -5006,6 +5010,7 @@ void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
if( ( Train->RadioChannel() == 10 ) if( ( Train->RadioChannel() == 10 )
&& ( true == Train->mvOccupied->Radio )
&& ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) { && ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) {
Train->Dynamic()->RadioStop(); Train->Dynamic()->RadioStop();
} }
@@ -5018,6 +5023,23 @@ void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command
} }
} }
void TTrain::OnCommand_radiocall3send( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) {
if( ( Train->RadioChannel() != 10 )
&& ( true == Train->mvOccupied->Radio )
&& ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) {
simulation::Events.queue_receivers( radio_message::call3, Train->Dynamic()->GetPosition() );
}
// visual feedback
Train->ggRadioCall3.UpdateValue( 1.0 );
}
else if( Command.action == GLFW_RELEASE ) {
// visual feedback
Train->ggRadioCall3.UpdateValue( 0.0 );
}
}
void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ) { void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ) {
if( Command.action == GLFW_PRESS ) { if( Command.action == GLFW_PRESS ) {
@@ -5032,6 +5054,10 @@ void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Comm
Train->MoveToVehicle(dynobj); Train->MoveToVehicle(dynobj);
} }
} }
// HACK: match consist door permit state with the preset in the active cab
if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) {
Train->mvOccupied->ChangeDoorPermitPreset( 0 );
}
} }
} }
@@ -5049,6 +5075,10 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com
Train->MoveToVehicle(dynobj); Train->MoveToVehicle(dynobj);
} }
} }
// HACK: match consist door permit state with the preset in the active cab
if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) {
Train->mvOccupied->ChangeDoorPermitPreset( 0 );
}
} }
} }
@@ -5127,10 +5157,11 @@ bool TTrain::Update( double const Deltatime )
if( ( ggMainButton.GetDesiredValue() > 0.95 ) if( ( ggMainButton.GetDesiredValue() > 0.95 )
|| ( ggMainOnButton.GetDesiredValue() > 0.95 ) ) { || ( ggMainOnButton.GetDesiredValue() > 0.95 ) ) {
// keep track of period the line breaker button is held down, to determine when/if circuit closes // keep track of period the line breaker button is held down, to determine when/if circuit closes
if( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage ) if( ( mvControlled->MainsInitTimeCountdown <= 0.0 )
|| ( ( mvControlled->EngineType != TEngineType::ElectricSeriesMotor ) && ( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage )
&& ( mvControlled->EngineType != TEngineType::ElectricInductionMotor ) || ( ( mvControlled->EngineType != TEngineType::ElectricSeriesMotor )
&& ( true == mvControlled->Battery ) ) ) { && ( mvControlled->EngineType != TEngineType::ElectricInductionMotor )
&& ( true == mvControlled->Battery ) ) ) ) {
// prevent the switch from working if there's no power // prevent the switch from working if there's no power
// TODO: consider whether it makes sense for diesel engines and such // TODO: consider whether it makes sense for diesel engines and such
fMainRelayTimer += Deltatime; fMainRelayTimer += Deltatime;
@@ -5640,9 +5671,10 @@ bool TTrain::Update( double const Deltatime )
|| (true == mvControlled->Mains) ) ? || (true == mvControlled->Mains) ) ?
true : true :
false ) ); false ) );
// NOTE: 'off' variant uses the same test, but opposite resulting states
btLampkaWylSzybkiOff.Turn( btLampkaWylSzybkiOff.Turn(
( ( ( m_linebreakerstate == 2 ) ( ( ( mvControlled->MainsInitTimeCountdown > 0.0 )
|| ( fHVoltage == 0.0 )
|| ( m_linebreakerstate == 2 )
|| ( true == mvControlled->Mains ) ) ? || ( true == mvControlled->Mains ) ) ?
false : false :
true ) ); true ) );
@@ -5874,7 +5906,7 @@ bool TTrain::Update( double const Deltatime )
auto const *mover { tmp->MoverParameters }; auto const *mover { tmp->MoverParameters };
btLampkaWylSzybkiB.Turn( mover->Mains ); btLampkaWylSzybkiB.Turn( mover->Mains );
btLampkaWylSzybkiBOff.Turn( false == mover->Mains ); btLampkaWylSzybkiBOff.Turn( ( false == mover->Mains ) && ( mover->MainsInitTimeCountdown <= 0.0 ) && ( fHVoltage != 0.0 ) );
btLampkaOporyB.Turn(mover->ResistorsFlagCheck()); btLampkaOporyB.Turn(mover->ResistorsFlagCheck());
btLampkaBezoporowaB.Turn( btLampkaBezoporowaB.Turn(
@@ -6129,6 +6161,7 @@ bool TTrain::Update( double const Deltatime )
ggRadioChannelNext.Update(); ggRadioChannelNext.Update();
ggRadioStop.Update(); ggRadioStop.Update();
ggRadioTest.Update(); ggRadioTest.Update();
ggRadioCall3.Update();
ggDepartureSignalButton.Update(); ggDepartureSignalButton.Update();
ggPantFrontButton.Update(); ggPantFrontButton.Update();
@@ -7479,6 +7512,7 @@ void TTrain::clear_cab_controls()
ggRadioChannelNext.Clear(); ggRadioChannelNext.Clear();
ggRadioStop.Clear(); ggRadioStop.Clear();
ggRadioTest.Clear(); ggRadioTest.Clear();
ggRadioCall3.Clear();
ggDoorLeftPermitButton.Clear(); ggDoorLeftPermitButton.Clear();
ggDoorRightPermitButton.Clear(); ggDoorRightPermitButton.Clear();
ggDoorPermitPresetButton.Clear(); ggDoorPermitPresetButton.Clear();
@@ -7796,7 +7830,7 @@ void TTrain::set_cab_controls( int const Cab ) {
TimetableLightActive ? TimetableLightActive ?
1.f : 1.f :
0.f ) ); 0.f ) );
// doors // doors permits
if( ggDoorLeftPermitButton.type() != TGaugeType::push ) { if( ggDoorLeftPermitButton.type() != TGaugeType::push ) {
ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit ? 1.f : 0.f ); ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit ? 1.f : 0.f );
} }
@@ -7804,6 +7838,7 @@ void TTrain::set_cab_controls( int const Cab ) {
ggDoorRightPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit ? 1.f : 0.f ); ggDoorRightPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].open_permit ? 1.f : 0.f );
} }
ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset ); ggDoorPermitPresetButton.PutValue( mvOccupied->Doors.permit_preset );
// door controls
ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].is_closed ? 0.f : 1.f ); ggDoorLeftButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].is_closed ? 0.f : 1.f );
ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f ); ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f );
// door lock // door lock
@@ -8164,6 +8199,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "radiochannelnext_sw:", ggRadioChannelNext }, { "radiochannelnext_sw:", ggRadioChannelNext },
{ "radiostop_sw:", ggRadioStop }, { "radiostop_sw:", ggRadioStop },
{ "radiotest_sw:", ggRadioTest }, { "radiotest_sw:", ggRadioTest },
{ "radiocall3_sw:", ggRadioCall3 },
{ "pantfront_sw:", ggPantFrontButton }, { "pantfront_sw:", ggPantFrontButton },
{ "pantrear_sw:", ggPantRearButton }, { "pantrear_sw:", ggPantRearButton },
{ "pantfrontoff_sw:", ggPantFrontButtonOff }, { "pantfrontoff_sw:", ggPantFrontButtonOff },

View File

@@ -347,6 +347,7 @@ class TTrain
static void OnCommand_radiochanneldecrease( TTrain *Train, command_data const &Command ); static void OnCommand_radiochanneldecrease( TTrain *Train, command_data const &Command );
static void OnCommand_radiostopsend( TTrain *Train, command_data const &Command ); static void OnCommand_radiostopsend( TTrain *Train, command_data const &Command );
static void OnCommand_radiostoptest( TTrain *Train, command_data const &Command ); static void OnCommand_radiostoptest( TTrain *Train, command_data const &Command );
static void OnCommand_radiocall3send( TTrain *Train, command_data const &Command );
static void OnCommand_cabchangeforward( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangeforward( TTrain *Train, command_data const &Command );
static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command ); static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command );
static void OnCommand_generictoggle( TTrain *Train, command_data const &Command ); static void OnCommand_generictoggle( TTrain *Train, command_data const &Command );
@@ -419,6 +420,7 @@ public: // reszta może by?publiczna
TGauge ggRadioChannelNext; TGauge ggRadioChannelNext;
TGauge ggRadioTest; TGauge ggRadioTest;
TGauge ggRadioStop; TGauge ggRadioStop;
TGauge ggRadioCall3;
TGauge ggUpperLightButton; TGauge ggUpperLightButton;
TGauge ggLeftLightButton; TGauge ggLeftLightButton;
TGauge ggRightLightButton; TGauge ggRightLightButton;

View File

@@ -101,7 +101,7 @@ bool TTrackFollower::Move(double fDistance, bool bPrimary)
{ // przesuwanie wózka po torach o odległość (fDistance), z wyzwoleniem eventów { // przesuwanie wózka po torach o odległość (fDistance), z wyzwoleniem eventów
// bPrimary=true - jest pierwszą osią w pojeździe, czyli generuje eventy i przepisuje pojazd // bPrimary=true - jest pierwszą osią w pojeździe, czyli generuje eventy i przepisuje pojazd
// Ra: zwraca false, jeśli pojazd ma być usunięty // Ra: zwraca false, jeśli pojazd ma być usunięty
auto const ismoving { ( std::abs( fDistance ) > 0.01 ) && ( Owner->GetVelocity() > 0.01 ) }; auto const ismoving { /* ( std::abs( fDistance ) > 0.01 ) && */ ( Owner->GetVelocity() > 0.01 ) };
fDistance *= fDirection; // dystans mnożnony przez kierunek fDistance *= fDirection; // dystans mnożnony przez kierunek
double s; // roboczy dystans double s; // roboczy dystans
double dir; // zapamiętany kierunek do sprawdzenia, czy się zmienił double dir; // zapamiętany kierunek do sprawdzenia, czy się zmienił

View File

@@ -23,7 +23,7 @@ jobs:
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
inputs: inputs:
pathtoPublish: 'build/bin' pathtoPublish: 'build/bin'
artifactName: binaries artifactName: binaries_linux
displayName: 'Publish binaries' displayName: 'Publish binaries'
- job: macos1013 - job: macos1013
@@ -43,7 +43,7 @@ jobs:
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
inputs: inputs:
pathtoPublish: 'build/bin' pathtoPublish: 'build/bin'
artifactName: binaries artifactName: binaries_macos
displayName: 'Publish binaries' displayName: 'Publish binaries'
- job: windows_x64 - job: windows_x64
@@ -64,12 +64,12 @@ jobs:
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
inputs: inputs:
pathtoPublish: 'build/bin' pathtoPublish: 'build/bin'
artifactName: binaries artifactName: binaries_win64
displayName: 'Publish binaries' displayName: 'Publish binaries'
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
inputs: inputs:
pathtoPublish: 'build/pdb' pathtoPublish: 'build/pdb'
artifactName: symbols artifactName: binaries_win64
displayName: 'Publish symbols' displayName: 'Publish symbols'
- job: windows_x32 - job: windows_x32
@@ -90,10 +90,10 @@ jobs:
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
inputs: inputs:
pathtoPublish: 'build/bin' pathtoPublish: 'build/bin'
artifactName: binaries artifactName: binaries_win32
displayName: 'Publish binaries' displayName: 'Publish binaries'
- task: PublishBuildArtifacts@1 - task: PublishBuildArtifacts@1
inputs: inputs:
pathtoPublish: 'build/pdb' pathtoPublish: 'build/pdb'
artifactName: symbols artifactName: binaries_win32
displayName: 'Publish symbols' displayName: 'Publish symbols'

View File

@@ -125,6 +125,7 @@ commanddescription_sequence Commands_descriptions = {
{ "radiochanneldecrease", command_target::vehicle, command_mode::oneoff }, { "radiochanneldecrease", command_target::vehicle, command_mode::oneoff },
{ "radiostopsend", command_target::vehicle, command_mode::oneoff }, { "radiostopsend", command_target::vehicle, command_mode::oneoff },
{ "radiostoptest", command_target::vehicle, command_mode::oneoff }, { "radiostoptest", command_target::vehicle, command_mode::oneoff },
{ "radiocall3send", command_target::vehicle, command_mode::oneoff },
// TBD, TODO: make cab change controls entity-centric // TBD, TODO: make cab change controls entity-centric
{ "cabchangeforward", command_target::vehicle, command_mode::oneoff }, { "cabchangeforward", command_target::vehicle, command_mode::oneoff },
{ "cabchangebackward", command_target::vehicle, command_mode::oneoff }, { "cabchangebackward", command_target::vehicle, command_mode::oneoff },

View File

@@ -119,6 +119,7 @@ enum class user_command {
radiochanneldecrease, radiochanneldecrease,
radiostopsend, radiostopsend,
radiostoptest, radiostoptest,
radiocall3send,
cabchangeforward, cabchangeforward,
cabchangebackward, cabchangebackward,

View File

@@ -127,6 +127,7 @@ driverkeyboard_input::default_bindings() {
{ user_command::radiochanneldecrease, GLFW_KEY_R }, { user_command::radiochanneldecrease, GLFW_KEY_R },
{ user_command::radiostopsend, GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control }, { user_command::radiostopsend, GLFW_KEY_PAUSE | keymodifier::shift | keymodifier::control },
{ user_command::radiostoptest, GLFW_KEY_R | keymodifier::shift | keymodifier::control }, { user_command::radiostoptest, GLFW_KEY_R | keymodifier::shift | keymodifier::control },
{ user_command::radiocall3send, GLFW_KEY_BACKSPACE },
{ user_command::cabchangeforward, GLFW_KEY_HOME }, { user_command::cabchangeforward, GLFW_KEY_HOME },
{ user_command::cabchangebackward, GLFW_KEY_END }, { user_command::cabchangebackward, GLFW_KEY_END },
// viewturn, // viewturn,

View File

@@ -719,6 +719,9 @@ drivermouse_input::default_bindings() {
{ "radiotest_sw:", { { "radiotest_sw:", {
user_command::radiostoptest, user_command::radiostoptest,
user_command::none } }, user_command::none } },
{ "radiocall3_sw:", {
user_command::radiocall3send,
user_command::none } },
{ "pantfront_sw:", { { "pantfront_sw:", {
user_command::pantographtogglefront, user_command::pantographtogglefront,
user_command::none } }, user_command::none } },

View File

@@ -44,7 +44,7 @@ driver_ui::driver_ui() {
m_scenariopanel.size_max = { Global.iWindowWidth * 0.95, Global.iWindowHeight * 0.95 }; m_scenariopanel.size_max = { Global.iWindowWidth * 0.95, Global.iWindowHeight * 0.95 };
m_timetablepanel.title = STR("%-*.*s Time: %d:%02d:%02d"); m_timetablepanel.title = STR("%-*.*s Time: %d:%02d:%02d");
m_timetablepanel.size_min = { 435, 110 }; m_timetablepanel.size_min = { 435, 70};
m_timetablepanel.size_max = { 435, Global.iWindowHeight * 0.95 }; m_timetablepanel.size_max = { 435, Global.iWindowHeight * 0.95 };
m_transcriptspanel.title = STR("Transcripts"); m_transcriptspanel.title = STR("Transcripts");

File diff suppressed because it is too large Load Diff

View File

@@ -85,6 +85,7 @@ private:
void update_section_scantable( std::vector<text_line> &Output ); void update_section_scantable( std::vector<text_line> &Output );
void update_section_scenario( std::vector<text_line> &Output ); void update_section_scenario( std::vector<text_line> &Output );
void update_section_eventqueue( std::vector<text_line> &Output ); void update_section_eventqueue( std::vector<text_line> &Output );
void update_section_powergrid( std::vector<text_line> &Output );
void update_section_camera( std::vector<text_line> &Output ); void update_section_camera( std::vector<text_line> &Output );
void update_section_renderer( std::vector<text_line> &Output ); void update_section_renderer( std::vector<text_line> &Output );
// section update helpers // section update helpers
@@ -103,6 +104,7 @@ private:
m_cameralines, m_cameralines,
m_scenariolines, m_scenariolines,
m_eventqueuelines, m_eventqueuelines,
m_powergridlines,
m_rendererlines; m_rendererlines;
int tprev { 0 }; // poprzedni czas int tprev { 0 }; // poprzedni czas
double VelPrev { 0.0 }; // poprzednia prędkość double VelPrev { 0.0 }; // poprzednia prędkość

View File

@@ -550,6 +550,7 @@ void TTrainParameters::serialize( dictionary_source *Output ) const {
Output->insert( ( stationlabel + "am" ), timetableline.Am ); Output->insert( ( stationlabel + "am" ), timetableline.Am );
Output->insert( ( stationlabel + "dh" ), timetableline.Dh ); Output->insert( ( stationlabel + "dh" ), timetableline.Dh );
Output->insert( ( stationlabel + "dm" ), timetableline.Dm ); Output->insert( ( stationlabel + "dm" ), timetableline.Dm );
Output->insert( ( stationlabel + "tracks" ), timetableline.TrackNo );
} }
} }
} }

View File

@@ -124,8 +124,7 @@ class opengl_renderer
/// Renderer runtime settings /// Renderer runtime settings
struct Settings struct Settings
{ {
/** Force normal render of traction, when user is in debug mode. */ bool traction_debug { false };
bool force_normal_traction_render { false };
} settings; } settings;
// methods // methods

View File

@@ -531,7 +531,10 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch
} }
else { else {
scene::Groups.insert( scene::Groups.handle(), eventlauncher ); scene::Groups.insert( scene::Groups.handle(), eventlauncher );
simulation::Region->insert( eventlauncher ); if( false == eventlauncher->IsRadioActivated() ) {
// NOTE: radio-activated launchers due to potentially large activation radius are resolved on global level rather than put in a region cell
simulation::Region->insert( eventlauncher );
}
} }
} }
else if( nodedata.type == "sound" ) { else if( nodedata.type == "sound" ) {

View File

@@ -246,6 +246,7 @@ std::string locale::label_cab_control(std::string const &Label)
{ "radiochannelnext_sw:", STRN("radio channel") }, { "radiochannelnext_sw:", STRN("radio channel") },
{ "radiotest_sw:", STRN("radiostop test") }, { "radiotest_sw:", STRN("radiostop test") },
{ "radiostop_sw:", STRN("radiostop") }, { "radiostop_sw:", STRN("radiostop") },
{ "radiocall3_sw:", STRN("radio call 3") },
{ "pantfront_sw:", STRN("pantograph A") }, { "pantfront_sw:", STRN("pantograph A") },
{ "pantrear_sw:", STRN("pantograph B") }, { "pantrear_sw:", STRN("pantograph B") },
{ "pantfrontoff_sw:", STRN("pantograph A") }, { "pantfrontoff_sw:", STRN("pantograph A") },

View File

@@ -1 +1 @@
#define VERSION_INFO "M7 (sim) 23.05.2019" #define VERSION_INFO "M7 (sim) 13.07.2019"

View File

@@ -74,9 +74,9 @@ void ui::vehicleparams_panel::render_contents()
// power transfers // power transfers
mover.Couplers[ end::front ].power_high.voltage, mover.Couplers[ end::front ].power_high.voltage,
mover.Couplers[ end::front ].power_high.current, mover.Couplers[ end::front ].power_high.current,
std::string( mover.Couplers[ end::front ].power_high.local ? "" : "-" ).c_str(), std::string( mover.Couplers[ end::front ].power_high.is_local ? "" : "-" ).c_str(),
std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(), std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(),
std::string( mover.Couplers[ end::rear ].power_high.local ? "" : "-" ).c_str(), std::string( mover.Couplers[ end::rear ].power_high.is_local ? "" : "-" ).c_str(),
mover.Couplers[ end::rear ].power_high.voltage, mover.Couplers[ end::rear ].power_high.voltage,
mover.Couplers[ end::rear ].power_high.current ); mover.Couplers[ end::rear ].power_high.current );