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

configurable pantograph compressor valve type, power coupler state calculation fixes, vehicle heating system enhancements, fiz file parser enhancement, debug ui panel enhancements, delayed door closing cab switch type

This commit is contained in:
tmj-fstate
2019-06-13 01:38:20 +02:00
parent 32ca2b76ff
commit 85d810b330
10 changed files with 152 additions and 113 deletions

View File

@@ -2459,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;
}

View File

@@ -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)

View File

@@ -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:" ) {

View File

@@ -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

View File

@@ -618,7 +618,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 +1370,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,6 +1504,7 @@ public:
bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/
/*-funkcje typowe dla lokomotywy elektrycznej*/
void PowerCouplersCheck( double const Deltatime );
void ConverterCheck( double const Timestep ); // przetwornica
void HeatingCheck( double const Timestep );
void WaterPumpCheck( double const Timestep );

View File

@@ -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,81 @@ 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 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 = std::abs( hvc );
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 ) {
auto const localvoltage { std::abs( hvc ) };
oppositecoupler.power_high.voltage = std::max(
oppositecoupler.power_high.voltage,
localvoltage - coupler.power_high.current * 0.02 );
oppositecoupler.power_high.is_live |=
( localvoltage > 0.1 )
&& ( oppositehighvoltagecoupling || ( oppositeheatingcoupling && localpowersource && Heating ) );
}
}
// przekazywanie pradow
hvc = 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( hvc != 0.0 ) {
// ...ale jest cos na sprzegach:
coupler.power_high.current = ( Itot + TotalCurrent ) * coupler.power_high.voltage / hvc; // 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 +1492,24 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
// heating system status check
void TMoverParameters::HeatingCheck( double const Timestep ) {
Heating = (
( true == HeatingAllow )
auto const heatingpowerthreshold { 0.1 };
auto const voltage { (
// 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 ) ) );
Power < 0.1 ?
GetTrainsetVoltage() :
( true == Mains ?
Voltage :
GetTrainsetVoltage() ) ) };
Heating = (
( true == HeatingAllow )
&& ( std::abs( voltage ) > heatingpowerthreshold ) );
if( Heating ) {
TotalCurrent += 1000 * HeatingPower / voltage; // heater power cost presumably specified in kilowatts
}
}
// water pump status check
@@ -3882,7 +3894,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,6 +4032,7 @@ 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 ) ) ) {
@@ -4413,7 +4425,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 +5304,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;
@@ -7439,15 +7451,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 ) );
}
@@ -7889,13 +7897,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;
@@ -7903,8 +7917,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 ) {
@@ -8220,8 +8239,9 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue;
}
} // while line
/*
in.close();
*/
// Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie
// zaleznosci
@@ -8869,6 +8889,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 ) );

View File

@@ -4721,8 +4721,11 @@ void TTrain::OnCommand_doorcloseall( TTrain *Train, command_data const &Command
if( Train->mvOccupied->Doors.has_autowarning ) {
Train->mvOccupied->signal_departure( true );
}
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 );
}
// visual feedback
Train->ggDoorLeftButton.UpdateValue( 0.0, Train->dsbSwitch );
Train->ggDoorRightButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -4730,10 +4733,14 @@ 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 ) {
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 );
}
// visual feedback
if( Train->ggDoorAllOffButton.SubModel )
Train->ggDoorAllOffButton.UpdateValue( 0.0 );

View File

@@ -589,14 +589,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 );

View File

@@ -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",

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 19
#define VERSION_MINOR 604
#define VERSION_MINOR 610
#define VERSION_REVISION 0