mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-20 14:49:20 +02:00
Merge with TMJ
This commit is contained in:
108
Driver.cpp
108
Driver.cpp
@@ -2133,7 +2133,10 @@ bool TController::CheckVehicles(TOrders user)
|
||||
// NOTE: don't set battery in the occupied vehicle, let the user/ai do it explicitly
|
||||
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 ) {
|
||||
p->MoverParameters->HeatingAllow = true;
|
||||
p->MoverParameters->ConverterSwitch( true, range_t::local );
|
||||
@@ -2456,7 +2459,7 @@ bool TController::PrepareEngine()
|
||||
mvOccupied->PantRear( true );
|
||||
if (mvControlling->PantPress < 4.2) {
|
||||
// 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ć
|
||||
mvControlling->bPantKurek3 = false;
|
||||
}
|
||||
@@ -2529,14 +2532,14 @@ bool TController::PrepareEngine()
|
||||
}
|
||||
else {
|
||||
OK = ( OrderDirectionChange( iDirection, mvOccupied ) == -1 );
|
||||
mvOccupied->ConverterSwitch( true );
|
||||
mvControlling->ConverterSwitch( true );
|
||||
// w EN57 sprężarka w ra jest zasilana z silnikowego
|
||||
mvOccupied->CompressorSwitch( true );
|
||||
mvControlling->CompressorSwitch( true );
|
||||
// enable motor blowers
|
||||
mvOccupied->MotorBlowersSwitchOff( false, end::front );
|
||||
mvOccupied->MotorBlowersSwitch( true, end::front );
|
||||
mvOccupied->MotorBlowersSwitchOff( false, end::rear );
|
||||
mvOccupied->MotorBlowersSwitch( true, end::rear );
|
||||
mvControlling->MotorBlowersSwitchOff( false, end::front );
|
||||
mvControlling->MotorBlowersSwitch( true, end::front );
|
||||
mvControlling->MotorBlowersSwitchOff( false, end::rear );
|
||||
mvControlling->MotorBlowersSwitch( true, end::rear );
|
||||
// enable train brake if it's off
|
||||
if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) {
|
||||
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) );
|
||||
@@ -2550,6 +2553,14 @@ bool TController::PrepareEngine()
|
||||
if( lookup != brakepositions.end() ) {
|
||||
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
|
||||
@@ -2632,7 +2643,9 @@ bool TController::ReleaseEngine() {
|
||||
mvOccupied->OperateDoors( side::left, false );
|
||||
|
||||
if( true == mvControlling->Mains ) {
|
||||
mvControlling->CompressorSwitch( false );
|
||||
// heating
|
||||
mvControlling->HeatingAllow = false;
|
||||
// devices
|
||||
mvControlling->ConverterSwitch( false );
|
||||
// line breaker/engine
|
||||
OK = mvControlling->MainSwitch( false );
|
||||
@@ -3533,29 +3546,56 @@ void TController::SetTimeControllers()
|
||||
//5.1. Digital controller in DMUs with hydro
|
||||
if ((mvControlling->EngineType == TEngineType::DieselEngine) && (mvControlling->EIMCtrlType == 3))
|
||||
{
|
||||
DizelPercentage_Speed = DizelPercentage;
|
||||
double Factor = 10 * (mvControlling->Vmax) / (mvControlling->Vmax + 3*mvControlling->Vel);
|
||||
double DesiredPercentage = (VelDesired > mvControlling->Vel ? (VelDesired - mvControlling->Vel) / Factor : 0);
|
||||
DesiredPercentage = clamp(DesiredPercentage, 0.0, 1.0);
|
||||
if (VelDesired < 0.5 * mvControlling->Vmax && VelDesired - mvControlling->Vel < 10)
|
||||
DesiredPercentage = std::min(DesiredPercentage, 0.75);
|
||||
int DizelActualPercentage = 100.4 * mvControlling->eimic_real;
|
||||
int PosInc = mvControlling->MainCtrlPosNo;
|
||||
int PosDec = 0;
|
||||
for(int i=PosInc;i>=0;i--)
|
||||
if ((mvControlling->UniCtrlList[i].SetCtrlVal <= 0) && (mvControlling->UniCtrlList[i].SpeedDown > 0.01))
|
||||
{
|
||||
PosDec = i;
|
||||
break;
|
||||
}
|
||||
DizelPercentage_Speed = round(double(DizelPercentage*DesiredPercentage));
|
||||
if (VelDesired < std::min(mvControlling->hydro_TC_LockupSpeed,mvControlling->Vmax / 5)) DizelPercentage = std::min(DizelPercentage_Speed, 1);
|
||||
if (abs(DizelPercentage_Speed - DizelActualPercentage)>(DizelPercentage>1?3:0))
|
||||
{
|
||||
if (((DizelPercentage_Speed == 0 && DizelActualPercentage > 10) || (DizelActualPercentage - DizelPercentage_Speed > 50)) && PosDec > 0) PosDec -= 1; //pozycję wczesniej powinno byc szybkie zejscie, jeśli trzeba
|
||||
int DesiredPos = (DizelPercentage_Speed > DizelActualPercentage ? PosInc : PosDec);
|
||||
while (mvControlling->MainCtrlPos > DesiredPos) mvControlling->DecMainCtrl(1);
|
||||
while (mvControlling->MainCtrlPos < DesiredPos) mvControlling->IncMainCtrl(1);
|
||||
if( mvControlling->Vel > 10 ) {
|
||||
|
||||
DizelPercentage_Speed = DizelPercentage;
|
||||
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 ) };
|
||||
if( ( VelDesired < 0.5 * mvControlling->Vmax )
|
||||
&& ( VelDesired - mvControlling->Vel < 10 ) ) {
|
||||
DesiredPercentage = std::min( DesiredPercentage, 0.75 );
|
||||
}
|
||||
DizelPercentage_Speed = std::round( DesiredPercentage * DizelPercentage );
|
||||
if( VelDesired < std::min( mvControlling->hydro_TC_LockupSpeed, mvControlling->Vmax / 5 ) ) {
|
||||
DizelPercentage = std::min( DizelPercentage_Speed, 1 );
|
||||
}
|
||||
}
|
||||
else {
|
||||
// HACK: workaround for the default mode breaking at low speeds
|
||||
DizelPercentage = DizelPercentage_Speed = ( AccDesired > 0.0 ? 100 : 0 );
|
||||
}
|
||||
|
||||
auto const DizelActualPercentage { 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 ? 3 : 0 ) ) {
|
||||
|
||||
if( ( PosDec > 0 )
|
||||
&& ( ( DizelActualPercentage - DizelPercentage_Speed > 50 )
|
||||
|| ( ( DizelPercentage_Speed == 0 )
|
||||
&& ( DizelActualPercentage > 10 ) ) ) ) {
|
||||
//pozycję wczesniej powinno byc szybkie zejscie, jeśli trzeba
|
||||
PosDec -= 1;
|
||||
}
|
||||
auto const DesiredPos { (
|
||||
DizelPercentage_Speed > DizelActualPercentage ?
|
||||
PosInc :
|
||||
PosDec ) };
|
||||
while( mvControlling->MainCtrlPos > DesiredPos ) { mvControlling->DecMainCtrl( 1 ); }
|
||||
while( mvControlling->MainCtrlPos < DesiredPos ) { mvControlling->IncMainCtrl( 1 ); }
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5145,6 +5185,7 @@ TController::UpdateSituation(double dt) {
|
||||
// za radą yB ustawiamy pozycję 3 kranu (ruszanie kranem w innych miejscach
|
||||
// powino zostać wyłączone)
|
||||
// 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 ) {
|
||||
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_EPB ) );
|
||||
}
|
||||
@@ -5392,7 +5433,8 @@ TController::UpdateSituation(double dt) {
|
||||
exchangetime = std::max( exchangetime, vehicle->LoadExchangeTime() );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
34
DynObj.cpp
34
DynObj.cpp
@@ -2702,10 +2702,11 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
if (v == 0.0) {
|
||||
v = MoverParameters->PantFrontVolt;
|
||||
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
|
||||
// NOTE: condition disabled, other vehicles types can have power cables as well
|
||||
v = MoverParameters->GetTrainsetVoltage(); // ostatnia szansa
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
if (v != 0.0)
|
||||
@@ -5776,23 +5777,28 @@ TDynamicObject::LoadMMediaFile_mdload( std::string const &Name ) const {
|
||||
TModel3d *loadmodel { nullptr };
|
||||
|
||||
// check if we don't have model override for this load type
|
||||
auto const lookup { LoadModelOverrides.find( Name ) };
|
||||
if( lookup != LoadModelOverrides.end() ) {
|
||||
loadmodel = TModelsManager::GetModel( asBaseDir + lookup->second, true );
|
||||
// if the override was succesfully loaded call it a day
|
||||
if( loadmodel != nullptr ) { return loadmodel; }
|
||||
{
|
||||
auto const lookup { LoadModelOverrides.find( Name ) };
|
||||
if( lookup != LoadModelOverrides.end() ) {
|
||||
loadmodel = TModelsManager::GetModel( asBaseDir + lookup->second, true );
|
||||
// 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
|
||||
// try first specialized version of the load model, vehiclename_loadname
|
||||
auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + Name };
|
||||
if( ( true == FileExists( specializedloadfilename + ".e3d" ) )
|
||||
|| ( true == FileExists( specializedloadfilename + ".t3d" ) ) ) {
|
||||
loadmodel = TModelsManager::GetModel( specializedloadfilename, true );
|
||||
{
|
||||
auto const specializedloadfilename { asBaseDir + MoverParameters->TypeName + "_" + Name };
|
||||
loadmodel = TModelsManager::GetModel( specializedloadfilename, true, false );
|
||||
if( loadmodel != nullptr ) { return loadmodel; }
|
||||
}
|
||||
if( loadmodel == nullptr ) {
|
||||
// if this fails, try generic load model
|
||||
loadmodel = TModelsManager::GetModel( asBaseDir + Name, true );
|
||||
// try generic version of the load model next, loadname
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ TGauge::Load_mapping( cParser &Input ) {
|
||||
m_type = (
|
||||
gaugetype == "impulse" ? TGaugeType::push :
|
||||
gaugetype == "return" ? TGaugeType::push :
|
||||
gaugetype == "delayed" ? TGaugeType::push_delayed :
|
||||
TGaugeType::toggle ); // default
|
||||
}
|
||||
else if( key == "soundinc:" ) {
|
||||
|
||||
3
Gauge.h
3
Gauge.h
@@ -23,7 +23,8 @@ enum class TGaugeAnimation {
|
||||
|
||||
enum class TGaugeType {
|
||||
toggle,
|
||||
push
|
||||
push,
|
||||
push_delayed
|
||||
};
|
||||
|
||||
// animowany wskaźnik, mogący przyjmować wiele stanów pośrednich
|
||||
|
||||
@@ -387,7 +387,7 @@ struct TBrakePressure
|
||||
typedef std::map<int,TBrakePressure> TBrakePressureTable;
|
||||
|
||||
/*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*/
|
||||
enum class TPowerType { NoPower, BioPower, MechPower, ElectricPower, SteamPower };
|
||||
/*rodzaj paliwa*/
|
||||
@@ -440,10 +440,22 @@ struct TCurrentCollector {
|
||||
//}
|
||||
};
|
||||
/*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;
|
||||
TPowerSource RechargeSource;
|
||||
@@ -453,7 +465,7 @@ struct _mover__1
|
||||
//}
|
||||
};
|
||||
|
||||
struct _mover__2
|
||||
struct TPowerCable
|
||||
{
|
||||
TPowerType PowerTrans;
|
||||
double SteamPressure;
|
||||
@@ -463,12 +475,17 @@ struct _mover__2
|
||||
//}
|
||||
};
|
||||
|
||||
struct _mover__3
|
||||
struct THeater
|
||||
{
|
||||
TGrateType Grate;
|
||||
TBoilerType Boiler;
|
||||
};
|
||||
|
||||
struct TTransducer {
|
||||
// ld inputs
|
||||
double InputVoltage;
|
||||
};
|
||||
|
||||
/*parametry źródeł mocy*/
|
||||
struct TPowerParameters
|
||||
{
|
||||
@@ -480,11 +497,11 @@ struct TPowerParameters
|
||||
{
|
||||
struct
|
||||
{
|
||||
_mover__3 RHeater;
|
||||
THeater RHeater;
|
||||
};
|
||||
struct
|
||||
{
|
||||
_mover__2 RPowerCable;
|
||||
TPowerCable RPowerCable;
|
||||
};
|
||||
struct
|
||||
{
|
||||
@@ -492,15 +509,15 @@ struct TPowerParameters
|
||||
};
|
||||
struct
|
||||
{
|
||||
_mover__1 RAccumulator;
|
||||
TAccumulator RAccumulator;
|
||||
};
|
||||
struct
|
||||
{
|
||||
TEngineType GeneratorEngine;
|
||||
engine_generator EngineGenerator;
|
||||
};
|
||||
struct
|
||||
{
|
||||
double InputVoltage;
|
||||
TTransducer Transducer;
|
||||
};
|
||||
struct
|
||||
{
|
||||
@@ -618,7 +635,8 @@ enum class TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic
|
||||
struct power_coupling {
|
||||
double current{ 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 {
|
||||
@@ -1369,6 +1387,7 @@ public:
|
||||
|
||||
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 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 iLights[2]; // bity zapalonych świateł tutaj, żeby dało się liczyć pobór prądu
|
||||
|
||||
@@ -1502,7 +1521,8 @@ public:
|
||||
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/
|
||||
|
||||
/*-funkcje typowe dla lokomotywy elektrycznej*/
|
||||
void ConverterCheck( double const Timestep ); // przetwornica
|
||||
void PowerCouplersCheck( double const Deltatime );
|
||||
void ConverterCheck( double const Timestep ); // przetwornica
|
||||
void HeatingCheck( double const Timestep );
|
||||
void WaterPumpCheck( double const Timestep );
|
||||
void WaterHeaterCheck( double const Timestep );
|
||||
|
||||
@@ -673,7 +673,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: zbiornika rozrządu nie pompuje się tu, tylko pantografy; potem można zamknąć
|
||||
// WS i odpalić resztę
|
||||
if ((TrainType == dt_EZT) ?
|
||||
if (PantAutoValve ?
|
||||
(PantPress < ScndPipePress) :
|
||||
bPantKurek3) // kurek zamyka połączenie z ZG
|
||||
{ // zbiornik pantografu połączony ze zbiornikiem głównym - małą sprężarką się tego nie napompuje
|
||||
@@ -1070,85 +1070,6 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
|
||||
const double Vepsilon = 1e-5;
|
||||
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))
|
||||
{ // Ra: to przepisywanie tu jest bez sensu
|
||||
RunningShape = Shape;
|
||||
@@ -1399,6 +1320,10 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
|
||||
SetFlag( SoundFlag, sound::relay );
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: gather and move current calculations to dedicated method
|
||||
TotalCurrent = 0;
|
||||
|
||||
// traction motors
|
||||
MotorBlowersCheck( Deltatime );
|
||||
// uklady hamulcowe:
|
||||
@@ -1436,6 +1361,114 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
|
||||
BrakeSlippingTimer += Deltatime;
|
||||
// automatic doors
|
||||
update_doors( Deltatime );
|
||||
|
||||
PowerCouplersCheck( Deltatime );
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -1492,12 +1525,70 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
|
||||
// heating system status check
|
||||
void TMoverParameters::HeatingCheck( double const Timestep ) {
|
||||
|
||||
Heating = (
|
||||
( true == HeatingAllow )
|
||||
// powered vehicles are generally required to activate their power source to provide heating
|
||||
// passive vehicles get a pass in this regard
|
||||
&& ( ( Power < 0.1 )
|
||||
|| ( true == Mains ) ) );
|
||||
// update heating devices
|
||||
// TBD, TODO: move this to a separate method?
|
||||
switch( HeatingPowerSource.SourceType ) {
|
||||
case TPowerSource::Generator: {
|
||||
if( ( HeatingPowerSource.EngineGenerator.engine_revolutions != nullptr )
|
||||
&& ( 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
|
||||
@@ -3882,7 +3973,6 @@ void TMoverParameters::ComputeConstans(void)
|
||||
double BearingF, RollF, HideModifier;
|
||||
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();
|
||||
TotalMassxg = TotalMass * g; // TotalMass*g
|
||||
BearingF = 2.0 * (DamageFlag && dtrain_bearing);
|
||||
@@ -4021,9 +4111,10 @@ void TMoverParameters::ComputeTotalForce(double dt) {
|
||||
else
|
||||
Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo;
|
||||
} // bo nie dzialalo
|
||||
// TODO: clean up this elseif to match changes in power coupling code
|
||||
else if( ( EngineType == TEngineType::ElectricInductionMotor )
|
||||
|| ( ( ( 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!
|
||||
Voltage =
|
||||
std::max(
|
||||
@@ -4413,7 +4504,7 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
|
||||
tmp = DElist[ MainCtrlPos ].RPM / 60.0;
|
||||
|
||||
if( ( true == Heating )
|
||||
if( ( true == HeatingAllow )
|
||||
&& ( HeatingPower > 0 )
|
||||
&& ( EngineHeatingRPM > 0 ) ) {
|
||||
// bump engine revolutions up if needed, when heating is on
|
||||
@@ -5292,12 +5383,12 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
Im = eimv[eimv_If];
|
||||
if ((eimv[eimv_Ipoj] >= 0))
|
||||
Vadd *= (1.0 - 2.0 * dt);
|
||||
else if ((Voltage < EnginePowerSource.CollectorParameters.MaxV))
|
||||
else if ((std::abs(Voltage) < EnginePowerSource.CollectorParameters.MaxV))
|
||||
Vadd *= (1.0 - dt);
|
||||
else
|
||||
Vadd = Max0R(
|
||||
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));
|
||||
|
||||
EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000;
|
||||
@@ -6993,8 +7084,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 );
|
||||
auto const doors { Doors.permit_presets[ Doors.permit_preset ] };
|
||||
auto const permitleft = doors & 1;
|
||||
auto const permitright = doors & 2;
|
||||
auto const permitleft { ( ( doors & 1 ) != 0 ) };
|
||||
auto const permitright { ( ( doors & 2 ) != 0 ) };
|
||||
|
||||
PermitDoors( ( CabNo > 0 ? side::left : side::right ), permitleft, Notify );
|
||||
PermitDoors( ( CabNo > 0 ? side::right : side::left ), permitright, Notify );
|
||||
@@ -7452,15 +7543,11 @@ double TMoverParameters::GetTrainsetVoltage(void)
|
||||
{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
|
||||
return std::max(
|
||||
( ( ( Couplers[end::front].Connected )
|
||||
&& ( ( Couplers[ end::front ].CouplingFlag & ctrain_power )
|
||||
|| ( ( Couplers[ end::front ].CouplingFlag & ctrain_heating )
|
||||
&& ( Couplers[ end::front ].Connected->Heating ) ) ) ) ?
|
||||
&& ( Couplers[ end::front ].Connected->Couplers[ Couplers[ end::front ].ConnectedNr ].power_high.is_live ) ) ?
|
||||
Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
|
||||
0.0 ),
|
||||
( ( ( Couplers[end::rear].Connected )
|
||||
&& ( ( Couplers[ end::rear ].CouplingFlag & ctrain_power )
|
||||
|| ( ( Couplers[ end::rear ].CouplingFlag & ctrain_heating )
|
||||
&& ( Couplers[ end::rear ].Connected->Heating ) ) ) ) ?
|
||||
&& ( Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.is_live ) ) ?
|
||||
Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
|
||||
0.0 ) );
|
||||
}
|
||||
@@ -7902,13 +7989,19 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
|
||||
std::string file = chkpath + TypeName + ".fiz";
|
||||
|
||||
WriteLog("LOAD FIZ FROM " + file);
|
||||
|
||||
/*
|
||||
std::ifstream in(file);
|
||||
if (!in.is_open())
|
||||
{
|
||||
WriteLog("E8 - FIZ FILE NOT EXIST.");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
cParser fizparser( file, cParser::buffer_FILE );
|
||||
if( false == fizparser.ok() ) {
|
||||
WriteLog( "E8 - FIZ FILE NOT EXIST." );
|
||||
return false;
|
||||
}
|
||||
|
||||
ConversionError = 0;
|
||||
|
||||
@@ -7916,8 +8009,13 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
|
||||
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
std::unordered_map<std::string, std::string> fizlines;
|
||||
std::string inputline;
|
||||
/*
|
||||
while (std::getline(in, inputline))
|
||||
{
|
||||
*/
|
||||
while( fizparser.ok() ) {
|
||||
|
||||
inputline = fizparser.getToken<std::string>( false, "\n" );
|
||||
|
||||
bool comment = ( ( inputline.find('#') != std::string::npos )
|
||||
|| ( inputline.compare( 0, 2, "//" ) == 0 ) );
|
||||
if( true == comment ) {
|
||||
@@ -8233,8 +8331,9 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
|
||||
continue;
|
||||
}
|
||||
} // while line
|
||||
/*
|
||||
in.close();
|
||||
|
||||
*/
|
||||
// Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie
|
||||
// zaleznosci
|
||||
|
||||
@@ -8882,6 +8981,9 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
|
||||
lookup->second :
|
||||
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
|
||||
{
|
||||
auto lookup = starts.find( extract_value( "FuelStart", line ) );
|
||||
@@ -8980,12 +9082,13 @@ void TMoverParameters::LoadFIZ_Power( std::string const &Line ) {
|
||||
|
||||
EnginePowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "EnginePower", Line ) );
|
||||
LoadFIZ_PowerParamsDecode( EnginePowerSource, "", Line );
|
||||
|
||||
/*
|
||||
if( ( EnginePowerSource.SourceType == TPowerSource::Generator )
|
||||
&& ( EnginePowerSource.GeneratorEngine == TEngineType::WheelsDriven ) ) {
|
||||
// perpetuum mobile?
|
||||
ConversionError = 666;
|
||||
}
|
||||
*/
|
||||
if( Power == 0.0 ) {
|
||||
//jeśli nie ma mocy, np. rozrządcze EZT
|
||||
EnginePowerSource.SourceType = TPowerSource::NotDefined;
|
||||
@@ -9308,12 +9411,31 @@ void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparamet
|
||||
}
|
||||
case TPowerSource::Transducer: {
|
||||
|
||||
extract_value( Powerparameters.InputVoltage, Prefix + "TransducerInputV", Line, "" );
|
||||
extract_value( Powerparameters.Transducer.InputVoltage, Prefix + "TransducerInputV", Line, "" );
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
case TPowerSource::Accumulator: {
|
||||
@@ -9399,7 +9521,8 @@ TPowerSource TMoverParameters::LoadFIZ_SourceDecode( std::string const &Source )
|
||||
{ "CurrentCollector", TPowerSource::CurrentCollector },
|
||||
{ "PowerCable", TPowerSource::PowerCable },
|
||||
{ "Heater", TPowerSource::Heater },
|
||||
{ "Internal", TPowerSource::InternalSource }
|
||||
{ "Internal", TPowerSource::InternalSource },
|
||||
{ "Main", TPowerSource::Main }
|
||||
};
|
||||
auto lookup = powersources.find( Source );
|
||||
return
|
||||
@@ -9418,7 +9541,8 @@ TEngineType TMoverParameters::LoadFIZ_EngineDecode( std::string const &Engine )
|
||||
{ "Dumb", TEngineType::Dumb },
|
||||
{ "DieselElectric", TEngineType::DieselElectric },
|
||||
{ "DumbDE", TEngineType::DieselElectric },
|
||||
{ "ElectricInductionMotor", TEngineType::ElectricInductionMotor }
|
||||
{ "ElectricInductionMotor", TEngineType::ElectricInductionMotor },
|
||||
{ "Main", TEngineType::Main }
|
||||
};
|
||||
auto lookup = enginetypes.find( Engine );
|
||||
return
|
||||
@@ -9636,6 +9760,17 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
|
||||
if( LightsPosNo > 0 )
|
||||
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
|
||||
// to dac potem do init
|
||||
if( ReadyFlag ) // gotowy do drogi
|
||||
|
||||
@@ -57,7 +57,7 @@ TModelsManager::LoadModel(std::string const &Name, bool dynamic) {
|
||||
}
|
||||
|
||||
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
|
||||
// (kabina, wnętrze, ładunek)
|
||||
// dla "node...dynamic" mamy podaną ścieżkę w "\dynamic\" i musi być co najmniej 1 poziom, zwkle
|
||||
@@ -107,7 +107,9 @@ TModelsManager::GetModel(std::string const &Name, bool const Dynamic)
|
||||
}
|
||||
else {
|
||||
// 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
|
||||
m_modelsmap.emplace( filename, null_handle );
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ private:
|
||||
class TModelsManager {
|
||||
public:
|
||||
// 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:
|
||||
// types:
|
||||
|
||||
@@ -528,7 +528,7 @@ glm::vec3
|
||||
TTraction::wire_color() const {
|
||||
|
||||
glm::vec3 color;
|
||||
if( false == DebugModeFlag ) {
|
||||
if( false == DebugTractionFlag ) {
|
||||
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
|
||||
case 1: {
|
||||
|
||||
@@ -15,6 +15,8 @@ http://mozilla.org/MPL/2.0/.
|
||||
|
||||
class TTractionPowerSource : public scene::basic_node {
|
||||
|
||||
friend class debug_panel;
|
||||
|
||||
public:
|
||||
// constructor
|
||||
TTractionPowerSource( scene::node_data const &Nodedata );
|
||||
|
||||
19
Train.cpp
19
Train.cpp
@@ -4719,10 +4719,10 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
|
||||
if( Command.action == GLFW_PRESS ) {
|
||||
|
||||
if( Train->mvOccupied->Doors.has_autowarning ) {
|
||||
// automatic departure signal delays actual door closing until the button is released
|
||||
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::left, false );
|
||||
}
|
||||
@@ -4733,10 +4733,10 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
|
||||
Train->ggDoorAllOffButton.UpdateValue( 1.0, Train->dsbSwitch );
|
||||
}
|
||||
else if( Command.action == GLFW_RELEASE ) {
|
||||
// release the button
|
||||
if( Train->mvOccupied->Doors.has_autowarning ) {
|
||||
// automatic departure signal delays actual door closing until the button is released
|
||||
Train->mvOccupied->signal_departure( false );
|
||||
}
|
||||
if( Train->ggDoorAllOffButton.type() == TGaugeType::push_delayed ) {
|
||||
// now we can actually close the door
|
||||
Train->mvOccupied->OperateDoors( side::right, false );
|
||||
Train->mvOccupied->OperateDoors( side::left, false );
|
||||
@@ -5037,6 +5037,10 @@ void TTrain::OnCommand_cabchangeforward( TTrain *Train, command_data const &Comm
|
||||
1 );
|
||||
}
|
||||
}
|
||||
// HACK: match consist door permit state with the preset in the active cab
|
||||
if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) {
|
||||
Train->mvOccupied->ChangeDoorPermitPreset( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5053,6 +5057,10 @@ void TTrain::OnCommand_cabchangebackward( TTrain *Train, command_data const &Com
|
||||
1 );
|
||||
}
|
||||
}
|
||||
// HACK: match consist door permit state with the preset in the active cab
|
||||
if( Train->ggDoorPermitPresetButton.SubModel != nullptr ) {
|
||||
Train->mvOccupied->ChangeDoorPermitPreset( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7656,7 +7664,7 @@ void TTrain::set_cab_controls( int const Cab ) {
|
||||
TimetableLightActive ?
|
||||
1.f :
|
||||
0.f ) );
|
||||
// doors
|
||||
// doors permits
|
||||
if( ggDoorLeftPermitButton.type() != TGaugeType::push ) {
|
||||
ggDoorLeftPermitButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::left : side::right ) ].open_permit ? 1.f : 0.f );
|
||||
}
|
||||
@@ -7664,6 +7672,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 );
|
||||
}
|
||||
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 );
|
||||
ggDoorRightButton.PutValue( mvOccupied->Doors.instances[ ( mvOccupied->ActiveCab == 1 ? side::right : side::left ) ].is_closed ? 0.f : 1.f );
|
||||
// door lock
|
||||
|
||||
@@ -35,7 +35,7 @@ driver_ui::driver_ui() {
|
||||
m_scenariopanel.size_max = { Global.iWindowWidth * 0.95, Global.iWindowHeight * 0.95 };
|
||||
|
||||
m_timetablepanel.title = locale::strings[ locale::string::driver_timetable_header ];
|
||||
m_timetablepanel.size_min = { 435, 110 };
|
||||
m_timetablepanel.size_min = { 435, 70 };
|
||||
m_timetablepanel.size_max = { 435, Global.iWindowHeight * 0.95 };
|
||||
|
||||
m_transcriptspanel.title = locale::strings[ locale::string::driver_transcripts_header ];
|
||||
|
||||
@@ -16,6 +16,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "simulationtime.h"
|
||||
#include "Timer.h"
|
||||
#include "Event.h"
|
||||
#include "TractionPower.h"
|
||||
#include "Camera.h"
|
||||
#include "mtable.h"
|
||||
#include "Train.h"
|
||||
@@ -265,23 +266,23 @@ timetable_panel::update() {
|
||||
auto const *table = owner->TrainTimetable();
|
||||
if( table == nullptr ) { return; }
|
||||
|
||||
{ // destination
|
||||
// destination
|
||||
{
|
||||
auto textline = Bezogonkow( owner->Relation(), true );
|
||||
if( false == textline.empty() ) {
|
||||
textline += " (" + Bezogonkow( owner->TrainName(), true ) + ")";
|
||||
}
|
||||
|
||||
text_lines.emplace_back( textline, Global.UITextColor );
|
||||
}
|
||||
|
||||
{ // next station
|
||||
if( false == is_expanded ) {
|
||||
// next station
|
||||
auto const nextstation = owner->NextStop();
|
||||
if( false == nextstation.empty() ) {
|
||||
// jeśli jest podana relacja, to dodajemy punkt następnego zatrzymania
|
||||
auto textline = " -> " + nextstation;
|
||||
|
||||
text_lines.emplace_back( textline, Global.UITextColor );
|
||||
text_lines.emplace_back( "", Global.UITextColor );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +310,6 @@ timetable_panel::update() {
|
||||
static_cast<int>( consistlength ) );
|
||||
|
||||
text_lines.emplace_back( m_buffer.data(), Global.UITextColor );
|
||||
text_lines.emplace_back( "", Global.UITextColor );
|
||||
}
|
||||
|
||||
if( 0 == table->StationCount ) {
|
||||
@@ -377,24 +377,26 @@ timetable_panel::update() {
|
||||
candeparture ? readycolor : // czas minął i odjazd był, to nazwa stacji będzie na zielono
|
||||
isatpassengerstop ? waitcolor :
|
||||
Global.UITextColor ) };
|
||||
auto const trackcount{ ( tableline->TrackNo == 1 ? u8" ┃ " : u8" ║ " ) };
|
||||
m_tablelines.emplace_back(
|
||||
( u8"│ " + vmax + u8" │ " + station + u8" │ " + arrival + u8" │ " + traveltime + u8" │" ),
|
||||
( u8"│ " + vmax + u8" │ " + station + trackcount + arrival + u8" │ " + traveltime + u8" │" ),
|
||||
linecolor );
|
||||
m_tablelines.emplace_back(
|
||||
( u8"│ │ " + location + tableline->StationWare + u8" │ " + departure + u8" │ │" ),
|
||||
( u8"│ │ " + location + tableline->StationWare + trackcount + departure + u8" │ │" ),
|
||||
linecolor );
|
||||
// divider/footer
|
||||
if( i < table->StationCount ) {
|
||||
auto const *nexttableline { tableline + 1 };
|
||||
if( tableline->vmax == nexttableline->vmax ) {
|
||||
m_tablelines.emplace_back( u8"│ ├────────────────────────────────────┼─────────┼─────┤", Global.UITextColor );
|
||||
}
|
||||
else {
|
||||
m_tablelines.emplace_back( u8"├─────┼────────────────────────────────────┼─────────┼─────┤", Global.UITextColor );
|
||||
}
|
||||
std::string const vmaxnext{ ( tableline->vmax == nexttableline->vmax ? u8"│ ├" : u8"├─────┼" ) };
|
||||
auto const trackcountnext{ ( nexttableline->TrackNo == 1 ? u8"╂" : u8"╫" ) };
|
||||
m_tablelines.emplace_back(
|
||||
vmaxnext + u8"────────────────────────────────────" + trackcountnext + u8"─────────┼─────┤",
|
||||
Global.UITextColor );
|
||||
}
|
||||
else {
|
||||
m_tablelines.emplace_back( u8"└─────┴────────────────────────────────────┴─────────┴─────┘", Global.UITextColor );
|
||||
m_tablelines.emplace_back(
|
||||
u8"└─────┴────────────────────────────────────┴─────────┴─────┘",
|
||||
Global.UITextColor );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -474,6 +476,7 @@ debug_panel::update() {
|
||||
m_scantablelines.clear();
|
||||
m_scenariolines.clear();
|
||||
m_eventqueuelines.clear();
|
||||
m_powergridlines.clear();
|
||||
m_cameralines.clear();
|
||||
m_rendererlines.clear();
|
||||
|
||||
@@ -483,6 +486,7 @@ debug_panel::update() {
|
||||
update_section_scantable( m_scantablelines );
|
||||
update_section_scenario( m_scenariolines );
|
||||
update_section_eventqueue( m_eventqueuelines );
|
||||
update_section_powergrid( m_powergridlines );
|
||||
update_section_camera( m_cameralines );
|
||||
update_section_renderer( m_rendererlines );
|
||||
}
|
||||
@@ -524,6 +528,10 @@ debug_panel::render() {
|
||||
// event queue filter
|
||||
ImGui::Checkbox( "By This Vehicle Only", &m_eventqueueactivevehicleonly );
|
||||
}
|
||||
if( true == render_section( "Power Grid", m_powergridlines ) ) {
|
||||
// traction state debug
|
||||
ImGui::Checkbox( "Debug Traction", &DebugTractionFlag );
|
||||
}
|
||||
render_section( "Camera", m_cameralines );
|
||||
render_section( "Gfx Renderer", m_rendererlines );
|
||||
// toggles
|
||||
@@ -580,14 +588,17 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
|
||||
( mover.ConvOvldFlag ? '!' : '.' ),
|
||||
( mover.CompressorFlag ? 'C' : ( false == mover.CompressorAllowLocal ? '-' : ( ( mover.CompressorAllow || mover.CompressorStart == start_t::automatic ) ? 'c' : '.' ) ) ),
|
||||
( mover.CompressorGovernorLock ? '!' : '.' ),
|
||||
( mover.Heating ? 'H' : ( mover.HeatingAllow ? 'h' : '.' ) ),
|
||||
std::string( isplayervehicle ? locale::strings[ locale::string::debug_vehicle_radio ] + ( mover.Radio ? std::to_string( m_input.train->RadioChannel() ) : "-" ) : "" ).c_str(),
|
||||
std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
|
||||
// power transfers
|
||||
mover.Couplers[ end::front ].power_high.voltage,
|
||||
mover.Couplers[ end::front ].power_high.current,
|
||||
std::string( mover.Couplers[ end::front ].power_high.local ? "" : "-" ).c_str(),
|
||||
std::string( vehicle.DirectionGet() ? ":<<:" : ":>>:" ).c_str(),
|
||||
std::string( mover.Couplers[ end::rear ].power_high.local ? "" : "-" ).c_str(),
|
||||
std::string( mover.Couplers[ end::front ].power_high.is_local ? "" : "-" ).c_str(),
|
||||
std::string( vehicle.DirectionGet() ? ":<<" : ":>>" ).c_str(),
|
||||
mover.Voltage,
|
||||
std::string( vehicle.DirectionGet() ? "<<:" : ">>:" ).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.current );
|
||||
|
||||
@@ -986,6 +997,46 @@ debug_panel::update_section_eventqueue( std::vector<text_line> &Output ) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debug_panel::update_section_powergrid( std::vector<text_line> &Output ) {
|
||||
|
||||
auto const lowpowercolor { glm::vec4( 164.0f / 255.0f, 132.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
|
||||
auto const nopowercolor { glm::vec4( 164.0f / 255.0f, 84.0f / 255.0f, 84.0f / 255.0f, 1.f ) };
|
||||
|
||||
Output.emplace_back( "Name: Output: Timeout:", Global.UITextColor );
|
||||
|
||||
std::string textline;
|
||||
|
||||
for( auto const *powerstation : simulation::Powergrid.sequence() ) {
|
||||
|
||||
if( true == powerstation->bSection ) { continue; }
|
||||
|
||||
auto const name { (
|
||||
powerstation->m_name.empty() ?
|
||||
"(unnamed)" :
|
||||
powerstation->m_name )
|
||||
+ " " };
|
||||
|
||||
textline =
|
||||
name.substr( 0, 20 )
|
||||
+ " " + to_string( powerstation->OutputVoltage, 0, 5 )
|
||||
+ " " + to_string( powerstation->FuseTimer, 1, 12 )
|
||||
+ ( powerstation->FuseCounter == 0 ?
|
||||
"" :
|
||||
" (x" + to_string( powerstation->FuseCounter ) + ")" );
|
||||
|
||||
Output.emplace_back(
|
||||
textline,
|
||||
( ( powerstation->FastFuse || powerstation->SlowFuse ) ? nopowercolor :
|
||||
powerstation->OutputVoltage < ( 0.8 * powerstation->NominalVoltage ) ? lowpowercolor :
|
||||
Global.UITextColor ) );
|
||||
}
|
||||
|
||||
if( Output.size() == 1 ) {
|
||||
Output.front().data = "(no power stations)";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debug_panel::update_section_camera( std::vector<text_line> &Output ) {
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ private:
|
||||
void update_section_scantable( 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_powergrid( std::vector<text_line> &Output );
|
||||
void update_section_camera( std::vector<text_line> &Output );
|
||||
void update_section_renderer( std::vector<text_line> &Output );
|
||||
// section update helpers
|
||||
@@ -105,6 +106,7 @@ private:
|
||||
m_cameralines,
|
||||
m_scenariolines,
|
||||
m_eventqueuelines,
|
||||
m_powergridlines,
|
||||
m_rendererlines;
|
||||
int tprev { 0 }; // poprzedni czas
|
||||
double VelPrev { 0.0 }; // poprzednia prędkość
|
||||
|
||||
@@ -549,6 +549,7 @@ void TTrainParameters::serialize( dictionary_source *Output ) const {
|
||||
Output->insert( ( stationlabel + "am" ), timetableline.Am );
|
||||
Output->insert( ( stationlabel + "dh" ), timetableline.Dh );
|
||||
Output->insert( ( stationlabel + "dm" ), timetableline.Dm );
|
||||
Output->insert( ( stationlabel + "tracks" ), timetableline.TrackNo );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ init() {
|
||||
"Name: %s%s\nLoad: %.0f %s\nStatus: %s%s\nCouplers:\n front: %s\n rear: %s",
|
||||
", owned by: ",
|
||||
"none",
|
||||
"Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s%s%s%.0f@%.0f",
|
||||
"Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s%s[%.0f]%s%s%.0f@%.0f",
|
||||
" radio: ",
|
||||
" oil pressure: ",
|
||||
"Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, cooling fans: %.0f+%.0f",
|
||||
@@ -236,7 +236,7 @@ init() {
|
||||
"Nazwa: %s%s\nLadunek: %.0f %s\nStatus: %s%s\nSprzegi:\n przedni: %s\n tylny: %s",
|
||||
", wlasciciel: ",
|
||||
"wolny",
|
||||
"Urzadzenia: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nTransfer pradow: %.0f@%.0f%s%s%s%.0f@%.0f",
|
||||
"Urzadzenia: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nTransfer pradow: %.0f@%.0f%s%s[%.0f]%s%s%.0f@%.0f",
|
||||
" radio: ",
|
||||
" cisn.oleju: ",
|
||||
"Nastawniki:\n glowny: %d(%d), dodatkowy: %s\nMoc silnika: %.1f, prad silnika: %.0f\nObroty:\n silnik: %.0f, motory: %.0f\n went.silnika: %.0f, went.motorow: %.0f+%.0f, went.chlodnicy: %.0f+%.0f",
|
||||
|
||||
@@ -31,6 +31,7 @@ bool DebugModeFlag = false;
|
||||
bool FreeFlyModeFlag = false;
|
||||
bool EditorModeFlag = false;
|
||||
bool DebugCameraFlag = false;
|
||||
bool DebugTractionFlag = false;
|
||||
|
||||
double Max0R(double x1, double x2)
|
||||
{
|
||||
|
||||
@@ -38,6 +38,7 @@ extern bool DebugModeFlag;
|
||||
extern bool FreeFlyModeFlag;
|
||||
extern bool EditorModeFlag;
|
||||
extern bool DebugCameraFlag;
|
||||
extern bool DebugTractionFlag;
|
||||
|
||||
/*funkcje matematyczne*/
|
||||
double Max0R(double x1, double x2);
|
||||
|
||||
Reference in New Issue
Block a user