From 129924315da847b259743617080e92af376209de Mon Sep 17 00:00:00 2001 From: Hirek193 Date: Mon, 27 Apr 2026 18:21:55 +0200 Subject: [PATCH] Cleanup hamulce.cpp/h with Mover.cpp/h --- McZapkie/MOVER.h | 1443 ++-- McZapkie/Mover.cpp | 17945 +++++++++++++++++++++-------------------- McZapkie/hamulce.cpp | 5272 +++++++----- McZapkie/hamulce.h | 2025 +++-- 4 files changed, 14451 insertions(+), 12234 deletions(-) diff --git a/McZapkie/MOVER.h b/McZapkie/MOVER.h index 78062821..6cca9297 100644 --- a/McZapkie/MOVER.h +++ b/McZapkie/MOVER.h @@ -9,7 +9,7 @@ http://mozilla.org/MPL/2.0/. #pragma once //--------------------------------------------------------------------------- -//Q: 20160805 - odlaczenie pliku fizyki .pas od kompilacji +// Q: 20160805 - odlaczenie pliku fizyki .pas od kompilacji #include #include "hamulce.h" #include "scripting/ladderlogic.h" @@ -19,7 +19,6 @@ Copyright (C) 2001-2004 Maciej Czapkiewicz and others */ - /* (C) McZapkie v.2004.02 Co brakuje: @@ -81,483 +80,923 @@ zwiekszenie nacisku przy duzych predkosciach w hamulcach Oerlikona #include "utilities/dumb3d.h" #include "utilities/utilities.h" +/// Global counter incremented when a string-to-numeric conversion fails during config parsing. extern int ConversionError; -const double Steel2Steel_friction = 0.15; //tarcie statyczne -const double g = 9.81; //przyspieszenie ziemskie -const double SandSpeed = 0.1; //ile kg/s} +/// Static friction coefficient for steel-on-steel contact (used for adhesion at standstill). +const double Steel2Steel_friction = 0.15; // tarcie statyczne +/// Earth gravitational acceleration [m/s^2]. +const double g = 9.81; // przyspieszenie ziemskie +/// Sand consumption rate when sanding is active [kg/s]. +const double SandSpeed = 0.1; // ile kg/s} +/// 2*pi shortcut. const double Pirazy2 = 6.2831853071794f; //-- var, const, procedure --------------------------------------------------- +/// Truthy alias used by CheckLocomotiveParameters() to ignore a check failure. static bool const Go = true; -static bool const Hold = false; /*dla CheckLocomotiveParameters*/ -static int const ResArraySize = 64; /*dla silnikow elektrycznych*/ +/// Falsy alias used by CheckLocomotiveParameters() to abort on a check failure. +static bool const Hold = false; /*dla CheckLocomotiveParameters*/ +/// Maximum number of resistor / scheme entries for electric motor traction. +static int const ResArraySize = 64; /*dla silnikow elektrycznych*/ +/// Maximum number of motor-parameter table entries (gear stages). static int const MotorParametersArraySize = 10; -static int const maxcc = 4; /*max. ilosc odbierakow pradu*/ -//static int const LocalBrakePosNo = 10; /*ilosc nastaw hamulca pomocniczego*/ -//static int const MainBrakeMaxPos = 10; /*max. ilosc nastaw hamulca zasadniczego*/ -static int const ManualBrakePosNo = 20; /*ilosc nastaw hamulca recznego*/ +/// Maximum number of pantograph current collectors per vehicle. +static int const maxcc = 4; /*max. ilosc odbierakow pradu*/ +// static int const LocalBrakePosNo = 10; /*ilosc nastaw hamulca pomocniczego*/ +// static int const MainBrakeMaxPos = 10; /*max. ilosc nastaw hamulca zasadniczego*/ +/// Number of positions on the manual (parking) brake handle. +static int const ManualBrakePosNo = 20; /*ilosc nastaw hamulca recznego*/ +/// Number of positions on the lights selector switch. static int const LightsSwitchPosNo = 16; -static int const UniversalCtrlArraySize = 32; /*max liczba pozycji uniwersalnego nastawnika*/ +/// Maximum number of positions of the universal (auxiliary) controller. +static int const UniversalCtrlArraySize = 32; /*max liczba pozycji uniwersalnego nastawnika*/ /*uszkodzenia toru*/ +/// Track damage flag: rail wear. static int const dtrack_railwear = 2; +/// Track damage flag: free / loose rail. static int const dtrack_freerail = 4; +/// Track damage flag: thin (worn-out) rail. static int const dtrack_thinrail = 8; +/// Track damage flag: bent rail. static int const dtrack_railbend = 16; +/// Track damage flag: vegetation overgrowth. static int const dtrack_plants = 32; +/// Track damage flag: track impassable for movement. static int const dtrack_nomove = 64; +/// Track damage flag: rails missing entirely. static int const dtrack_norail = 128; /*uszkodzenia taboru*/ -static int const dtrain_thinwheel = 1; /*dla lokomotyw*/ -static int const dtrain_loadshift = 1; /*dla wagonow*/ +/// Vehicle damage flag: thin wheel (locomotives). +static int const dtrain_thinwheel = 1; /*dla lokomotyw*/ +/// Vehicle damage flag: shifted load (wagons). +static int const dtrain_loadshift = 1; /*dla wagonow*/ +/// Vehicle damage flag: wheel wear. static int const dtrain_wheelwear = 2; +/// Vehicle damage flag: bearing failure. static int const dtrain_bearing = 4; +/// Vehicle damage flag: coupling damage. static int const dtrain_coupling = 8; -static int const dtrain_ventilator = 16; /*dla lokomotywy el.*/ -static int const dtrain_loaddamage = 16; /*dla wagonow*/ -static int const dtrain_engine = 32; /*dla lokomotyw*/ -static int const dtrain_loaddestroyed = 32;/*dla wagonow*/ +/// Vehicle damage flag: ventilator failure (electric locomotive). +static int const dtrain_ventilator = 16; /*dla lokomotywy el.*/ +/// Vehicle damage flag: load damage (wagons). +static int const dtrain_loaddamage = 16; /*dla wagonow*/ +/// Vehicle damage flag: engine failure (locomotives). +static int const dtrain_engine = 32; /*dla lokomotyw*/ +/// Vehicle damage flag: load destroyed (wagons). +static int const dtrain_loaddestroyed = 32; /*dla wagonow*/ +/// Vehicle damage flag: axle damage. static int const dtrain_axle = 64; -static int const dtrain_out = 128; /*wykolejenie*/ -static int const dtrain_pantograph = 256; /*polamanie pantografu*/ +/// Vehicle damage flag: derailment. +static int const dtrain_out = 128; /*wykolejenie*/ +/// Vehicle damage flag: broken pantograph. +static int const dtrain_pantograph = 256; /*polamanie pantografu*/ -/*przyczyny wykolejenia*/ -enum DerailReason { +/// Reason for a derailment event. +enum DerailReason +{ + /// No derailment. NONE = 0, - END_OF_TRACK = 1, // Ra: powód wykolejenia: brak szyn - TOO_HIGH_SPEED = 2, // Ra: powód wykolejenia: przewrócony na łuku - GAUGE_MISMATCH = 3, // Ra: powód wykolejenia: za szeroki tor - WRONG_TRACK_TYPE = 4, // Ra: powód wykolejenia: nieodpowiednia trajektoria - COLLISION = 5, // powód wykolejenia: zderzenie z innym pojazdem + /// End of track reached. + END_OF_TRACK = 1, // Ra: powód wykolejenia: brak szyn + /// Speed too high for curve (overturn). + TOO_HIGH_SPEED = 2, // Ra: powód wykolejenia: przewrócony na łuku + /// Track gauge does not match wheelset gauge. + GAUGE_MISMATCH = 3, // Ra: powód wykolejenia: za szeroki tor + /// Track type incompatible with this vehicle. + WRONG_TRACK_TYPE = 4, // Ra: powód wykolejenia: nieodpowiednia trajektoria + /// Collision with another vehicle. + COLLISION = 5, // powód wykolejenia: zderzenie z innym pojazdem }; /*wagi prawdopodobienstwa dla funkcji FuzzyLogic*/ -#define p_elengproblem (1e-02) -#define p_elengdamage (1e-01) -#define p_coupldmg (2e-03) -#define p_derail (1e-03) -#define p_accn (1e-01) -#define p_slippdmg (1e-03) +/// Fuzzy-logic probability weight: electric engine general problem. +#define p_elengproblem (1e-02) +/// Fuzzy-logic probability weight: electric engine damage. +#define p_elengdamage (1e-01) +/// Fuzzy-logic probability weight: coupler damage. +#define p_coupldmg (2e-03) +/// Fuzzy-logic probability weight: derailment. +#define p_derail (1e-03) +/// Fuzzy-logic probability weight: acceleration-related event. +#define p_accn (1e-01) +/// Fuzzy-logic probability weight: damage caused by wheel slip. +#define p_slippdmg (1e-03) - /*typ sprzegu*/ -static int const ctrain_virtual = 0; //gdy pojazdy na tym samym torze się widzą wzajemnie -static int const ctrain_coupler = 1; //sprzeg fizyczny -static int const ctrain_pneumatic = 2; //przewody hamulcowe -static int const ctrain_controll = 4; //przewody sterujące (ukrotnienie) -static int const ctrain_power = 8; //przewody zasilające (WN) -static int const ctrain_passenger = 16; //mostek przejściowy -static int const ctrain_scndpneumatic = 32; //przewody 8 atm (żółte; zasilanie powietrzem) -static int const ctrain_heating = 64; //przewody ogrzewania WN -static int const ctrain_depot = 128; //nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna -// vehicle sides; exclusive -enum end { - front = 0, - rear = 1 +/*typ sprzegu*/ +/// Coupling type: virtual — vehicles share a track and are aware of each other. +static int const ctrain_virtual = 0; // gdy pojazdy na tym samym torze się widzą wzajemnie +/// Coupling type: physical coupler. +static int const ctrain_coupler = 1; // sprzeg fizyczny +/// Coupling type: pneumatic brake hose. +static int const ctrain_pneumatic = 2; // przewody hamulcowe +/// Coupling type: control cable (multiple-unit). +static int const ctrain_controll = 4; // przewody sterujące (ukrotnienie) +/// Coupling type: high-voltage power cable. +static int const ctrain_power = 8; // przewody zasilające (WN) +/// Coupling type: passenger gangway. +static int const ctrain_passenger = 16; // mostek przejściowy +/// Coupling type: secondary 8 atm pneumatic line (yellow, main air). +static int const ctrain_scndpneumatic = 32; // przewody 8 atm (żółte; zasilanie powietrzem) +/// Coupling type: high-voltage train heating cable. +static int const ctrain_heating = 64; // przewody ogrzewania WN +/// Coupling type: permanent (inter-section) — not separable during ordinary shunting; encoded as negative in config files. +static int const ctrain_depot = 128; // nie rozłączalny podczas zwykłych manewrów (międzyczłonowy), we wpisie wartość ujemna +/// Vehicle ends — front or rear (mutually exclusive). +enum end +{ + /// Front end. + front = 0, + /// Rear end. + rear = 1 }; -enum side { - right = 0, - left = 1 +/// Vehicle sides — right or left (mutually exclusive). +enum side +{ + /// Right side. + right = 0, + /// Left side. + left = 1 }; -// possible coupling types; can be combined -enum coupling { - faux = 0x0, - coupler = 0x1, - brakehose = 0x2, - control = 0x4, - highvoltage = 0x8, - gangway = 0x10, - mainhose = 0x20, - heating = 0x40, - permanent = 0x80, - power24v = 0x100, - power110v = 0x200, - power3x400v = 0x400, -// uic = 0x1000, +/// Bit flags representing the kind of physical/logical connections in a coupling. Combinable. +enum coupling +{ + /// No coupling (virtual / not connected). + faux = 0x0, + /// Mechanical coupler. + coupler = 0x1, + /// Pneumatic brake hose (PG). + brakehose = 0x2, + /// Control cable (multiple-unit). + control = 0x4, + /// High-voltage cable (traction supply). + highvoltage = 0x8, + /// Passenger gangway. + gangway = 0x10, + /// Main air (8 atm) line — secondary pneumatic supply. + mainhose = 0x20, + /// Train heating cable. + heating = 0x40, + /// Permanent (non-separable) coupling. + permanent = 0x80, + /// 24 V auxiliary power cable. + power24v = 0x100, + /// 110 V auxiliary power cable. + power110v = 0x200, + /// 3-phase 400 V auxiliary power cable. + power3x400v = 0x400, + // uic = 0x1000, }; -// possible effect ranges for control commands; exclusive -enum class range_t { - local, - unit, - consist +/// Range of effect for a control command (mutually exclusive). +enum class range_t +{ + /// Affects only this vehicle. + local, + /// Affects this multiple-unit (vehicles permanently coupled into a unit). + unit, + /// Affects the entire consist. + consist }; -// possible settings of enable/disable input pair; exclusive -enum class operation_t { - none = 0, - enable, - disable, - enable_on, - enable_off, - disable_on, - disable_off, +/// Possible settings for an enable/disable input pair (mutually exclusive). +enum class operation_t +{ + /// No input. + none = 0, + /// Enable input held active. + enable, + /// Disable input held active. + disable, + /// Enable button press transition (rising edge). + enable_on, + /// Enable button release transition. + enable_off, + /// Disable button press transition. + disable_on, + /// Disable button release transition. + disable_off, }; -// start method for devices; exclusive -enum class start_t { - disabled, - manual, - automatic, - manualwithautofallback, - converter, - battery, - direction +/// Auto-start method for ancillary devices (mutually exclusive). +enum class start_t +{ + /// Device cannot be started. + disabled, + /// Manual start only. + manual, + /// Starts automatically. + automatic, + /// Manual start with automatic fallback. + manualwithautofallback, + /// Driven by the converter state. + converter, + /// Driven by the battery state. + battery, + /// Driven by direction selector state. + direction }; -// recognized vehicle light locations and types; can be combined -enum light { +/// Bit flags representing vehicle external lights (positions and types). Combinable. +enum light +{ - headlight_left = ( 1 << 0 ), - redmarker_left = ( 1 << 1 ), - headlight_upper = ( 1 << 2 ), -// TBD, TODO: redmarker_upper support? - headlight_right = ( 1 << 4 ), - redmarker_right = ( 1 << 5 ), - rearendsignals = ( 1 << 6 ), - auxiliary_left = ( 1 << 7 ), - auxiliary_right = ( 1 << 8 ), - highbeamlight_left = ( 1 << 9 ), - highbeamlight_right = ( 1 << 10 ) + /// Headlight, left. + headlight_left = (1 << 0), + /// Red marker, left. + redmarker_left = (1 << 1), + /// Headlight, upper centre. + headlight_upper = (1 << 2), + // TBD, TODO: redmarker_upper support? + /// Headlight, right. + headlight_right = (1 << 4), + /// Red marker, right. + redmarker_right = (1 << 5), + /// Rear-end markers (combined). + rearendsignals = (1 << 6), + /// Auxiliary light, left (e.g. ditch light). + auxiliary_left = (1 << 7), + /// Auxiliary light, right. + auxiliary_right = (1 << 8), + /// High-beam headlight, left. + highbeamlight_left = (1 << 9), + /// High-beam headlight, right. + highbeamlight_right = (1 << 10) }; -// door operation methods; exclusive -enum control_t { - passenger, // local, opened/closed for duration of loading - driver, // remote, operated by the driver - autonomous, // local, closed when vehicle moves and/or after timeout - conductor, // remote, operated by the conductor - mixed // primary manual but answers also to remote control +/// Door operation method (who controls them and how) — mutually exclusive. +enum control_t +{ + /// Local; passengers operate manually, doors open/close for the duration of loading. + passenger, // local, opened/closed for duration of loading + /// Remote; driver-operated. + driver, // remote, operated by the driver + /// Local autonomous; close when the vehicle moves and/or after a timeout. + autonomous, // local, closed when vehicle moves and/or after timeout + /// Remote; conductor-operated. + conductor, // remote, operated by the conductor + /// Primarily manual but also responds to remote control. + mixed // primary manual but answers also to remote control }; - /*typ hamulca elektrodynamicznego*/ +/*typ hamulca elektrodynamicznego*/ +/// Electrodynamic-brake type: no ED brake. static int const dbrake_none = 0; +/// Electrodynamic-brake type: passive (always on while moving). static int const dbrake_passive = 1; +/// Electrodynamic-brake type: switchable (driver toggles). static int const dbrake_switch = 2; +/// Electrodynamic-brake type: reversal (engaged via reverser). static int const dbrake_reversal = 4; +/// Electrodynamic-brake type: automatic (engages from main brake). static int const dbrake_automatic = 8; /*dzwieki*/ -enum sound { - none, - loud = 1 << 0, - couplerstretch = 1 << 1, - bufferclash = 1 << 2, - relay = 1 << 3, - parallel = 1 << 4, - shuntfield = 1 << 5, - pneumatic = 1 << 6, - detach = 1 << 7, - attachcoupler = 1 << 8, - attachbrakehose = 1 << 9, - attachmainhose = 1 << 10, - attachcontrol = 1 << 11, - attachgangway = 1 << 12, - attachheating = 1 << 13, - attachadapter = 1 << 14, - removeadapter = 1 << 15, - doorpermit = 1 << 16, +/// Bit flags identifying sound events emitted by a vehicle. Combinable. +enum sound +{ + /// No sound event. + none, + /// Generic "loud" event flag (e.g. impact / forced action). + loud = 1 << 0, + /// Coupler stretching to its limit. + couplerstretch = 1 << 1, + /// Buffer clash (vehicles colliding). + bufferclash = 1 << 2, + /// Contactor / relay clicking. + relay = 1 << 3, + /// Series-parallel switch operating. + parallel = 1 << 4, + /// Field-shunt contactor operating. + shuntfield = 1 << 5, + /// Generic pneumatic event. + pneumatic = 1 << 6, + /// Coupling detached. + detach = 1 << 7, + /// Mechanical coupler attached. + attachcoupler = 1 << 8, + /// Brake hose attached. + attachbrakehose = 1 << 9, + /// Main air hose attached. + attachmainhose = 1 << 10, + /// Control cable attached. + attachcontrol = 1 << 11, + /// Gangway attached. + attachgangway = 1 << 12, + /// Heating cable attached. + attachheating = 1 << 13, + /// Adapter piece attached to coupler. + attachadapter = 1 << 14, + /// Adapter piece removed from coupler. + removeadapter = 1 << 15, + /// Door-open permission signalling. + doorpermit = 1 << 16, }; -// customizable reset button -enum relay_t { - maincircuitground = 1 << 0, - auxiliarycircuitground = 1 << 1, - tractionnmotoroverload = 1 << 2, - primaryconverteroverload = 1 << 3, - secondaryconverteroverload = 1 << 4, - ventillatoroverload = 1 << 5, - heatingoverload = 1 << 6, - electrodynamicbrakesoverload = 1 << 7, +/// Bit flags for the customizable reset button — which protective relay it resets. Combinable. +enum relay_t +{ + /// Main circuit ground-fault relay. + maincircuitground = 1 << 0, + /// Auxiliary circuit ground-fault relay. + auxiliarycircuitground = 1 << 1, + /// Traction motor overload relay. + tractionnmotoroverload = 1 << 2, + /// Primary converter overload relay. + primaryconverteroverload = 1 << 3, + /// Secondary converter overload relay. + secondaryconverteroverload = 1 << 4, + /// Ventilator overload relay. + ventillatoroverload = 1 << 5, + /// Heating overload relay. + heatingoverload = 1 << 6, + /// Electrodynamic-brake overload relay. + electrodynamicbrakesoverload = 1 << 7, }; -// functions during activation/deactivation -enum activation { +/// Bit flags for actions triggered on cab activation / deactivation. Combinable. +enum activation +{ + /// Engage the emergency brake. emergencybrake = 1 << 0, + /// Operate cab mirrors. mirrors = 1 << 1, + /// Raise the pantographs. pantographsup = 1 << 2, + /// Switch on red end-of-train markers. redmarkers = 1 << 3, + /// Set door-open permit. doorpermition = 1 << 4, + /// Engage the spring brake. springbrakeon = 1 << 5, + /// Release the spring brake. springbrakeoff = 1 << 6, + /// Place the reverser in neutral. neutraldirection = 1 << 7, }; -//szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType -//zamienione na flagi bitowe, aby szybko wybierać grupę (np. EZT+SZT) -// TODO: convert to enums, they're used as specific checks anyway +// szczególne typy pojazdów (inna obsługa) dla zmiennej TrainType +// zamienione na flagi bitowe, aby szybko wybierać grupę (np. EZT+SZT) +// TODO: convert to enums, they're used as specific checks anyway +/// Vehicle type flag: default (no special handling). static int const dt_Default = 0; +/// Vehicle type flag: EZT (electric multiple unit). static int const dt_EZT = 1; +/// Vehicle type flag: ET41 locomotive. static int const dt_ET41 = 2; +/// Vehicle type flag: ET42 locomotive. static int const dt_ET42 = 4; +/// Vehicle type flag: pseudo-diesel (electric drivetrain with diesel input model). static int const dt_PseudoDiesel = 8; -static int const dt_ET22 = 0x10; //używane od Megapacka -static int const dt_SN61 = 0x20; //nie używane w warunkach, ale ustawiane z CHK +/// Vehicle type flag: ET22 locomotive (added in Megapack). +static int const dt_ET22 = 0x10; // używane od Megapacka +/// Vehicle type flag: SN61 (set from CHK only, not used in conditions). +static int const dt_SN61 = 0x20; // nie używane w warunkach, ale ustawiane z CHK +/// Vehicle type flag: EP05 locomotive. static int const dt_EP05 = 0x40; +/// Vehicle type flag: ET40 locomotive. static int const dt_ET40 = 0x80; +/// Vehicle type flag: ŠKODA 181 locomotive. static int const dt_181 = 0x100; +/// Vehicle type flag: DMU (diesel multiple unit). static int const dt_DMU = 0x200; -//stałe dla asynchronów +// stałe dla asynchronów +/// EIM config index: dfic — frequency rise rate at start. static int const eimc_s_dfic = 0; +/// EIM config index: dfmax — maximum frequency rate of change. static int const eimc_s_dfmax = 1; +/// EIM config index: p — number of pole pairs. static int const eimc_s_p = 2; +/// EIM config index: cfu — voltage / frequency conversion coefficient. static int const eimc_s_cfu = 3; +/// EIM config index: cim — current / current conversion coefficient. static int const eimc_s_cim = 4; +/// EIM config index: icif — magnetisation current ratio. static int const eimc_s_icif = 5; +/// EIM config index: Uzmax — maximum DC link voltage. static int const eimc_f_Uzmax = 7; +/// EIM config index: Uzh — DC link voltage at field-weakening transition. static int const eimc_f_Uzh = 8; +/// EIM config index: DU — voltage drop at the converter. static int const eimc_f_DU = 9; +/// EIM config index: I0 — no-load magnetising current. static int const eimc_f_I0 = 10; +/// EIM config index: cfu — V/f gain in normal mode. static int const eimc_f_cfu = 11; +/// EIM config index: cfuH — V/f gain in field-weakening region. static int const eimc_f_cfuH = 12; +/// EIM config index: F0 — starting force at zero speed. static int const eimc_p_F0 = 13; +/// EIM config index: a1 — force-frequency slope coefficient. static int const eimc_p_a1 = 14; +/// EIM config index: Pmax — maximum power. static int const eimc_p_Pmax = 15; +/// EIM config index: Fh — force at field-weakening point. static int const eimc_p_Fh = 16; +/// EIM config index: Ph — power at field-weakening point. static int const eimc_p_Ph = 17; +/// EIM config index: Vh0 — speed where field weakening begins. static int const eimc_p_Vh0 = 18; +/// EIM config index: Vh1 — speed of full field weakening. static int const eimc_p_Vh1 = 19; +/// EIM config index: Imax — maximum motor current. static int const eimc_p_Imax = 20; +/// EIM config index: abed — anti-skid set point. static int const eimc_p_abed = 21; +/// EIM config index: eped — EP brake intensity bias. static int const eimc_p_eped = 22; -//zmienne dla asynchronów +// zmienne dla asynchronów +/// EIM variable index: FMAXMAX — absolute maximum allowable force. static int const eimv_FMAXMAX = 0; +/// EIM variable index: Fmax — current force limit. static int const eimv_Fmax = 1; +/// EIM variable index: ks — slip coefficient. static int const eimv_ks = 2; +/// EIM variable index: df — frequency offset. static int const eimv_df = 3; +/// EIM variable index: fp — base frequency. static int const eimv_fp = 4; +/// EIM variable index: U — applied voltage. static int const eimv_U = 5; +/// EIM variable index: pole — pole-pair indicator. static int const eimv_pole = 6; +/// EIM variable index: Ic — control current. static int const eimv_Ic = 7; +/// EIM variable index: If — field current. static int const eimv_If = 8; +/// EIM variable index: M — torque. static int const eimv_M = 9; +/// EIM variable index: Fr — actual force. static int const eimv_Fr = 10; +/// EIM variable index: Ipoj — line current. static int const eimv_Ipoj = 11; +/// EIM variable index: Pm — mechanical power. static int const eimv_Pm = 12; +/// EIM variable index: Pe — electrical power. static int const eimv_Pe = 13; +/// EIM variable index: eta — efficiency. static int const eimv_eta = 14; +/// EIM variable index: fkr — critical frequency. static int const eimv_fkr = 15; +/// EIM variable index: Uzsmax — maximum measured DC link voltage. static int const eimv_Uzsmax = 16; +/// EIM variable index: Pmax — instantaneous power limit. static int const eimv_Pmax = 17; +/// EIM variable index: Fzad — set-point force. static int const eimv_Fzad = 18; +/// EIM variable index: Imax — maximum allowed current. static int const eimv_Imax = 19; +/// EIM variable index: Fful — full force. static int const eimv_Fful = 20; +/// Brake-of-mode flag: PS (pneumatic, primary). static int const bom_PS = 1; +/// Brake-of-mode flag: PN (pneumatic, no electrodynamic). static int const bom_PN = 2; +/// Brake-of-mode flag: EP (electro-pneumatic). static int const bom_EP = 4; +/// Brake-of-mode flag: MED (mixed pneumatic+ED). static int const bom_MED = 8; +/// Bit flags reporting vehicle problems that prevent driving. enum TProblem // lista problemów taboru, które uniemożliwiają jazdę { // flagi bitowe + /// The vehicle has the brake applied or seized axles. pr_Hamuje = 1, // pojazd ma załączony hamulec lub zatarte osie + /// The vehicle requires pantographs to be inflated/raised. pr_Pantografy = 2, // pojazd wymaga napompowania pantografów + /// Reserved sentinel — last bit flag. pr_Ostatni = 0x80000000 // ostatnia flaga bitowa }; +/// Compressor parameter list — indices into the compressor programmer table. enum TCompressorList // lista parametrów w programatorze sprężarek { // pozycje kolejne - cl_Allow = 0, // zezwolenie na pracę sprężarek - cl_SpeedFactor = 1, // mnożnik wydajności - cl_MinFactor = 2, // mnożnik progu załącznika ciśnieniowego - cl_MaxFactor = 3 // mnożnik progu wyłącznika ciśnieniowego + /// Compressor enable permission (0/1). + cl_Allow = 0, // zezwolenie na pracę sprężarek + /// Compressor output multiplier. + cl_SpeedFactor = 1, // mnożnik wydajności + /// Pressure-switch lower threshold multiplier. + cl_MinFactor = 2, // mnożnik progu załącznika ciśnieniowego + /// Pressure-switch upper threshold multiplier. + cl_MaxFactor = 3 // mnożnik progu wyłącznika ciśnieniowego }; +/// 3-D position in world coordinates [m]. struct TLocation { + /// X coordinate. double X; + /// Y coordinate (vertical). double Y; + /// Z coordinate. double Z; }; +/// Euler-angle rotation (radians) around X / Y / Z axes. struct TRotation { + /// Rotation around X axis. double Rx; + /// Rotation around Y axis. double Ry; + /// Rotation around Z axis. double Rz; }; +/// Vehicle bounding box (width × length × height [m]). struct TDimension { + /// Width. double W = 0.0; + /// Length. double L = 0.0; + /// Height. double H = 0.0; }; +/// A pending command queued for the vehicle, with its arguments and propagation rules. struct TCommand { + /// Command name. std::string Command; /*komenda*/ + /// First numeric argument. double Value1 = 0.0; /*argumenty komendy*/ + /// Second numeric argument. double Value2 = 0.0; - int Coupling { coupling::control }; // coupler flag used to determine command propagation - TLocation Location; + /// Coupling flag controlling how the command propagates between vehicles. + int Coupling{coupling::control}; // coupler flag used to determine command propagation + /// World-space location associated with the command. + TLocation Location; }; /*tory*/ +/// Geometric shape of a track segment under the vehicle. struct TTrackShape -{/*ksztalt odcinka*/ +{ /*ksztalt odcinka*/ + /// Curvature radius [m]; 0 means straight track. double R = 0.0; // promien + /// Segment length [m]. double Len = 0.0; // dlugosc + /// Track gradient (rise/run). double dHtrack = 0.0; // nachylenie + /// Track cant / superelevation. double dHrail = 0.0; // przechylka }; +/// Per-segment track parameters: gauge, friction, category, load capacity, damage. struct TTrackParam -{/*parametry odcinka - szerokosc, tarcie statyczne, kategoria, obciazalnosc w t/os, uszkodzenia*/ +{ /*parametry odcinka - szerokosc, tarcie statyczne, kategoria, obciazalnosc w t/os, uszkodzenia*/ + /// Track gauge / width [m]. double Width = 0.0; + /// Static friction coefficient on this segment. double friction = 0.0; + /// Track category bit flags. int CategoryFlag = 0; + /// Track-quality bit flags. int QualityFlag = 0; + /// Track-damage bit flags (dtrack_*). int DamageFlag = 0; + /// Maximum allowed velocity on this segment (used by AI driver). double Velmax; /*dla uzytku maszynisty w ai_driver*/ }; +/// Traction-supply parameters at the vehicle's current location. struct TTractionParam { + /// Catenary voltage [V]. double TractionVoltage = 0.0; /*napiecie*/ + /// Catenary frequency [Hz] (0 for DC). double TractionFreq = 0.0; /*czestotliwosc*/ + /// Maximum current capacity [A]. double TractionMaxCurrent = 0.0; /*obciazalnosc*/ + /// Pantograph-catenary contact resistance [Ω]. double TractionResistivity = 0.0; /*rezystancja styku*/ }; /*powyzsze parametry zwiazane sa z torem po ktorym aktualnie pojazd jedzie*/ -/*typy hamulcow zespolonych*/ -enum class TBrakeSystem { Individual, Pneumatic, ElectroPneumatic }; -/*podtypy hamulcow zespolonych*/ -enum class TBrakeSubSystem { ss_None, ss_W, ss_K, ss_KK, ss_Hik, ss_ESt, ss_KE, ss_LSt, ss_MT, ss_Dako }; -enum class TBrakeValve { NoValve, W, W_Lu_VI, W_Lu_L, W_Lu_XR, K, Kg, Kp, Kss, Kkg, Kkp, Kks, Hikg1, Hikss, Hikp1, KE, SW, EStED, NESt3, ESt3, LSt, ESt4, ESt3AL2, EP1, EP2, M483, CV1_L_TR, CV1, CV1_R, Other }; -enum class TBrakeHandle { NoHandle, West, FV4a, M394, M254, FVE408, FVel6, D2, Knorr, FD1, BS2, testH, St113, MHZ_P, MHZ_T, MHZ_EN57, MHZ_K5P, MHZ_K8P, MHZ_6P }; -/*typy hamulcow indywidualnych*/ -enum class TLocalBrake { NoBrake, ManualBrake, PneumaticBrake, HydraulicBrake }; -/*dla osob/towar: opoznienie hamowania/odhamowania*/ +/// High-level brake-system family. +enum class TBrakeSystem +{ + /// Individual (vehicle-only) brake. + Individual, + /// Pneumatic brake (Westinghouse-style). + Pneumatic, + /// Electro-pneumatic brake. + ElectroPneumatic +}; +/// Brake-system subtype identifying the manufacturer's distributor family. +enum class TBrakeSubSystem +{ + ss_None, + ss_W, + ss_K, + ss_KK, + ss_Hik, + ss_ESt, + ss_KE, + ss_LSt, + ss_MT, + ss_Dako +}; +/// Specific brake-distributor (valve) model. +enum class TBrakeValve +{ + NoValve, + W, + W_Lu_VI, + W_Lu_L, + W_Lu_XR, + K, + Kg, + Kp, + Kss, + Kkg, + Kkp, + Kks, + Hikg1, + Hikss, + Hikp1, + KE, + SW, + EStED, + NESt3, + ESt3, + LSt, + ESt4, + ESt3AL2, + EP1, + EP2, + M483, + CV1_L_TR, + CV1, + CV1_R, + Other +}; +/// Specific driver's brake-handle model (cab valve). +enum class TBrakeHandle +{ + NoHandle, + West, + FV4a, + M394, + M254, + FVE408, + FVel6, + D2, + Knorr, + FD1, + BS2, + testH, + St113, + MHZ_P, + MHZ_T, + MHZ_EN57, + MHZ_K5P, + MHZ_K8P, + MHZ_6P +}; +/// Type of the auxiliary (independent) brake. +enum class TLocalBrake +{ + NoBrake, + ManualBrake, + PneumaticBrake, + HydraulicBrake +}; +/// Brake delay parameter table (apply/release for passenger and freight). typedef double TBrakeDelayTable[4]; +/// One row of the brake pressure / pipe pressure / flow-speed table for a brake handle position. struct TBrakePressure { + /// Brake pipe pressure target [bar]. double PipePressureVal = 0.0; + /// Brake cylinder pressure target [bar]. double BrakePressureVal = 0.0; + /// Flow speed (orifice scaling). double FlowSpeedVal = 0.0; + /// Brake system this entry applies to. TBrakeSystem BrakeType = TBrakeSystem::Pneumatic; }; -typedef std::map TBrakePressureTable; +/// Brake pressure table indexed by handle position. +typedef std::map TBrakePressureTable; -/*typy napedow*/ -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*/ -enum class TFuelType { Undefined, Coal, Oil }; -/*rodzaj rusztu*/ -struct TGrateType { +/// Engine / drive type. +enum class TEngineType +{ + None, + Dumb, + WheelsDriven, + ElectricSeriesMotor, + ElectricInductionMotor, + DieselEngine, + SteamEngine, + DieselElectric, + Main +}; +/// Form of energy supplied by the power source. +enum class TPowerType +{ + NoPower, + BioPower, + MechPower, + ElectricPower, + SteamPower +}; +/// Fuel type for combustion engines. +enum class TFuelType +{ + Undefined, + Coal, + Oil +}; +/// Steam-locomotive grate parameters. +struct TGrateType +{ + /// Fuel type burned on this grate. TFuelType FuelType; + /// Grate surface area [m²]. double GrateSurface; + /// Fuel transport speed (stoker rate). double FuelTransportSpeed; + /// Fuel ignition temperature [°C]. double IgnitionTemperature; + /// Maximum allowable grate temperature [°C]. double MaxTemperature; - //inline TGrateType() { - // FuelType = Undefined; - // GrateSurface = 0.0; - // FuelTransportSpeed = 0.0; - // IgnitionTemperature = 0.0; - // MaxTemperature = 0.0; - //} + // inline TGrateType() { + // FuelType = Undefined; + // GrateSurface = 0.0; + // FuelTransportSpeed = 0.0; + // IgnitionTemperature = 0.0; + // MaxTemperature = 0.0; + // } }; -/*rodzaj kotla*/ -struct TBoilerType { +/// Steam-locomotive boiler parameters. +struct TBoilerType +{ + /// Boiler internal volume [m³]. double BoilerVolume; + /// Heat exchange surface of the boiler [m²]. double BoilerHeatSurface; + /// Superheater surface [m²]. double SuperHeaterSurface; - double MaxWaterVolume; double MinWaterVolume; + /// Maximum water volume [m³]. + double MaxWaterVolume; + /// Minimum (safety) water volume [m³]. + double MinWaterVolume; + /// Maximum boiler pressure [bar]. double MaxPressure; - //inline TBoilerType() { - // BoilerVolume = 0.0; - // BoilerHeatSurface = 0.0; - // SuperHeaterSurface = 0.0; - // MaxWaterVolume = 0.0; - // MinWaterVolume = 0.0; - // MaxPressure = 0.0; - //} + // inline TBoilerType() { + // BoilerVolume = 0.0; + // BoilerHeatSurface = 0.0; + // SuperHeaterSurface = 0.0; + // MaxWaterVolume = 0.0; + // MinWaterVolume = 0.0; + // MaxPressure = 0.0; + // } }; -/*rodzaj odbieraka pradu*/ +/// Pantograph (current collector) model identifier. enum TPantType { + /// AKP-4E pantograph (PKP single-arm). AKP_4E, + /// DSA-series pantograph (Stemmann). DSAx, + /// EC160/EC200 pantograph. EC160_200, + /// WBL85 pantograph. WBL85 }; -struct TCurrentCollector { - long CollectorsNo; //musi być tu, bo inaczej się kopie - double MinH; double MaxH; //zakres ruchu pantografu, nigdzie nie używany - double CSW; //szerokość części roboczej (styku) ślizgacza - double MinV; double MaxV; //minimalne i maksymalne akceptowane napięcie - bool OVP; //czy jest przekaznik nadnapieciowy - double InsetV; //minimalne napięcie wymagane do załączenia - double MinPress; //minimalne ciśnienie do załączenia WS - double MaxPress; //maksymalne ciśnienie za reduktorem - bool FakePower; - int PhysicalLayout; +/// Current-collector (pantograph) configuration block. +struct TCurrentCollector +{ + /// Number of pantographs of this type. + long CollectorsNo; // musi być tu, bo inaczej się kopie + /// Minimum pantograph height [m] (currently unused). + double MinH; + /// Maximum pantograph height [m] (currently unused). + double MaxH; + /// Working width of the contact strip [m]. + double CSW; // szerokość części roboczej (styku) ślizgacza + /// Minimum acceptable contact-line voltage [V]. + double MinV; + /// Maximum acceptable contact-line voltage [V]. + double MaxV; + /// True if an over-voltage protection relay is fitted. + bool OVP; // czy jest przekaznik nadnapieciowy + /// Minimum voltage required to engage the main switch [V]. + double InsetV; // minimalne napięcie wymagane do załączenia + /// Minimum air pressure required to operate [bar]. + double MinPress; // minimalne ciśnienie do załączenia WS + /// Maximum air pressure after the reductor [bar]. + double MaxPress; // maksymalne ciśnienie za reduktorem + /// True if power output is faked (e.g. for AI vehicles without a model). + bool FakePower; + /// Physical layout id (orientation / side). + int PhysicalLayout; + /// Pantograph type (model). TPantType PantographType; - //inline TCurrentCollector() { - // CollectorsNo = 0; - // MinH, MaxH, CSW, MinV, MaxV = 0.0; - // OVP, InsetV, MinPress, MaxPress = 0.0; - //} + // inline TCurrentCollector() { + // CollectorsNo = 0; + // MinH, MaxH, CSW, MinV, MaxV = 0.0; + // OVP, InsetV, MinPress, MaxPress = 0.0; + // } }; -/*typy źródeł mocy*/ -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; +/// Power-source kind (where the vehicle gets electrical or mechanical energy from). +enum class TPowerSource +{ + NotDefined, + InternalSource, + Transducer, + Generator, + Accumulator, + CurrentCollector, + PowerCable, + Heater, + Main }; +/// Diesel engine driven generator parameters and outputs. +struct engine_generator +{ + // ld inputs + /// Pointer to the prime-mover revolutions [rev/s]. + double *engine_revolutions; // revs per second of the prime mover + // config + /// Minimum working rev rate [rev/s]. + double revolutions_min; // min working revolutions rate, in revs per second + /// Maximum working rev rate [rev/s]. + double revolutions_max; // max working revolutions rate, in revs per second + /// Voltage generated at revolutions_min [V]. + double voltage_min; // voltage generated at min working revolutions + /// Voltage generated at revolutions_max [V]. + double voltage_max; // voltage generated at max working revolutions + // ld outputs + /// Current rev rate [rev/s]. + double revolutions; + /// Current generated voltage [V]. + double voltage; +}; + +/// Battery / accumulator power source. struct TAccumulator { + /// Maximum capacity [Ah]. double MaxCapacity; + /// Source used to recharge the battery. TPowerSource RechargeSource; - //inline _mover__1() { - // MaxCapacity = 0.0; - // RechargeSource = NotDefined; - //} + // inline _mover__1() { + // MaxCapacity = 0.0; + // RechargeSource = NotDefined; + // } }; +/// Permanent power cable (e.g. to a heater) carrying a specific power form. struct TPowerCable { + /// Type of power transmitted. TPowerType PowerTrans; + /// Steam pressure (when SteamPower is transmitted) [bar]. double SteamPressure; - //inline _mover__2() { - // SteamPressure = 0.0; - // PowerTrans = NoPower; - //} + // inline _mover__2() { + // SteamPressure = 0.0; + // PowerTrans = NoPower; + // } }; +/// Steam locomotive boiler-and-grate combo. struct THeater { + /// Grate parameters. TGrateType Grate; + /// Boiler parameters. TBoilerType Boiler; }; -struct TTransducer { - // ld inputs - double InputVoltage; +/// Transducer (DC-DC / converter) parameters. +struct TTransducer +{ + // ld inputs + /// Input voltage [V]. + double InputVoltage; }; -/*parametry źródeł mocy*/ +/// +/// Generic power-source parameters. The trailing union holds source-specific +/// configuration depending on SourceType. +/// struct TPowerParameters { + /// Maximum source voltage [V]. double MaxVoltage; + /// Maximum source current [A]. double MaxCurrent; + /// Internal resistance [Ω]. double IntR; + /// Type of source (selects which union member is meaningful). TPowerSource SourceType; union { @@ -589,17 +1028,16 @@ struct TPowerParameters { TPowerType PowerType; }; - }; - inline TPowerParameters() - { - MaxVoltage = 0.0; - MaxCurrent = 0.0; - IntR = 0.001; - SourceType = TPowerSource::NotDefined; - PowerType = TPowerType::NoPower; - RPowerCable.PowerTrans = TPowerType::NoPower; - } + inline TPowerParameters() + { + MaxVoltage = 0.0; + MaxCurrent = 0.0; + IntR = 0.001; + SourceType = TPowerSource::NotDefined; + PowerType = TPowerType::NoPower; + RPowerCable.PowerTrans = TPowerType::NoPower; + } }; /*dla lokomotyw elektrycznych:*/ @@ -646,7 +1084,7 @@ struct TShuntScheme }; typedef TShuntScheme TShuntSchemeTable[33]; struct TMPTRelay -{/*lista przekaznikow bocznikowania*/ +{ /*lista przekaznikow bocznikowania*/ double Iup = 0.0; double Idown = 0.0; }; @@ -661,15 +1099,16 @@ struct TMotorParameters double Isat; double fi0; // aproksymacja E(n)=fi*n} {dla dizla fi, mfi: predkosci przelozenia biegu <-> bool AutoSwitch; - TMotorParameters() { - mfi = 0.0; - mIsat = 0.0; - mfi0 = 0.0; - fi = 0.0; - Isat = 0.0; - fi0 = 0.0; - AutoSwitch = false; - } + TMotorParameters() + { + mfi = 0.0; + mIsat = 0.0; + mfi0 = 0.0; + fi = 0.0; + Isat = 0.0; + fi0 = 0.0; + AutoSwitch = false; + } }; struct TUniversalCtrl @@ -684,7 +1123,7 @@ struct TUniversalCtrl int NextPosFastInc = 0; /*nastepna duza pozycja przy przechodzeniu szybkim*/ int PrevPosFastDec = 0; /*poprzednia duza pozycja przy przechodzeniu szybkim*/ }; -using TUniversalCtrlTable = std::array< TUniversalCtrl, UniversalCtrlArraySize + 1>; +using TUniversalCtrlTable = std::array; class TSecuritySystem { @@ -714,7 +1153,7 @@ class TSecuritySystem double MaxHoldTime = 1.5; bool CabDependent = false; -public: + public: void set_enabled(bool e); void acknowledge_press(); void acknowledge_release(); @@ -737,77 +1176,88 @@ public: }; struct TTransmision -{//liczba zebow przekladni +{ // liczba zebow przekladni int NToothM = 0; int NToothW = 0; double Ratio = 1.0; double Efficiency = 1.0; }; -enum class TCouplerType { NoCoupler, Articulated, Bare, Chain, Screw, Automatic }; - -struct power_coupling { - double current{ 0.0 }; - double voltage{ 0.0 }; - 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 +enum class TCouplerType +{ + NoCoupler, + Articulated, + Bare, + Chain, + Screw, + Automatic }; -struct TCoupling { +struct power_coupling +{ + double current{0.0}; + double voltage{0.0}; + 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 +{ /*parametry*/ - double SpringKB = 1.0; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */ - double DmaxB = 0.1; /*tolerancja scisku/rozciagania, sila rozerwania*/ - double FmaxB = 1000.0; - double SpringKC = 1.0; - double DmaxC = 0.1; - double FmaxC = 1000.0; - double beta = 0.0; - TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/ - int AutomaticCouplingFlag = coupling::coupler; - int AllowedFlag = ( coupling::coupler | coupling::brakehose ); //Ra: maska dostępnych - int PowerFlag = ( coupling::power110v | coupling::power24v ); - int PowerCoupling = coupling::permanent; // type of coupling required for power transfer - /*zmienne*/ - bool AutomaticCouplingAllowed { true }; // whether automatic coupling can be currently performed + double SpringKB = 1.0; /*stala sprezystosci zderzaka/sprzegu, %tlumiennosci */ + double DmaxB = 0.1; /*tolerancja scisku/rozciagania, sila rozerwania*/ + double FmaxB = 1000.0; + double SpringKC = 1.0; + double DmaxC = 0.1; + double FmaxC = 1000.0; + double beta = 0.0; + TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/ + int AutomaticCouplingFlag = coupling::coupler; + int AllowedFlag = (coupling::coupler | coupling::brakehose); // Ra: maska dostępnych + int PowerFlag = (coupling::power110v | coupling::power24v); + int PowerCoupling = coupling::permanent; // type of coupling required for power transfer + /*zmienne*/ + bool AutomaticCouplingAllowed{true}; // whether automatic coupling can be currently performed int CouplingFlag = 0; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/ class TMoverParameters *Connected = nullptr; /*co jest podlaczone*/ - int ConnectedNr = 0; //Ra: od której strony podłączony do (Connected): 0=przód, 1=tył - double CForce = 0.0; /*sila z jaka dzialal*/ - double Dist = 0.0; /*strzalka ugiecia zderzaków*/ - bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/ - float stretch_duration { 0.f }; // seconds, elapsed time with excessive force applied to the coupler - // optional adapter piece - double adapter_length { 0.0 }; // meters, value added on the given end to standard vehicle (half)length - double adapter_height { 0.0 }; // meters, distance from rail level - TCouplerType adapter_type = TCouplerType::NoCoupler; // CouplerType override if other than NoCoupler + int ConnectedNr = 0; // Ra: od której strony podłączony do (Connected): 0=przód, 1=tył + double CForce = 0.0; /*sila z jaka dzialal*/ + double Dist = 0.0; /*strzalka ugiecia zderzaków*/ + bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/ + float stretch_duration{0.f}; // seconds, elapsed time with excessive force applied to the coupler + // optional adapter piece + double adapter_length{0.0}; // meters, value added on the given end to standard vehicle (half)length + double adapter_height{0.0}; // meters, distance from rail level + TCouplerType adapter_type = TCouplerType::NoCoupler; // CouplerType override if other than NoCoupler - power_coupling power_high; - power_coupling power_110v; - power_coupling power_24v; + power_coupling power_high; + power_coupling power_110v; + power_coupling power_24v; - int sounds { 0 }; // sounds emitted by the coupling devices - bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/ - std::string control_type; // abstraction of control coupling interface and communication standard + int sounds{0}; // sounds emitted by the coupling devices + bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/ + std::string control_type; // abstraction of control coupling interface and communication standard - inline bool - has_adapter() const { - return ( adapter_type != TCouplerType::NoCoupler ); } - inline TCouplerType const - type() const { - return ( - adapter_type == TCouplerType::NoCoupler ? - CouplerType : - adapter_type ); } + inline bool has_adapter() const + { + return (adapter_type != TCouplerType::NoCoupler); + } + inline TCouplerType const type() const + { + return (adapter_type == TCouplerType::NoCoupler ? CouplerType : adapter_type); + } }; class TDynamicObject; -struct neighbour_data { - TDynamicObject *vehicle { nullptr }; // detected obstacle - int vehicle_end { -1 }; // facing end of the obstacle - float distance { 10000.f }; // distance to the obstacle // NOTE: legacy value. TBD, TODO: use standard -1 instead? +struct neighbour_data +{ + TDynamicObject *vehicle{nullptr}; // detected obstacle + int vehicle_end{-1}; // facing end of the obstacle + float distance{10000.f}; // distance to the obstacle // NOTE: legacy value. TBD, TODO: use standard -1 instead? }; -struct speed_control { +struct speed_control +{ bool IsActive = false; bool Start = false; bool ManualStateOverride = true; @@ -833,11 +1283,12 @@ struct speed_control { double FactorIpos = 0.0; double FactorIneg = 0.0; double BrakeInterventionVel = 30.0; - double PowerUpSpeed = 1000; - double PowerDownSpeed = 1000; + double PowerUpSpeed = 1000; + double PowerDownSpeed = 1000; }; -struct inverter { +struct inverter +{ double Freal = 0.0; double Request = 0.0; bool IsActive = true; @@ -1813,9 +2264,9 @@ class TMoverParameters int modernDimmerPosition{0}; int modernDimmerDefaultPosition{0}; - //bool modernContainOffPos{true}; - bool enableModernDimmer {false}; - bool modernDimmerCanCycle {false}; + // bool modernContainOffPos{true}; + bool enableModernDimmer{false}; + bool modernDimmerCanCycle{false}; // Barwa reflektora int refR{255}; // Czerwony @@ -1827,97 +2278,97 @@ class TMoverParameters double highDimMultiplier{2.5f}; // mnoznik dlugich przyciemnionych double highMultiplier{2.8f}; // mnoznik dlugich - plc::basic_controller m_plc; + plc::basic_controller m_plc; - int AIHintPantstate{ 0 }; // suggested pantograph setup - bool AIHintPantUpIfIdle{ true }; // whether raise both pantographs if idling for a while - double AIHintLocalBrakeAccFactor{ 1.05 }; // suggested acceleration weight for local brake operation + int AIHintPantstate{0}; // suggested pantograph setup + bool AIHintPantUpIfIdle{true}; // whether raise both pantographs if idling for a while + double AIHintLocalBrakeAccFactor{1.05}; // suggested acceleration weight for local brake operation -public: + public: TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab); // obsługa sprzęgów - static double CouplerDist( TMoverParameters const *Left, TMoverParameters const *Right ); - static double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2); + static double CouplerDist(TMoverParameters const *Left, TMoverParameters const *Right); + static double Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2); bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Enforce = false, bool Audible = true); int DettachStatus(int ConnectNo); bool Dettach(int ConnectNo); - void damage_coupler( int const End ); - void Derail(DerailReason Reason); + void damage_coupler(int const End); + void Derail(DerailReason Reason); bool DirectionForward(); - bool DirectionBackward( void );/*! kierunek ruchu*/ - bool EIMDirectionChangeAllow( void ) const; - inline double IsVehicleEIMBrakingFactor() { - return ( - ( DynamicBrakeFlag && ResistorsFlag ) ? 0.0 : - eimv[ eimv_Ipoj ] < 0 ? -1.0 : - 1.0 ); } + bool DirectionBackward(void); /*! kierunek ruchu*/ + bool EIMDirectionChangeAllow(void) const; + inline double IsVehicleEIMBrakingFactor() + { + return ((DynamicBrakeFlag && ResistorsFlag) ? 0.0 : eimv[eimv_Ipoj] < 0 ? -1.0 : 1.0); + } void BrakeLevelSet(double b); bool BrakeLevelAdd(double b); bool IncBrakeLevel(); // wersja na użytek AI bool DecBrakeLevel(); bool ChangeCab(int direction); bool CurrentSwitch(bool const State); - bool IsMotorOverloadRelayHighThresholdOn() const; + bool IsMotorOverloadRelayHighThresholdOn() const; void UpdateBatteryVoltage(double dt); - double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, TLocation const &NewLoc, TRotation const &NewRot); //oblicza przesuniecie pojazdu - double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, TLocation const &NewLoc, TRotation const &NewRot); //oblicza przesuniecie pojazdu - wersja zoptymalizowana - void compute_movement_( double const Deltatime ); + double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, TLocation const &NewLoc, + TRotation const &NewRot); // oblicza przesuniecie pojazdu + double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, TLocation const &NewLoc, TRotation const &NewRot); // oblicza przesuniecie pojazdu - wersja zoptymalizowana + void compute_movement_(double const Deltatime); double ShowEngineRotation(int VehN); // Q ******************************************************************************************* - double GetTrainsetVoltage( int const Coupling = ( coupling::heating | coupling::highvoltage ) ) const; - double GetTrainsetHighVoltage() const; + double GetTrainsetVoltage(int const Coupling = (coupling::heating | coupling::highvoltage)) const; + double GetTrainsetHighVoltage() const; bool switch_physics(bool const State); double LocalBrakeRatio(void); double ManualBrakeRatio(void); - double PipeRatio(void);/*ile napelniac*/ - double RealPipeRatio(void);/*jak szybko*/ + double PipeRatio(void); /*ile napelniac*/ + double RealPipeRatio(void); /*jak szybko*/ double BrakeVP(void) const; - double EngineRPMRatio() const; // returns current engine revolutions as percentage of max engine revolutions, in range 0-1 - double EngineIdleRPM() const; - double EngineMaxRPM() const; + double EngineRPMRatio() const; // returns current engine revolutions as percentage of max engine revolutions, in range 0-1 + double EngineIdleRPM() const; + double EngineMaxRPM() const; /*! przesylanie komend sterujacych*/ - bool SendCtrlToNext(std::string const CtrlCommand, double const ctrlvalue, double const dir, int const Couplertype = coupling::control ); - bool SetInternalCommand( std::string NewCommand, double NewValue1, double NewValue2, int const Couplertype = coupling::control ); + bool SendCtrlToNext(std::string const CtrlCommand, double const ctrlvalue, double const dir, int const Couplertype = coupling::control); + bool SetInternalCommand(std::string NewCommand, double NewValue1, double NewValue2, int const Couplertype = coupling::control); double GetExternalCommand(std::string &Command); - bool RunCommand( std::string Command, double CValue1, double CValue2, int const Couplertype = coupling::control ); - bool RunInternalCommand(); + bool RunCommand(std::string Command, double CValue1, double CValue2, int const Couplertype = coupling::control); + bool RunInternalCommand(); void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation); - bool CabActivisation( bool const Enforce = false ); - bool CabDeactivisation( bool const Enforce = false ); - bool CabActivisationAuto( bool const Enforce = false ); - bool CabDeactivisationAuto( bool const Enforce = false ); + bool CabActivisation(bool const Enforce = false); + bool CabDeactivisation(bool const Enforce = false); + bool CabActivisationAuto(bool const Enforce = false); + bool CabDeactivisationAuto(bool const Enforce = false); /*! funkcje zwiekszajace/zmniejszajace nastawniki*/ /*! glowny nastawnik:*/ bool IncMainCtrl(int CtrlSpeed); bool DecMainCtrl(int CtrlSpeed); - bool IsMainCtrlActualNoPowerPos() const; // whether the master controller is actually set to position which won't generate any extra power - bool IsMainCtrlNoPowerPos() const; // whether the master controller is set to position which won't generate any extra power - bool IsMainCtrlMaxPowerPos() const; - int MainCtrlNoPowerPos() const; // highest setting of master controller which won't cause engine to generate extra power - int MainCtrlActualPowerPos() const; // current actual setting of master controller, relative to the highest setting not generating extra power - int MainCtrlPowerPos() const; // current setting of master controller, relative to the highest setting not generating extra power + bool IsMainCtrlActualNoPowerPos() const; // whether the master controller is actually set to position which won't generate any extra power + bool IsMainCtrlNoPowerPos() const; // whether the master controller is set to position which won't generate any extra power + bool IsMainCtrlMaxPowerPos() const; + int MainCtrlNoPowerPos() const; // highest setting of master controller which won't cause engine to generate extra power + int MainCtrlActualPowerPos() const; // current actual setting of master controller, relative to the highest setting not generating extra power + int MainCtrlPowerPos() const; // current setting of master controller, relative to the highest setting not generating extra power /*! pomocniczy nastawnik:*/ bool IncScndCtrl(int CtrlSpeed); bool DecScndCtrl(int CtrlSpeed); int GetVirtualScndPos(); - bool IsScndCtrlNoPowerPos() const; - bool IsScndCtrlMaxPowerPos() const; + bool IsScndCtrlNoPowerPos() const; + bool IsScndCtrlMaxPowerPos() const; - bool AddPulseForce(int Multipler);/*dla drezyny*/ + bool AddPulseForce(int Multipler); /*dla drezyny*/ - bool SandboxManual( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza reczne sypanie piasku*/ - bool SandboxAuto( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza automatyczne sypanie piasku*/ - bool Sandbox( bool const State, range_t const Notify = range_t::consist );/*wlacza/wylacza sypanie piasku*/ - bool SandboxAutoAllow(bool const State);/*wlacza/wylacza zezwolenie na automatyczne sypanie piasku*/ + bool SandboxManual(bool const State, range_t const Notify = range_t::consist); /*wlacza/wylacza reczne sypanie piasku*/ + bool SandboxAuto(bool const State, range_t const Notify = range_t::consist); /*wlacza/wylacza automatyczne sypanie piasku*/ + bool Sandbox(bool const State, range_t const Notify = range_t::consist); /*wlacza/wylacza sypanie piasku*/ + bool SandboxAutoAllow(bool const State); /*wlacza/wylacza zezwolenie na automatyczne sypanie piasku*/ - /*! zbijanie czuwaka/SHP*/ + /*! zbijanie czuwaka/SHP*/ void SecuritySystemReset(void); void SecuritySystemCheck(double dt); - bool BatterySwitch( bool State, range_t const Notify = range_t::consist ); + bool BatterySwitch(bool State, range_t const Notify = range_t::consist); bool EpFuseSwitch(bool State); bool SpringBrakeActivate(bool State); bool SpringBrakeShutOff(bool State); @@ -1933,30 +2384,30 @@ public: bool DecManualBrakeLevel(int CtrlSpeed); bool DynamicBrakeSwitch(bool Switch); bool RadiostopSwitch(bool Switch); - bool AlarmChainSwitch( bool const State ); + bool AlarmChainSwitch(bool const State); bool AntiSlippingBrake(void); bool BrakeReleaser(int state); bool UniversalBrakeButton(int button, int state); /*uniwersalny przycisk hamulca*/ bool SwitchEPBrake(int state); bool AntiSlippingButton(void); /*! reczny wlacznik urzadzen antyposlizgowych*/ - /*funkcje dla ukladow pneumatycznych*/ + /*funkcje dla ukladow pneumatycznych*/ bool IncBrakePress(double &brake, double PressLimit, double dp); bool DecBrakePress(double &brake, double PressLimit, double dp); - bool BrakeDelaySwitch(int BDS);/*! przelaczanie nastawy opoznienia*/ - bool IncBrakeMult(void);/*przelaczanie prozny/ladowny*/ + bool BrakeDelaySwitch(int BDS); /*! przelaczanie nastawy opoznienia*/ + bool IncBrakeMult(void); /*przelaczanie prozny/ladowny*/ bool DecBrakeMult(void); /*pomocnicze funkcje dla ukladow pneumatycznych*/ void UpdateBrakePressure(double dt); void UpdatePipePressure(double dt); - void CompressorCheck(double dt);/*wlacza, wylacza kompresor, laduje zbiornik*/ - void UpdatePantVolume(double dt); //Ra + void CompressorCheck(double dt); /*wlacza, wylacza kompresor, laduje zbiornik*/ + void UpdatePantVolume(double dt); // Ra void UpdateScndPipePressure(double dt); void UpdateSpringBrake(double dt); double GetDVc(double dt); /*funkcje obliczajace sily*/ - void ComputeConstans(void);//ABu: wczesniejsze wyznaczenie stalych dla liczenia sil + void ComputeConstans(void); // ABu: wczesniejsze wyznaczenie stalych dla liczenia sil void ComputeMass(void); void ComputeTotalForce(double dt); double Adhesive(double staticfriction) const; @@ -1971,178 +2422,180 @@ public: double ComputeRotatingWheel(double WForce, double dt, double n) const; /*--funkcje dla lokomotyw*/ - bool WaterPumpBreakerSwitch( bool State, range_t const Notify = range_t::consist ); // water pump breaker state toggle - bool WaterPumpSwitch( bool State, range_t const Notify = range_t::consist ); // water pump state toggle - bool WaterPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // water pump state toggle - bool WaterHeaterBreakerSwitch( bool State, range_t const Notify = range_t::consist ); // water heater breaker state toggle - bool WaterHeaterSwitch( bool State, range_t const Notify = range_t::consist ); // water heater state toggle - bool WaterCircuitsLinkSwitch( bool State, range_t const Notify = range_t::consist ); // water circuits link state toggle - bool FuelPumpSwitch( bool State, range_t const Notify = range_t::consist ); // fuel pump state toggle - bool FuelPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // fuel pump state toggle - bool OilPumpSwitch( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle - bool OilPumpSwitchOff( bool State, range_t const Notify = range_t::consist ); // oil pump state toggle - bool MotorBlowersSwitch( bool State, end const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle - bool MotorBlowersSwitchOff( bool State, end const Side, range_t const Notify = range_t::consist ); // traction motor fan state toggle - bool CompartmentLightsSwitch( bool State, range_t const Notify = range_t::consist ); // compartment lights state toggle - bool CompartmentLightsSwitchOff( bool State, range_t const Notify = range_t::consist ); // compartment lights state toggle - bool MainSwitch( bool const State, range_t const Notify = range_t::consist );/*! wylacznik glowny*/ - void MainSwitch_( bool const State ); - bool MainSwitchCheck() const; // checks conditions for closing the line breaker - bool ConverterSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl przetwornicy*/ - bool CompressorSwitch( bool State, range_t const Notify = range_t::consist );/*! wl/wyl sprezarki*/ - bool ChangeCompressorPreset( int const Change, range_t const Notify = range_t::consist ); - bool HeatingSwitch( bool const State, range_t const Notify = range_t::consist ); - void HeatingSwitch_( bool const State ); - double EnginePowerSourceVoltage() const; // returns voltage of defined main engine power source + bool WaterPumpBreakerSwitch(bool State, range_t const Notify = range_t::consist); // water pump breaker state toggle + bool WaterPumpSwitch(bool State, range_t const Notify = range_t::consist); // water pump state toggle + bool WaterPumpSwitchOff(bool State, range_t const Notify = range_t::consist); // water pump state toggle + bool WaterHeaterBreakerSwitch(bool State, range_t const Notify = range_t::consist); // water heater breaker state toggle + bool WaterHeaterSwitch(bool State, range_t const Notify = range_t::consist); // water heater state toggle + bool WaterCircuitsLinkSwitch(bool State, range_t const Notify = range_t::consist); // water circuits link state toggle + bool FuelPumpSwitch(bool State, range_t const Notify = range_t::consist); // fuel pump state toggle + bool FuelPumpSwitchOff(bool State, range_t const Notify = range_t::consist); // fuel pump state toggle + bool OilPumpSwitch(bool State, range_t const Notify = range_t::consist); // oil pump state toggle + bool OilPumpSwitchOff(bool State, range_t const Notify = range_t::consist); // oil pump state toggle + bool MotorBlowersSwitch(bool State, end const Side, range_t const Notify = range_t::consist); // traction motor fan state toggle + bool MotorBlowersSwitchOff(bool State, end const Side, range_t const Notify = range_t::consist); // traction motor fan state toggle + bool CompartmentLightsSwitch(bool State, range_t const Notify = range_t::consist); // compartment lights state toggle + bool CompartmentLightsSwitchOff(bool State, range_t const Notify = range_t::consist); // compartment lights state toggle + bool MainSwitch(bool const State, range_t const Notify = range_t::consist); /*! wylacznik glowny*/ + void MainSwitch_(bool const State); + bool MainSwitchCheck() const; // checks conditions for closing the line breaker + bool ConverterSwitch(bool State, range_t const Notify = range_t::consist); /*! wl/wyl przetwornicy*/ + bool CompressorSwitch(bool State, range_t const Notify = range_t::consist); /*! wl/wyl sprezarki*/ + bool ChangeCompressorPreset(int const Change, range_t const Notify = range_t::consist); + bool HeatingSwitch(bool const State, range_t const Notify = range_t::consist); + void HeatingSwitch_(bool const State); + double EnginePowerSourceVoltage() const; // returns voltage of defined main engine power source - /*-funkcje typowe dla lokomotywy elektrycznej*/ - void LowVoltagePowerCheck( double const Deltatime ); - void MainsCheck( double const Deltatime ); - void PowerCouplersCheck( double const Deltatime, coupling const Coupling ); - void ConverterCheck( double const Timestep ); // przetwornica - void HeatingCheck( double const Timestep ); - void WaterPumpCheck( double const Timestep ); - void WaterHeaterCheck( double const Timestep ); - void FuelPumpCheck( double const Timestep ); - void OilPumpCheck( double const Timestep ); - void MotorBlowersCheck( double const Timestep ); - void PantographsCheck( double const Timestep ); - void LightsCheck( double const Timestep ); - bool FuseOn( range_t const Notify = range_t::consist ); //bezpiecznik nadamiary + /*-funkcje typowe dla lokomotywy elektrycznej*/ + void LowVoltagePowerCheck(double const Deltatime); + void MainsCheck(double const Deltatime); + void PowerCouplersCheck(double const Deltatime, coupling const Coupling); + void ConverterCheck(double const Timestep); // przetwornica + void HeatingCheck(double const Timestep); + void WaterPumpCheck(double const Timestep); + void WaterHeaterCheck(double const Timestep); + void FuelPumpCheck(double const Timestep); + void OilPumpCheck(double const Timestep); + void MotorBlowersCheck(double const Timestep); + void PantographsCheck(double const Timestep); + void LightsCheck(double const Timestep); + bool FuseOn(range_t const Notify = range_t::consist); // bezpiecznik nadamiary bool FuseFlagCheck(void) const; // sprawdzanie flagi nadmiarowego void FuseOff(void); // wylaczenie nadmiarowego - bool UniversalResetButton( int const Button, range_t const Notify = range_t::consist ); - bool RelayReset( int const Relays, range_t const Notify = range_t::consist ); // resets specified relays - double ShowCurrent( int AmpN ) const; //pokazuje bezwgl. wartosc pradu na wybranym amperomierzu - double ShowCurrentP(int AmpN) const; //pokazuje bezwgl. wartosc pradu w wybranym pojezdzie //Q 20160722 + bool UniversalResetButton(int const Button, range_t const Notify = range_t::consist); + bool RelayReset(int const Relays, range_t const Notify = range_t::consist); // resets specified relays + double ShowCurrent(int AmpN) const; // pokazuje bezwgl. wartosc pradu na wybranym amperomierzu + double ShowCurrentP(int AmpN) const; // pokazuje bezwgl. wartosc pradu w wybranym pojezdzie //Q 20160722 - /*!o pokazuje bezwgl. wartosc obrotow na obrotomierzu jednego z 3 pojazdow*/ - /*function ShowEngineRotation(VehN:int): integer; //Ra 2014-06: przeniesione do C++*/ - /*funkcje uzalezniajace sile pociagowa od predkosci: v2n, n2r, current, momentum*/ + /*!o pokazuje bezwgl. wartosc obrotow na obrotomierzu jednego z 3 pojazdow*/ + /*function ShowEngineRotation(VehN:int): integer; //Ra 2014-06: przeniesione do C++*/ + /*funkcje uzalezniajace sile pociagowa od predkosci: v2n, n2r, current, momentum*/ double v2n(void); double Current(double n, double U); double Momentum(double I); double MomentumF(double I, double Iw, int SCP); - bool CutOffEngine(void); //odlaczenie udszkodzonych silnikow - /*funkcje automatycznego rozruchu np EN57*/ - bool MaxCurrentSwitch(bool State, range_t const Notify = range_t::consist ); //przelacznik pradu wysokiego rozruchu - bool MinCurrentSwitch(bool State); //przelacznik pradu automatycznego rozruchu - bool AutoRelaySwitch(bool State); //przelacznik automatycznego rozruchu - bool AutoRelayCheck();//symulacja automatycznego rozruchu - bool MotorConnectorsCheck(); - bool ResistorsFlagCheck(void) const; //sprawdzenie kontrolki oporow rozruchowych NBMX + bool CutOffEngine(void); // odlaczenie udszkodzonych silnikow + /*funkcje automatycznego rozruchu np EN57*/ + bool MaxCurrentSwitch(bool State, range_t const Notify = range_t::consist); // przelacznik pradu wysokiego rozruchu + bool MinCurrentSwitch(bool State); // przelacznik pradu automatycznego rozruchu + bool AutoRelaySwitch(bool State); // przelacznik automatycznego rozruchu + bool AutoRelayCheck(); // symulacja automatycznego rozruchu + bool MotorConnectorsCheck(); + bool ResistorsFlagCheck(void) const; // sprawdzenie kontrolki oporow rozruchowych NBMX - bool OperatePantographsValve( operation_t const State, range_t const Notify = range_t::consist ); - bool OperatePantographValve( end const End, operation_t const State, range_t const Notify = range_t::consist ); - bool DropAllPantographs( bool const State, range_t const Notify = range_t::consist ); + bool OperatePantographsValve(operation_t const State, range_t const Notify = range_t::consist); + bool OperatePantographValve(end const End, operation_t const State, range_t const Notify = range_t::consist); + bool DropAllPantographs(bool const State, range_t const Notify = range_t::consist); - void CheckEIMIC(double dt); //sprawdzenie i zmiana nastawy zintegrowanego nastawnika jazdy/hamowania + void CheckEIMIC(double dt); // sprawdzenie i zmiana nastawy zintegrowanego nastawnika jazdy/hamowania void CheckSpeedCtrl(double dt); void SpeedCtrlButton(int button); void SpeedCtrlInc(); void SpeedCtrlDec(); - bool SpeedCtrlPowerInc(); - bool SpeedCtrlPowerDec(); + bool SpeedCtrlPowerInc(); + bool SpeedCtrlPowerDec(); - /*-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna*/ + /*-funkcje typowe dla lokomotywy spalinowej z przekladnia mechaniczna*/ bool dizel_EngageSwitch(double state); bool dizel_EngageChange(double dt); bool dizel_AutoGearCheck(void); double dizel_fillcheck(int mcp, 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_Heat( double const dt ); - bool dizel_StartupCheck(); - bool dizel_Update(double dt); + double dizel_MomentumRetarder(double n, double dt); // moment hamowania retardera + void dizel_HeatSet(float const Value); + void dizel_Heat(double const dt); + bool dizel_StartupCheck(); + bool dizel_Update(double dt); /* funckje dla wagonow*/ - bool AssignLoad( std::string const &Name, float const Amount = 0.f ); + bool AssignLoad(std::string const &Name, float const Amount = 0.f); bool LoadingDone(double LSpeed, std::string const &Loadname); - bool PermitDoors( side const Door, bool const State = true, range_t const Notify = range_t::consist ); - void PermitDoors_( side const Door, bool const State = true ); - bool ChangeDoorPermitPreset( int const Change, range_t const Notify = range_t::consist ); - bool PermitDoorStep( bool const State, range_t const Notify = range_t::consist ); - bool ChangeDoorControlMode( bool const State, range_t const Notify = range_t::consist ); - bool OperateDoors( side const Door, bool const State, range_t const Notify = range_t::consist ); - bool LockDoors( bool const State, range_t const Notify = range_t::consist ); - bool signal_departure( bool const State, range_t const Notify = range_t::consist ); // toggles departure warning - void update_doors( double const Deltatime ); // door controller update + bool PermitDoors(side const Door, bool const State = true, range_t const Notify = range_t::consist); + void PermitDoors_(side const Door, bool const State = true); + bool ChangeDoorPermitPreset(int const Change, range_t const Notify = range_t::consist); + bool PermitDoorStep(bool const State, range_t const Notify = range_t::consist); + bool ChangeDoorControlMode(bool const State, range_t const Notify = range_t::consist); + bool OperateDoors(side const Door, bool const State, range_t const Notify = range_t::consist); + bool LockDoors(bool const State, range_t const Notify = range_t::consist); + bool signal_departure(bool const State, range_t const Notify = range_t::consist); // toggles departure warning + void update_doors(double const Deltatime); // door controller update - /* funkcje dla samochodow*/ + /* funkcje dla samochodow*/ bool ChangeOffsetH(double DeltaOffset); /*funkcje ladujace pliki opisujace pojazd*/ - bool LoadFIZ(std::string chkpath); //Q 20160717 bool LoadChkFile(std::string chkpath); - bool CheckLocomotiveParameters( bool ReadyFlag, int Dir ); - std::string EngineDescription( int what ) const; -private: - void LoadFIZ_Param( std::string const &line ); - void LoadFIZ_Load( std::string const &line ); - void LoadFIZ_Dimensions( std::string const &line ); - void LoadFIZ_Wheels( std::string const &line ); - void LoadFIZ_Brake( std::string const &line ); - void LoadFIZ_Doors( std::string const &line ); - void LoadFIZ_BuffCoupl( std::string const &line, int const Index ); - void LoadFIZ_TurboPos( std::string const &line ); - void LoadFIZ_Cntrl( std::string const &line ); + bool LoadFIZ(std::string chkpath); // Q 20160717 bool LoadChkFile(std::string chkpath); + bool CheckLocomotiveParameters(bool ReadyFlag, int Dir); + std::string EngineDescription(int what) const; + + private: + void LoadFIZ_Param(std::string const &line); + void LoadFIZ_Load(std::string const &line); + void LoadFIZ_Dimensions(std::string const &line); + void LoadFIZ_Wheels(std::string const &line); + void LoadFIZ_Brake(std::string const &line); + void LoadFIZ_Doors(std::string const &line); + void LoadFIZ_BuffCoupl(std::string const &line, int const Index); + void LoadFIZ_TurboPos(std::string const &line); + void LoadFIZ_Cntrl(std::string const &line); void LoadFIZ_Blending(std::string const &line); void LoadFIZ_DCEMUED(std::string const &line); void LoadFIZ_SpringBrake(std::string const &line); - void LoadFIZ_Light( std::string const &line ); + void LoadFIZ_Light(std::string const &line); void LoadFIZ_Headlights(std::string const &Line); - void LoadFIZ_Clima( std::string const &line ); - void LoadFIZ_Power( std::string const &Line ); - void LoadFIZ_SpeedControl( std::string const &Line ); - void LoadFIZ_Engine( std::string const &Input ); - void LoadFIZ_Switches( std::string const &Input ); - void LoadFIZ_MotorParamTable( std::string const &Input ); - void LoadFIZ_Circuit( std::string const &Input ); - void LoadFIZ_AI( std::string const &Input ); - void LoadFIZ_RList( std::string const &Input ); + void LoadFIZ_Clima(std::string const &line); + void LoadFIZ_Power(std::string const &Line); + void LoadFIZ_SpeedControl(std::string const &Line); + void LoadFIZ_Engine(std::string const &Input); + void LoadFIZ_Switches(std::string const &Input); + void LoadFIZ_MotorParamTable(std::string const &Input); + void LoadFIZ_Circuit(std::string const &Input); + void LoadFIZ_AI(std::string const &Input); + void LoadFIZ_RList(std::string const &Input); void LoadFIZ_UCList(std::string const &Input); - void LoadFIZ_DList( std::string const &Input ); - void LoadFIZ_FFList( std::string const &Input ); - void LoadFIZ_FFEDList( std::string const &Input ); + void LoadFIZ_DList(std::string const &Input); + void LoadFIZ_FFList(std::string const &Input); + void LoadFIZ_FFEDList(std::string const &Input); void LoadFIZ_WiperList(std::string const &Input); - void LoadFIZ_LightsList( std::string const &Input ); + void LoadFIZ_LightsList(std::string const &Input); void LoadFIZ_DimmerList(std::string const &Input); void LoadFIZ_CompressorList(std::string const &Input); - void LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Input ); - TPowerType LoadFIZ_PowerDecode( std::string const &Power ); - TPowerSource LoadFIZ_SourceDecode( std::string const &Source ); - TEngineType LoadFIZ_EngineDecode( std::string const &Engine ); - bool readMPT0( std::string const &line ); - bool readMPT( std::string const &line ); //Q 20160717 - bool readMPTElectricSeries( std::string const &line ); - bool readMPTDieselElectric( std::string const &line ); - bool readMPTDieselEngine( std::string const &line ); - bool readBPT(/*int const ln,*/ std::string const &line); //Q 20160721 - bool readRList( std::string const &Input ); + void LoadFIZ_PowerParamsDecode(TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Input); + TPowerType LoadFIZ_PowerDecode(std::string const &Power); + TPowerSource LoadFIZ_SourceDecode(std::string const &Source); + TEngineType LoadFIZ_EngineDecode(std::string const &Engine); + bool readMPT0(std::string const &line); + bool readMPT(std::string const &line); // Q 20160717 + bool readMPTElectricSeries(std::string const &line); + bool readMPTDieselElectric(std::string const &line); + bool readMPTDieselEngine(std::string const &line); + bool readBPT(/*int const ln,*/ std::string const &line); // Q 20160721 + bool readRList(std::string const &Input); bool readUCList(std::string const &Input); - bool readDList( std::string const &line ); + bool readDList(std::string const &line); bool readDMList(std::string const &line); bool readV2NMAXList(std::string const &line); bool readHTCList(std::string const &line); bool readPmaxList(std::string const &line); - bool readFFList( std::string const &line ); - bool readFFEDList( std::string const &line ); - bool readWWList( std::string const &line ); - bool readWiperList( std::string const &line ); + bool readFFList(std::string const &line); + bool readFFEDList(std::string const &line); + bool readWWList(std::string const &line); + bool readWiperList(std::string const &line); bool readDimmerList(std::string const &line); - bool readLightsList( std::string const &Input ); + bool readLightsList(std::string const &Input); bool readCompressorList(std::string const &Input); - void BrakeValveDecode( std::string const &s ); //Q 20160719 - void BrakeSubsystemDecode(); //Q 20160719 + void BrakeValveDecode(std::string const &s); // Q 20160719 + void BrakeSubsystemDecode(); // Q 20160719 }; -//double Distance(TLocation Loc1, TLocation Loc2, TDimension Dim1, TDimension Dim2); +// double Distance(TLocation Loc1, TLocation Loc2, TDimension Dim1, TDimension Dim2); -namespace simulation { +namespace simulation +{ using weights_table = std::unordered_map; extern weights_table Weights; -} // simulation +} // namespace simulation diff --git a/McZapkie/Mover.cpp b/McZapkie/Mover.cpp index 96f384e3..c7b9699b 100644 --- a/McZapkie/Mover.cpp +++ b/McZapkie/Mover.cpp @@ -28,34 +28,28 @@ const double CouplerTune = 0.1; // skalowanie tlumiennosci int ConversionError = 0; -std::vector const TMoverParameters::eimc_labels = { - "dfic: ", "dfmax:", "p: ", "scfu: ", "cim: ", "icif: ", "Uzmax:", "Uzh: ", "DU: ", "I0: ", - "fcfu: ", "F0: ", "a1: ", "Pmax: ", "Fh: ", "Ph: ", "Vh0: ", "Vh1: ", "Imax: ", "abed: ", - "eped: " -}; +std::vector const TMoverParameters::eimc_labels = {"dfic: ", "dfmax:", "p: ", "scfu: ", "cim: ", "icif: ", "Uzmax:", "Uzh: ", "DU: ", "I0: ", "fcfu: ", + "F0: ", "a1: ", "Pmax: ", "Fh: ", "Ph: ", "Vh0: ", "Vh1: ", "Imax: ", "abed: ", "eped: "}; std::vector const TMoverParameters::eimv_labels = { - "Fkrt:", "Fmax:", "ks: ", "df: ", "fp: ", "Us: ", "pole:", "Ic: ", "If: ", "M: ", - "Fr: ", "Ipoj:", "Pm: ", "Pe: ", "eta: ", "fkr: ", "Uzsm:", "Pmax:", "Fzad:", "Imax:", - "Fful:" -}; + "Fkrt:", "Fmax:", "ks: ", "df: ", "fp: ", "Us: ", "pole:", "Ic: ", "If: ", "M: ", "Fr: ", "Ipoj:", "Pm: ", "Pe: ", "eta: ", "fkr: ", "Uzsm:", "Pmax:", "Fzad:", "Imax:", "Fful:"}; inline double square(double val) // SQR() zle liczylo w current() ... { - return val * val; + return val * val; } double ComputeCollision(double &v1, double &v2, double m1, double m2, double beta, bool vc) { // oblicza zmiane predkosci i przyrost pedu wskutek kolizji - assert( beta < 1.0 ); + assert(beta < 1.0); - if( ( v1 < v2 ) && ( vc == true ) ) + if ((v1 < v2) && (vc == true)) return 0; else { double sum = m1 + m2; - double w1 = ( m2 * v2 * 2.0 + v1 * ( m1 - m2 ) ) / sum; - double w2 = ( m1 * v1 * 2.0 + v2 * ( m2 - m1 ) ) / sum; + double w1 = (m2 * v2 * 2.0 + v1 * (m1 - m2)) / sum; + double w2 = (m1 * v1 * 2.0 + v2 * (m2 - m1)) / sum; v1 = w1 * std::sqrt(1.0 - beta); // niejawna zmiana predkosci wskutek zderzenia v2 = w2 * std::sqrt(1.0 - beta); return m1 * (w2 - w1) * (1 - beta); @@ -80,30 +74,35 @@ int DirF(int CouplerN) } } -void TSecuritySystem::set_enabled(bool e) { +void TSecuritySystem::set_enabled(bool e) +{ if (vigilance_enabled || cabsignal_enabled || radiostop_enabled) enabled = e; if (CabDependent) cabactive = 0; } -void TSecuritySystem::acknowledge_press() { +void TSecuritySystem::acknowledge_press() +{ pressed = true; - if (vigilance_timer > AwareDelay) { + if (vigilance_timer > AwareDelay) + { alert_timer = 0.0; vigilance_timer = 0.0; return; } vigilance_timer = 0.0; - if (!separate_acknowledge && cabsignal_active && !cabsignal_lock) { + if (!separate_acknowledge && cabsignal_active && !cabsignal_lock) + { cabsignal_active = false; alert_timer = 0.0; } } -void TSecuritySystem::acknowledge_release() { +void TSecuritySystem::acknowledge_release() +{ pressed = false; if (press_timer > MaxHoldTime) @@ -111,15 +110,19 @@ void TSecuritySystem::acknowledge_release() { press_timer = 0.0; } -void TSecuritySystem::cabsignal_reset() { - if (cabsignal_active && !cabsignal_lock) { +void TSecuritySystem::cabsignal_reset() +{ + if (cabsignal_active && !cabsignal_lock) + { cabsignal_active = false; alert_timer = 0.0; } } -void TSecuritySystem::update(double dt, double vel, bool pwr, int cab) { - if (!enabled || !pwr || DebugModeFlag) { +void TSecuritySystem::update(double dt, double vel, bool pwr, int cab) +{ + if (!enabled || !pwr || DebugModeFlag) + { power = pwr; cabsignal_active = false; vigilance_timer = 0.0; @@ -131,8 +134,9 @@ void TSecuritySystem::update(double dt, double vel, bool pwr, int cab) { bool just_powered_on = !power && pwr; bool just_activated = CabDependent && (cabactive != cab); - /* enabling battery */ - if (cabsignal_enabled && (just_powered_on || just_activated)) { + /* enabling battery */ + if (cabsignal_enabled && (just_powered_on || just_activated)) + { cabsignal_active = true; alert_timer = SoundSignalDelay; } @@ -147,121 +151,132 @@ void TSecuritySystem::update(double dt, double vel, bool pwr, int cab) { if (pressed && (!is_sifa || velocity > AwareMinSpeed)) press_timer += dt; - if (vigilance_timer > AwareDelay - || press_timer > MaxHoldTime - || cabsignal_active) + if (vigilance_timer > AwareDelay || press_timer > MaxHoldTime || cabsignal_active) alert_timer += dt; } -void TSecuritySystem::set_cabsignal() { - if (cabsignal_enabled && power) +void TSecuritySystem::set_cabsignal() +{ + if (cabsignal_enabled && power) cabsignal_active = true; } -bool TSecuritySystem::has_separate_acknowledge() const { +bool TSecuritySystem::has_separate_acknowledge() const +{ return separate_acknowledge; } -bool TSecuritySystem::is_blinking() const { - if (!power) - return false; +bool TSecuritySystem::is_blinking() const +{ + if (!power) + return false; return alert_timer > 0.0; } -bool TSecuritySystem::is_vigilance_blinking() const { - if (!power) - return false; +bool TSecuritySystem::is_vigilance_blinking() const +{ + if (!power) + return false; return press_timer > MaxHoldTime || vigilance_timer > AwareDelay; } -bool TSecuritySystem::is_cabsignal_blinking() const { - if (!power) - return false; +bool TSecuritySystem::is_cabsignal_blinking() const +{ + if (!power) + return false; return cabsignal_active; } -bool TSecuritySystem::is_beeping() const { - if (!power) - return false; +bool TSecuritySystem::is_beeping() const +{ + if (!power) + return false; return alert_timer > SoundSignalDelay && (!separate_acknowledge || is_vigilance_blinking()); } -bool TSecuritySystem::is_cabsignal_beeping() const { - if (!power) - return false; +bool TSecuritySystem::is_cabsignal_beeping() const +{ + if (!power) + return false; return alert_timer > SoundSignalDelay && is_cabsignal_blinking(); } -bool TSecuritySystem::is_braking() const { - if (!power && enabled) - return true; +bool TSecuritySystem::is_braking() const +{ + if (!power && enabled) + return true; - return alert_timer > SoundSignalDelay + EmergencyBrakeDelay; + return alert_timer > SoundSignalDelay + EmergencyBrakeDelay; } -bool TSecuritySystem::radiostop_available() const { +bool TSecuritySystem::radiostop_available() const +{ return radiostop_enabled; } -void TSecuritySystem::set_cabsignal_lock(bool v) { +void TSecuritySystem::set_cabsignal_lock(bool v) +{ cabsignal_lock = v; } -bool TSecuritySystem::is_engine_blocked() const { +bool TSecuritySystem::is_engine_blocked() const +{ if (!is_sifa) return false; return velocity < AwareMinSpeed && pressed; } -void TSecuritySystem::load(std::string const &line, double Vmax) { - std::string awaresystem = extract_value( "AwareSystem", line ); - if( awaresystem.find( "Active" ) != std::string::npos ) +void TSecuritySystem::load(std::string const &line, double Vmax) +{ + std::string awaresystem = extract_value("AwareSystem", line); + if (awaresystem.find("Active") != std::string::npos) vigilance_enabled = true; - if( awaresystem.find( "CabSignal" ) != std::string::npos ) + if (awaresystem.find("CabSignal") != std::string::npos) cabsignal_enabled = true; - if( awaresystem.find( "Sifa" ) != std::string::npos ) + if (awaresystem.find("Sifa") != std::string::npos) is_sifa = true; - if( awaresystem.find( "SeparateAcknowledge" ) != std::string::npos ) + if (awaresystem.find("SeparateAcknowledge") != std::string::npos) separate_acknowledge = true; - extract_value( AwareDelay, "AwareDelay", line, "" ); - AwareMinSpeed = 0.1 * Vmax; //domyślnie 10% Vmax - extract_value( AwareMinSpeed, "AwareMinSpeed", line, "" ); - extract_value( SoundSignalDelay, "SoundSignalDelay", line, "" ); - extract_value( EmergencyBrakeDelay, "EmergencyBrakeDelay", line, "" ); - extract_value( MaxHoldTime, "MaxHoldTime", line, "" ); - extract_value( radiostop_enabled, "RadioStop", line, "" ); - extract_value( MagnetLocation, "MagnetLocation", line, "" ); - extract_value( CabDependent, "CabDependent", line, "" ); + extract_value(AwareDelay, "AwareDelay", line, ""); + AwareMinSpeed = 0.1 * Vmax; // domyślnie 10% Vmax + extract_value(AwareMinSpeed, "AwareMinSpeed", line, ""); + extract_value(SoundSignalDelay, "SoundSignalDelay", line, ""); + extract_value(EmergencyBrakeDelay, "EmergencyBrakeDelay", line, ""); + extract_value(MaxHoldTime, "MaxHoldTime", line, ""); + extract_value(radiostop_enabled, "RadioStop", line, ""); + extract_value(MagnetLocation, "MagnetLocation", line, ""); + extract_value(CabDependent, "CabDependent", line, ""); } -double TableInterpolation(std::map &Map, double Parameter) +double TableInterpolation(std::map &Map, double Parameter) { - if (Map.size() == 0) - return 0.0; - if (Map.size() == 1) - return Map.begin()->second; + if (Map.size() == 0) + return 0.0; + if (Map.size() == 1) + return Map.begin()->second; - auto lower = Map.lower_bound(Parameter); - auto upper = lower; - - if (lower != Map.begin()) - lower--; - else - upper++; + auto lower = Map.lower_bound(Parameter); + auto upper = lower; - if (upper == Map.end()) { - lower--; - upper--; - } - double ratio = (upper->second - lower->second) / (upper->first - lower->first); - return (lower->second + (Parameter - lower->first) * ratio); + if (lower != Map.begin()) + lower--; + else + upper++; + + if (upper == Map.end()) + { + lower--; + upper--; + } + double ratio = (upper->second - lower->second) / (upper->first - lower->first); + return (lower->second + (Parameter - lower->first) * ratio); } // ************************************************************************************************* @@ -270,103 +285,101 @@ double TableInterpolation(std::map &Map, double Parameter) // ************************************************************************************************* double TMoverParameters::Current(double n, double U) { - // wazna funkcja - liczy prad plynacy przez silniki polaczone szeregowo lub rownolegle - // w zaleznosci od polozenia nastawnikow MainCtrl i ScndCtrl oraz predkosci obrotowej n - // a takze wywala bezpiecznik nadmiarowy gdy za duzy prad lub za male napiecie - // jest takze mozliwosc uszkodzenia silnika wskutek nietypowych parametrow + // wazna funkcja - liczy prad plynacy przez silniki polaczone szeregowo lub rownolegle + // w zaleznosci od polozenia nastawnikow MainCtrl i ScndCtrl oraz predkosci obrotowej n + // a takze wywala bezpiecznik nadmiarowy gdy za duzy prad lub za male napiecie + // jest takze mozliwosc uszkodzenia silnika wskutek nietypowych parametrow - double R, MotorCurrent; - double Rz, Delta, Isf; - double Mn; // przujmuje int, ale dla poprawnosci obliczeń - double Bn; - int SP = 0; - double U1; // napiecie z korekta + double R, MotorCurrent; + double Rz, Delta, Isf; + double Mn; // przujmuje int, ale dla poprawnosci obliczeń + double Bn; + int SP = 0; + double U1; // napiecie z korekta - MotorCurrent = 0; - // i dzialanie hamulca ED w EP09 - if ((DynamicBrakeType == dbrake_automatic)&&(TrainType != dt_EZT)) - { - if (((Hamulec->GetEDBCP() < 0.25) && (Vadd < 1)) || (BrakePress > 2.1)) - DynamicBrakeFlag = false; - else if ((BrakePress > 0.25) && (Hamulec->GetEDBCP() > 0.25)) - DynamicBrakeFlag = true; - DynamicBrakeFlag = (DynamicBrakeFlag && Power110vIsAvailable); - } + MotorCurrent = 0; + // i dzialanie hamulca ED w EP09 + if ((DynamicBrakeType == dbrake_automatic) && (TrainType != dt_EZT)) + { + if (((Hamulec->GetEDBCP() < 0.25) && (Vadd < 1)) || (BrakePress > 2.1)) + DynamicBrakeFlag = false; + else if ((BrakePress > 0.25) && (Hamulec->GetEDBCP() > 0.25)) + DynamicBrakeFlag = true; + DynamicBrakeFlag = (DynamicBrakeFlag && Power110vIsAvailable); + } if ((DynamicBrakeType == dbrake_automatic) && (TrainType == dt_EZT)) { - DynamicBrakeFlag = (Power110vIsAvailable && (TUHEX_Active || (Vadd>TUHEX_MinIw)) && DynamicBrakeEMUStatus); + DynamicBrakeFlag = (Power110vIsAvailable && (TUHEX_Active || (Vadd > TUHEX_MinIw)) && DynamicBrakeEMUStatus); } - // wylacznik cisnieniowy yBARC - to jest chyba niepotrzebne tutaj Q: no to usuwam... + // wylacznik cisnieniowy yBARC - to jest chyba niepotrzebne tutaj Q: no to usuwam... - // BrakeSubsystem = ss_LSt; - // if (BrakeSubsystem == ss_LSt) WriteLog("LSt"); - // if (BrakeSubsystem == ss_LSt) // zrobiona funkcja virtualna - if (DynamicBrakeFlag) - { - Hamulec->SetED(abs(Im / 350)); // hamulec ED na EP09 dziala az do zatrzymania lokomotywy - //- WriteLog("A"); - } - else - { - Hamulec->SetED(0); - //- WriteLog("B"); - } + // BrakeSubsystem = ss_LSt; + // if (BrakeSubsystem == ss_LSt) WriteLog("LSt"); + // if (BrakeSubsystem == ss_LSt) // zrobiona funkcja virtualna + if (DynamicBrakeFlag) + { + Hamulec->SetED(abs(Im / 350)); // hamulec ED na EP09 dziala az do zatrzymania lokomotywy + //- WriteLog("A"); + } + else + { + Hamulec->SetED(0); + //- WriteLog("B"); + } - ResistorsFlag = (RList[MainCtrlActualPos].R > 0.01); // and (!DelayCtrlFlag) - ResistorsFlag = - (ResistorsFlag || ((DynamicBrakeFlag == true) && (DynamicBrakeType == dbrake_automatic))); + ResistorsFlag = (RList[MainCtrlActualPos].R > 0.01); // and (!DelayCtrlFlag) + ResistorsFlag = (ResistorsFlag || ((DynamicBrakeFlag == true) && (DynamicBrakeType == dbrake_automatic))); - if ((TrainType == dt_ET22) && (DelayCtrlFlag) && (MainCtrlActualPos > 1)) - Bn = 1.0 - 1.0 / RList[MainCtrlActualPos].Bn; - else - Bn = 1; // to jest wykonywane dla EU07 + if ((TrainType == dt_ET22) && (DelayCtrlFlag) && (MainCtrlActualPos > 1)) + Bn = 1.0 - 1.0 / RList[MainCtrlActualPos].Bn; + else + Bn = 1; // to jest wykonywane dla EU07 - R = RList[MainCtrlActualPos].R * Bn + CircuitRes; + R = RList[MainCtrlActualPos].R * Bn + CircuitRes; - if( ( TrainType != dt_EZT ) - || ( Imin != IminLo ) - || ( false == ScndS ) ) { - // yBARC - boczniki na szeregu poprawnie - Mn = RList[ MainCtrlActualPos ].Mn; // to jest wykonywane dla EU07 - } - else { - Mn = RList[ MainCtrlActualPos ].Mn * RList[ MainCtrlActualPos ].Bn; - if( RList[ MainCtrlActualPos ].Bn > 1 ) { - Bn = 1; - R = CircuitRes; - } - } + if ((TrainType != dt_EZT) || (Imin != IminLo) || (false == ScndS)) + { + // yBARC - boczniki na szeregu poprawnie + Mn = RList[MainCtrlActualPos].Mn; // to jest wykonywane dla EU07 + } + else + { + Mn = RList[MainCtrlActualPos].Mn * RList[MainCtrlActualPos].Bn; + if (RList[MainCtrlActualPos].Bn > 1) + { + Bn = 1; + R = CircuitRes; + } + } - if (DynamicBrakeFlag && (!FuseFlag) && (DynamicBrakeType == dbrake_automatic) && - Power110vIsAvailable && Mains) // hamowanie EP09 //TUHEX - { + if (DynamicBrakeFlag && (!FuseFlag) && (DynamicBrakeType == dbrake_automatic) && Power110vIsAvailable && Mains) // hamowanie EP09 //TUHEX + { // TODO: zrobic bardziej uniwersalne nie tylko dla EP09 - MotorCurrent = - -Max0R(MotorParam[0].fi * (Vadd / (Vadd + MotorParam[0].Isat) - MotorParam[0].fi0), 0) * n * 2.0 / DynamicBrakeRes; - } - else if( ( RList[ MainCtrlActualPos ].Bn == 0 ) - || ( false == StLinFlag ) ) { - // wylaczone - MotorCurrent = 0; - } - else - { // wlaczone... - SP = ScndCtrlActualPos; + MotorCurrent = -Max0R(MotorParam[0].fi * (Vadd / (Vadd + MotorParam[0].Isat) - MotorParam[0].fi0), 0) * n * 2.0 / DynamicBrakeRes; + } + else if ((RList[MainCtrlActualPos].Bn == 0) || (false == StLinFlag)) + { + // wylaczone + MotorCurrent = 0; + } + else + { // wlaczone... + SP = ScndCtrlActualPos; - if (ScndCtrlActualPos < 255) // tak smiesznie bede wylaczal - { - if( ( ScndInMain ) - && ( RList[ MainCtrlActualPos ].ScndAct != 255 ) ) { - SP = RList[ MainCtrlActualPos ].ScndAct; - } + if (ScndCtrlActualPos < 255) // tak smiesznie bede wylaczal + { + if ((ScndInMain) && (RList[MainCtrlActualPos].ScndAct != 255)) + { + SP = RList[MainCtrlActualPos].ScndAct; + } - Rz = Mn * WindingRes + R; + Rz = Mn * WindingRes + R; - if (DynamicBrakeFlag) // hamowanie - { - if (DynamicBrakeType > 1) - { + if (DynamicBrakeFlag) // hamowanie + { + if (DynamicBrakeType > 1) + { // if DynamicBrakeType<>dbrake_automatic then // MotorCurrent:=-fi*n/Rz {hamowanie silnikiem na oporach rozruchowych} /* begin @@ -378,45 +391,41 @@ double TMoverParameters::Current(double n, double U) if ((DynamicBrakeType == dbrake_switch) && (TrainType == dt_ET42)) { // z Megapacka Rz = WindingRes + R; - MotorCurrent = - -MotorParam[SP].fi * n / Rz; //{hamowanie silnikiem na oporach rozruchowych} + MotorCurrent = -MotorParam[SP].fi * n / Rz; //{hamowanie silnikiem na oporach rozruchowych} } } - else - MotorCurrent = 0; // odciecie pradu od silnika - } - else - { - U1 = U + Mn * n * MotorParam[SP].fi0 * MotorParam[SP].fi; - // writepaslog("U1 ", FloatToStr(U1)); - // writepaslog("Isat ", FloatToStr(MotorParam[SP].Isat)); - // writepaslog("fi ", FloatToStr(MotorParam[SP].fi)); - Isf = Sign(U1) * MotorParam[SP].Isat; - // writepaslog("Isf ", FloatToStr(Isf)); - Delta = square(Isf * Rz + Mn * MotorParam[SP].fi * n - U1) + - 4.0 * U1 * Isf * Rz; // 105 * 1.67 + Mn * 140.9 * 20.532 - U1 - // DeltaQ = Isf * Rz + Mn * MotorParam[SP].fi * n - U1 + 4 * U1 * Isf * Rz; - // writepaslog("Delta ", FloatToStr(Delta)); - // writepaslog("DeltaQ ", FloatToStr(DeltaQ)); - // writepaslog("U ", FloatToStr(U)); - if (Mains) - { - if (U > 0) - MotorCurrent = - (U1 - Isf * Rz - Mn * MotorParam[SP].fi * n + std::sqrt(Delta)) / (2.0 * Rz); - else - MotorCurrent = - (U1 - Isf * Rz - Mn * MotorParam[SP].fi * n - std::sqrt(Delta)) / (2.0 * Rz); - } - else - MotorCurrent = 0; - } // else DBF + else + MotorCurrent = 0; // odciecie pradu od silnika + } + else + { + U1 = U + Mn * n * MotorParam[SP].fi0 * MotorParam[SP].fi; + // writepaslog("U1 ", FloatToStr(U1)); + // writepaslog("Isat ", FloatToStr(MotorParam[SP].Isat)); + // writepaslog("fi ", FloatToStr(MotorParam[SP].fi)); + Isf = Sign(U1) * MotorParam[SP].Isat; + // writepaslog("Isf ", FloatToStr(Isf)); + Delta = square(Isf * Rz + Mn * MotorParam[SP].fi * n - U1) + 4.0 * U1 * Isf * Rz; // 105 * 1.67 + Mn * 140.9 * 20.532 - U1 + // DeltaQ = Isf * Rz + Mn * MotorParam[SP].fi * n - U1 + 4 * U1 * Isf * Rz; + // writepaslog("Delta ", FloatToStr(Delta)); + // writepaslog("DeltaQ ", FloatToStr(DeltaQ)); + // writepaslog("U ", FloatToStr(U)); + if (Mains) + { + if (U > 0) + MotorCurrent = (U1 - Isf * Rz - Mn * MotorParam[SP].fi * n + std::sqrt(Delta)) / (2.0 * Rz); + else + MotorCurrent = (U1 - Isf * Rz - Mn * MotorParam[SP].fi * n - std::sqrt(Delta)) / (2.0 * Rz); + } + else + MotorCurrent = 0; + } // else DBF - } // 255 - else - MotorCurrent = 0; - } - // writepaslog("MotorCurrent ", FloatToStr(MotorCurrent)); + } // 255 + else + MotorCurrent = 0; + } + // writepaslog("MotorCurrent ", FloatToStr(MotorCurrent)); if ((DynamicBrakeType == dbrake_switch) && ((BrakePress > 2.0) || (PipePress < 3.6))) { @@ -428,10 +437,10 @@ double TMoverParameters::Current(double n, double U) else Im = MotorCurrent; - EnginePower = abs(Itot) * (1 + RList[MainCtrlActualPos].Mn) * abs(U) / 1000.0; + EnginePower = abs(Itot) * (1 + RList[MainCtrlActualPos].Mn) * abs(U) / 1000.0; - // awarie - MotorCurrent = abs(Im); // zmienna pomocnicza + // awarie + MotorCurrent = abs(Im); // zmienna pomocnicza if (MotorCurrent > 0) { @@ -442,581 +451,573 @@ double TMoverParameters::Current(double n, double U) if (FuzzyLogic(MotorCurrent, (double)ImaxLo / 10.0, p_elengproblem)) if (MainSwitch(false)) EventFlag = true; /*uszkodzony silnik (uplywy)*/ - if ((FuzzyLogic(abs(Im), Imax * 2, p_elengproblem) || - FuzzyLogic(abs(n), nmax * 1.11, p_elengproblem))) + if ((FuzzyLogic(abs(Im), Imax * 2, p_elengproblem) || FuzzyLogic(abs(n), nmax * 1.11, p_elengproblem))) /* or FuzzyLogic(Abs(U/Mn),2*NominalVoltage,1)) then */ /*poprawic potem*/ if ((SetFlag(DamageFlag, dtrain_engine))) EventFlag = true; /*! dorobic grzanie oporow rozruchowych i silnika*/ } - return Im; + return Im; } // ************************************************************************************************* // główny konstruktor // ************************************************************************************************* -TMoverParameters::TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab) : -TypeName( TypeNameInit ), -Name( NameInit ), -CabOccupied( Cab ) +TMoverParameters::TMoverParameters(double VelInitial, std::string TypeNameInit, std::string NameInit, int Cab) : TypeName(TypeNameInit), Name(NameInit), CabOccupied(Cab) { - WriteLog( - "------------------------------------------------------"); - WriteLog("init default physic values for " + NameInit + ", [" + TypeNameInit + "]"); - Dim = TDimension(); + WriteLog("------------------------------------------------------"); + WriteLog("init default physic values for " + NameInit + ", [" + TypeNameInit + "]"); + Dim = TDimension(); - // BrakeLevelSet(-2); //Pascal ustawia na 0, przestawimy na odcięcie (CHK jest jeszcze nie wczytane!) - iLights[ 0 ] = 0; - iLights[ 1 ] = 0; //światła zgaszone + // BrakeLevelSet(-2); //Pascal ustawia na 0, przestawimy na odcięcie (CHK jest jeszcze nie wczytane!) + iLights[0] = 0; + iLights[1] = 0; // światła zgaszone - // inicjalizacja stalych - for (int b = 0; b < ResArraySize + 1; ++b) - { - RList[b] = TScheme(); - } - RlistSize = 0; - for(int b = 0; b < MotorParametersArraySize + 1; ++b) { - MotorParam[ b ] = TMotorParameters(); - } + // inicjalizacja stalych + for (int b = 0; b < ResArraySize + 1; ++b) + { + RList[b] = TScheme(); + } + RlistSize = 0; + for (int b = 0; b < MotorParametersArraySize + 1; ++b) + { + MotorParam[b] = TMotorParameters(); + } - for (int b = 0; b < 2; ++b) - for (int k = 0; k < 17; ++k) - Lights[b][k] = 0; + for (int b = 0; b < 2; ++b) + for (int k = 0; k < 17; ++k) + Lights[b][k] = 0; for (int b = 0; b < 4; ++b) for (int k = 1; k < 9; ++k) - CompressorList[ b ][ k ] = 0; + CompressorList[b][k] = 0; CompressorList[0][0] = 0.0; CompressorList[1][0] = CompressorList[2][0] = CompressorList[3][0] = 1.0; - for (int b = -1; b <= MainBrakeMaxPos; ++b) - { - BrakePressureTable[b].PipePressureVal = 0.0; - BrakePressureTable[b].BrakePressureVal = 0.0; - BrakePressureTable[b].FlowSpeedVal = 0.0; - } - // with BrakePressureTable[-2] do {pozycja odciecia} - { - BrakePressureTable[-2].PipePressureVal = -1.0; - BrakePressureTable[-2].BrakePressureVal = -1.0; - BrakePressureTable[-2].FlowSpeedVal = 0.0; - } - for( int b = 0; b < 4; ++b ) { - BrakeDelay[ b ] = 0.0; - } + for (int b = -1; b <= MainBrakeMaxPos; ++b) + { + BrakePressureTable[b].PipePressureVal = 0.0; + BrakePressureTable[b].BrakePressureVal = 0.0; + BrakePressureTable[b].FlowSpeedVal = 0.0; + } + // with BrakePressureTable[-2] do {pozycja odciecia} + { + BrakePressureTable[-2].PipePressureVal = -1.0; + BrakePressureTable[-2].BrakePressureVal = -1.0; + BrakePressureTable[-2].FlowSpeedVal = 0.0; + } + for (int b = 0; b < 4; ++b) + { + BrakeDelay[b] = 0.0; + } - for (int b = 0; b < 2; ++b) // Ra: kto tu zrobił "for b:=1 to 2 do" ??? - { - Couplers[b].CouplerType = TCouplerType::NoCoupler; - Couplers[b].SpringKB = 1.0; - Couplers[b].SpringKC = 1.0; - Couplers[b].DmaxB = 0.1; - Couplers[b].FmaxB = 1000.0; - Couplers[b].DmaxC = 0.1; - Couplers[b].FmaxC = 1000.0; - } - for( int b = 0; b < 3; ++b ) { - BrakeCylMult[ b ] = 0.0; - } + for (int b = 0; b < 2; ++b) // Ra: kto tu zrobił "for b:=1 to 2 do" ??? + { + Couplers[b].CouplerType = TCouplerType::NoCoupler; + Couplers[b].SpringKB = 1.0; + Couplers[b].SpringKC = 1.0; + Couplers[b].DmaxB = 0.1; + Couplers[b].FmaxB = 1000.0; + Couplers[b].DmaxC = 0.1; + Couplers[b].FmaxC = 1000.0; + } + for (int b = 0; b < 3; ++b) + { + BrakeCylMult[b] = 0.0; + } - for( int b = 0; b < 26; ++b ) { - eimc[ b ] = 0.0; - } + for (int b = 0; b < 26; ++b) + { + eimc[b] = 0.0; + } eimc[eimc_p_eped] = 1.5; - for (int b = 0; b < 2; ++b) - { - Couplers[b].AllowedFlag = 3; // domyślnie hak i hamulec, inne trzeba włączyć jawnie w FIZ - Couplers[b].CouplingFlag = 0; - Couplers[b].Connected = NULL; - Couplers[b].ConnectedNr = 0; // Ra: to nie ma znaczenia jak nie podłączony - Couplers[b].Render = false; - Couplers[b].CForce = 0.0; - Couplers[b].Dist = 0.0; - Couplers[b].CheckCollision = false; - } + for (int b = 0; b < 2; ++b) + { + Couplers[b].AllowedFlag = 3; // domyślnie hak i hamulec, inne trzeba włączyć jawnie w FIZ + Couplers[b].CouplingFlag = 0; + Couplers[b].Connected = NULL; + Couplers[b].ConnectedNr = 0; // Ra: to nie ma znaczenia jak nie podłączony + Couplers[b].Render = false; + Couplers[b].CForce = 0.0; + Couplers[b].Dist = 0.0; + Couplers[b].CheckCollision = false; + } - for (int b = 0; b < 5; ++b) - { - MaxBrakePress[b] = 0.0; - } + for (int b = 0; b < 5; ++b) + { + MaxBrakePress[b] = 0.0; + } - Vel = abs(VelInitial); - V = VelInitial / 3.6; + Vel = abs(VelInitial); + V = VelInitial / 3.6; - for( int b = 0; b < 21; b++ ) { - eimv[ b ] = 0.0; - } + for (int b = 0; b < 21; b++) + { + eimv[b] = 0.0; + } - RunningShape.Len = 1.0; + RunningShape.Len = 1.0; - RunningTrack.CategoryFlag = CategoryFlag; - RunningTrack.Width = TrackW; - RunningTrack.friction = Steel2Steel_friction; - RunningTrack.QualityFlag = 20; - RunningTrack.DamageFlag = 0; - RunningTrack.Velmax = 100.0; // dla uzytku maszynisty w ai_driver} + RunningTrack.CategoryFlag = CategoryFlag; + RunningTrack.Width = TrackW; + RunningTrack.friction = Steel2Steel_friction; + RunningTrack.QualityFlag = 20; + RunningTrack.DamageFlag = 0; + RunningTrack.Velmax = 100.0; // dla uzytku maszynisty w ai_driver} - RunningTraction.TractionVoltage = 0.0; - RunningTraction.TractionFreq = 0.0; - RunningTraction.TractionMaxCurrent = 0.0; - RunningTraction.TractionResistivity = 1.0; + RunningTraction.TractionVoltage = 0.0; + RunningTraction.TractionFreq = 0.0; + RunningTraction.TractionMaxCurrent = 0.0; + RunningTraction.TractionResistivity = 1.0; }; -double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2, - const TDimension &Dim1, const TDimension &Dim2) +double TMoverParameters::Distance(const TLocation &Loc1, const TLocation &Loc2, const TDimension &Dim1, const TDimension &Dim2) { // zwraca odległość pomiędzy pojazdami (Loc1) i (Loc2) z uwzględnieneim ich długości (kule!) - return hypot(Loc2.X - Loc1.X, Loc1.Y - Loc2.Y) - 0.5 * (Dim2.L + Dim1.L); + return hypot(Loc2.X - Loc1.X, Loc1.Y - Loc2.Y) - 0.5 * (Dim2.L + Dim1.L); }; double TMoverParameters::CouplerDist(TMoverParameters const *Left, TMoverParameters const *Right) { // obliczenie odległości pomiędzy sprzęgami (kula!) - return - Distance( - Left->Loc, Right->Loc, - Left->Dim, Right->Dim); // odległość pomiędzy sprzęgami (kula!) + return Distance(Left->Loc, Right->Loc, Left->Dim, Right->Dim); // odległość pomiędzy sprzęgami (kula!) }; bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Enforce, bool Audible) -{ //łączenie do swojego sprzęgu (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr) - // Ra: zwykle wykonywane dwukrotnie, dla każdego pojazdu oddzielnie - // Ra: trzeba by odróżnić wymóg dociśnięcia od uszkodzenia sprzęgu przy podczepianiu AI do składu +{ // łączenie do swojego sprzęgu (ConnectNo) pojazdu (ConnectTo) stroną (ConnectToNr) + // Ra: zwykle wykonywane dwukrotnie, dla każdego pojazdu oddzielnie + // Ra: trzeba by odróżnić wymóg dociśnięcia od uszkodzenia sprzęgu przy podczepianiu AI do składu - if( ( ConnectTo == nullptr ) - || ( CouplingType == coupling::faux ) ) { - return false; - } - - auto &coupler { Couplers[ ConnectNo ] }; - auto &othercoupler = ConnectTo->Couplers[ ( ConnectToNr != 2 ? ConnectToNr : coupler.ConnectedNr ) ]; - auto const distance { CouplerDist( this, ConnectTo ) - ( coupler.adapter_length + othercoupler.adapter_length ) }; + if ((ConnectTo == nullptr) || (CouplingType == coupling::faux)) + { + return false; + } - auto const couplercheck { - ( Enforce ) - || ( ( distance <= dEpsilon ) - && ( coupler.type() != TCouplerType::NoCoupler ) - && ( coupler.type() == othercoupler.type() ) ) }; + auto &coupler{Couplers[ConnectNo]}; + auto &othercoupler = ConnectTo->Couplers[(ConnectToNr != 2 ? ConnectToNr : coupler.ConnectedNr)]; + auto const distance{CouplerDist(this, ConnectTo) - (coupler.adapter_length + othercoupler.adapter_length)}; - if( false == couplercheck ) { return false; } + auto const couplercheck{(Enforce) || ((distance <= dEpsilon) && (coupler.type() != TCouplerType::NoCoupler) && (coupler.type() == othercoupler.type()))}; - // stykaja sie zderzaki i kompatybilne typy sprzegow, chyba że łączenie na starcie - if( coupler.CouplingFlag == coupling::faux ) { - // jeśli wcześniej nie było połączone, ustalenie z której strony rysować sprzęg - coupler.Render = true; // tego rysować - othercoupler.Render = false; // a tego nie - }; - auto const couplingchange { CouplingType ^ coupler.CouplingFlag }; - coupler.Connected = ConnectTo; - coupler.CouplingFlag = CouplingType; // ustawienie typu sprzęgu - if( ConnectToNr != 2 ) { - coupler.ConnectedNr = ConnectToNr; // 2=nic nie podłączone - } - othercoupler.Connected = this; - othercoupler.CouplingFlag = CouplingType; - othercoupler.ConnectedNr = ConnectNo; + if (false == couplercheck) + { + return false; + } - if( ( true == Audible ) && ( couplingchange != 0 ) ) { - // set sound event flag - int soundflag{ sound::none }; - std::vector> const soundmappings = { - { coupling::coupler, sound::attachcoupler }, - { coupling::brakehose, sound::attachbrakehose }, - { coupling::mainhose, sound::attachmainhose }, - { coupling::control, sound::attachcontrol}, - { coupling::gangway, sound::attachgangway}, - { coupling::heating, sound::attachheating} }; - for( auto const &soundmapping : soundmappings ) { - if( ( couplingchange & soundmapping.first ) != 0 ) { - soundflag |= soundmapping.second; - } - } - SetFlag( coupler.sounds, soundflag ); - } + // stykaja sie zderzaki i kompatybilne typy sprzegow, chyba że łączenie na starcie + if (coupler.CouplingFlag == coupling::faux) + { + // jeśli wcześniej nie było połączone, ustalenie z której strony rysować sprzęg + coupler.Render = true; // tego rysować + othercoupler.Render = false; // a tego nie + }; + auto const couplingchange{CouplingType ^ coupler.CouplingFlag}; + coupler.Connected = ConnectTo; + coupler.CouplingFlag = CouplingType; // ustawienie typu sprzęgu + if (ConnectToNr != 2) + { + coupler.ConnectedNr = ConnectToNr; // 2=nic nie podłączone + } + othercoupler.Connected = this; + othercoupler.CouplingFlag = CouplingType; + othercoupler.ConnectedNr = ConnectNo; - return true; + if ((true == Audible) && (couplingchange != 0)) + { + // set sound event flag + int soundflag{sound::none}; + std::vector> const soundmappings = {{coupling::coupler, sound::attachcoupler}, {coupling::brakehose, sound::attachbrakehose}, + {coupling::mainhose, sound::attachmainhose}, {coupling::control, sound::attachcontrol}, + {coupling::gangway, sound::attachgangway}, {coupling::heating, sound::attachheating}}; + for (auto const &soundmapping : soundmappings) + { + if ((couplingchange & soundmapping.first) != 0) + { + soundflag |= soundmapping.second; + } + } + SetFlag(coupler.sounds, soundflag); + } + + return true; } int TMoverParameters::DettachStatus(int ConnectNo) { // Ra: sprawdzenie, czy odległość jest dobra do rozłączania - // powinny być 3 informacje: =0 sprzęg już rozłączony, <0 da się rozłączyć. >0 nie da się rozłączyć - if (!Couplers[ConnectNo].Connected) - return 0; // nie ma nic, to rozłączanie jest OK - if ((Couplers[ConnectNo].CouplingFlag & ctrain_coupler) == 0) - return -Couplers[ConnectNo].CouplingFlag; // hak nie połączony - rozłączanie jest OK - if (TestFlag(DamageFlag, dtrain_coupling)) - return -Couplers[ConnectNo].CouplingFlag; // hak urwany - rozłączanie jest OK -// CouplerDist(ConnectNo); - if ( (Couplers[ConnectNo].type() != TCouplerType::Screw) || (Neighbours[ConnectNo].distance < 0.01) ) - return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty - return (Neighbours[ConnectNo].distance > 0.2) ? -Couplers[ConnectNo].CouplingFlag : - Couplers[ConnectNo].CouplingFlag; + // powinny być 3 informacje: =0 sprzęg już rozłączony, <0 da się rozłączyć. >0 nie da się rozłączyć + if (!Couplers[ConnectNo].Connected) + return 0; // nie ma nic, to rozłączanie jest OK + if ((Couplers[ConnectNo].CouplingFlag & ctrain_coupler) == 0) + return -Couplers[ConnectNo].CouplingFlag; // hak nie połączony - rozłączanie jest OK + if (TestFlag(DamageFlag, dtrain_coupling)) + return -Couplers[ConnectNo].CouplingFlag; // hak urwany - rozłączanie jest OK + // CouplerDist(ConnectNo); + if ((Couplers[ConnectNo].type() != TCouplerType::Screw) || (Neighbours[ConnectNo].distance < 0.01)) + return -Couplers[ConnectNo].CouplingFlag; // można rozłączać, jeśli dociśnięty + return (Neighbours[ConnectNo].distance > 0.2) ? -Couplers[ConnectNo].CouplingFlag : Couplers[ConnectNo].CouplingFlag; }; bool TMoverParameters::Dettach(int ConnectNo) { // rozlaczanie - auto &coupler { Couplers[ ConnectNo ] }; - auto &othervehicle { coupler.Connected }; - auto &othercoupler { othervehicle->Couplers[ coupler.ConnectedNr ] }; + auto &coupler{Couplers[ConnectNo]}; + auto &othervehicle{coupler.Connected}; + auto &othercoupler{othervehicle->Couplers[coupler.ConnectedNr]}; - if( othervehicle == nullptr ) { return true; } // nie ma nic, to odczepiono + if (othervehicle == nullptr) + { + return true; + } // nie ma nic, to odczepiono - auto couplingchange { coupler.CouplingFlag }; // presume we'll uncouple all active flags - auto const couplingstate { DettachStatus( ConnectNo ) }; // stan sprzęgu - if (couplingstate < 0) { - // gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony) - std::tie( coupler.Connected, coupler.ConnectedNr, coupler.CouplingFlag ) - = std::tie( othercoupler.Connected, othercoupler.ConnectedNr, othercoupler.CouplingFlag ) - = std::make_tuple( nullptr, -1, coupling::faux ); - } - else if (couplingstate > 0) - { // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym nic) - coupler.CouplingFlag &= coupling::coupler; - othercoupler.CouplingFlag &= coupling::coupler; - } - // set sound event flag - couplingchange ^= coupler.CouplingFlag; // remaining bits were removed from coupling - if( couplingchange != 0 ) { - int soundflag { sound::detach }; // HACK: use detach flag to indicate removal of listed coupling - std::vector> const soundmappings = { - { coupling::coupler, sound::attachcoupler }, - { coupling::brakehose, sound::attachbrakehose }, - { coupling::mainhose, sound::attachmainhose }, - { coupling::control, sound::attachcontrol}, - { coupling::gangway, sound::attachgangway}, - { coupling::heating, sound::attachheating} }; - for( auto const &soundmapping : soundmappings ) { - if( ( couplingchange & soundmapping.first ) != 0 ) { - soundflag |= soundmapping.second; - } - } - SetFlag( coupler.sounds, soundflag ); - } + auto couplingchange{coupler.CouplingFlag}; // presume we'll uncouple all active flags + auto const couplingstate{DettachStatus(ConnectNo)}; // stan sprzęgu + if (couplingstate < 0) + { + // gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony) + std::tie(coupler.Connected, coupler.ConnectedNr, coupler.CouplingFlag) = std::tie(othercoupler.Connected, othercoupler.ConnectedNr, othercoupler.CouplingFlag) = + std::make_tuple(nullptr, -1, coupling::faux); + } + else if (couplingstate > 0) + { // odłączamy węże i resztę, pozostaje sprzęg fizyczny, który wymaga dociśnięcia (z wirtualnym nic) + coupler.CouplingFlag &= coupling::coupler; + othercoupler.CouplingFlag &= coupling::coupler; + } + // set sound event flag + couplingchange ^= coupler.CouplingFlag; // remaining bits were removed from coupling + if (couplingchange != 0) + { + int soundflag{sound::detach}; // HACK: use detach flag to indicate removal of listed coupling + std::vector> const soundmappings = {{coupling::coupler, sound::attachcoupler}, {coupling::brakehose, sound::attachbrakehose}, + {coupling::mainhose, sound::attachmainhose}, {coupling::control, sound::attachcontrol}, + {coupling::gangway, sound::attachgangway}, {coupling::heating, sound::attachheating}}; + for (auto const &soundmapping : soundmappings) + { + if ((couplingchange & soundmapping.first) != 0) + { + soundflag |= soundmapping.second; + } + } + SetFlag(coupler.sounds, soundflag); + } - return ( couplingstate < 0 ); + return (couplingstate < 0); }; bool TMoverParameters::DirectionForward() { - if( false == EIMDirectionChangeAllow() ) { return false; } + if (false == EIMDirectionChangeAllow()) + { + return false; + } - if ((MainCtrlPosNo > 0) - && (DirActive < 1) - && ( (CabActive != 0) || ( (InactiveCabFlag & activation::neutraldirection) == 0) ) ) - { - ++DirActive; - DirAbsolute = DirActive * CabActive; - SendCtrlToNext("Direction", DirActive, CabActive); - return true; - } - else if ((DirActive == 1) && (IsMainCtrlNoPowerPos()) && (TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor)) - return MinCurrentSwitch(true); //"wysoki rozruch" EN57 - return false; + if ((MainCtrlPosNo > 0) && (DirActive < 1) && ((CabActive != 0) || ((InactiveCabFlag & activation::neutraldirection) == 0))) + { + ++DirActive; + DirAbsolute = DirActive * CabActive; + SendCtrlToNext("Direction", DirActive, CabActive); + return true; + } + else if ((DirActive == 1) && (IsMainCtrlNoPowerPos()) && (TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor)) + return MinCurrentSwitch(true); //"wysoki rozruch" EN57 + return false; }; // Nastawianie hamulców void TMoverParameters::BrakeLevelSet(double b) { // ustawienie pozycji hamulca na wartość (b) w zakresie od -2 do BrakeCtrlPosNo - // jedyny dopuszczalny sposób przestawienia hamulca zasadniczego - if (fBrakeCtrlPos == b) - return; // nie przeliczać, jak nie ma zmiany - fBrakeCtrlPos = b; - if (fBrakeCtrlPos < Handle->GetPos(bh_MIN)) - fBrakeCtrlPos = Handle->GetPos(bh_MIN); // odcięcie - else if (fBrakeCtrlPos > Handle->GetPos(bh_MAX)) - fBrakeCtrlPos = Handle->GetPos(bh_MAX); - // TODO: verify whether BrakeCtrlPosR and fBrakeCtrlPos can be rolled into single variable - BrakeCtrlPosR = fBrakeCtrlPos; - int x = static_cast(std::floor(fBrakeCtrlPos)); // jeśli odwołujemy się do BrakeCtrlPos w pośrednich, to musi być - // obcięte a nie zaokrągone - while ((x > BrakeCtrlPos) && (BrakeCtrlPos < BrakeCtrlPosNo)) // jeśli zwiększyło się o 1 - if (!IncBrakeLevelOld()) // T_MoverParameters:: - break; // wyjście awaryjne - while ((x < BrakeCtrlPos) && (BrakeCtrlPos >= -1)) // jeśli zmniejszyło się o 1 - if (!DecBrakeLevelOld()) // T_MoverParameters:: - break; - BrakePressureActual = BrakePressureTable[BrakeCtrlPos]; // skopiowanie pozycji - /* - //youBy: obawiam sie, ze tutaj to nie dziala :P - //Ra 2014-03: było tak zrobione, że działało - po każdej zmianie pozycji była wywoływana ta - funkcja - // if (BrakeSystem==Pneumatic?BrakeSubsystem==Oerlikon:false) //tylko Oerlikon akceptuje ułamki - if(false) - if (fBrakeCtrlPos>0.0) - {//wartości pośrednie wyliczamy tylko dla hamowania - double u=fBrakeCtrlPos-double(x); //ułamek ponad wartość całkowitą - if (u>0.0) - {//wyliczamy wartości ważone - BrakePressureActual.PipePressureVal+=-u*BrakePressureActual.PipePressureVal+u*BrakePressureTable[BrakeCtrlPos+1+2].PipePressureVal; - //BrakePressureActual.BrakePressureVal+=-u*BrakePressureActual.BrakePressureVal+u*BrakePressureTable[BrakeCtrlPos+1].BrakePressureVal; - //to chyba nie będzie tak działać, zwłaszcza w EN57 - BrakePressureActual.FlowSpeedVal+=-u*BrakePressureActual.FlowSpeedVal+u*BrakePressureTable[BrakeCtrlPos+1+2].FlowSpeedVal; - } - } - */ + // jedyny dopuszczalny sposób przestawienia hamulca zasadniczego + if (fBrakeCtrlPos == b) + return; // nie przeliczać, jak nie ma zmiany + fBrakeCtrlPos = b; + if (fBrakeCtrlPos < Handle->GetPos(bh_MIN)) + fBrakeCtrlPos = Handle->GetPos(bh_MIN); // odcięcie + else if (fBrakeCtrlPos > Handle->GetPos(bh_MAX)) + fBrakeCtrlPos = Handle->GetPos(bh_MAX); + // TODO: verify whether BrakeCtrlPosR and fBrakeCtrlPos can be rolled into single variable + BrakeCtrlPosR = fBrakeCtrlPos; + int x = static_cast(std::floor(fBrakeCtrlPos)); // jeśli odwołujemy się do BrakeCtrlPos w pośrednich, to musi być + // obcięte a nie zaokrągone + while ((x > BrakeCtrlPos) && (BrakeCtrlPos < BrakeCtrlPosNo)) // jeśli zwiększyło się o 1 + if (!IncBrakeLevelOld()) // T_MoverParameters:: + break; // wyjście awaryjne + while ((x < BrakeCtrlPos) && (BrakeCtrlPos >= -1)) // jeśli zmniejszyło się o 1 + if (!DecBrakeLevelOld()) // T_MoverParameters:: + break; + BrakePressureActual = BrakePressureTable[BrakeCtrlPos]; // skopiowanie pozycji + /* + //youBy: obawiam sie, ze tutaj to nie dziala :P + //Ra 2014-03: było tak zrobione, że działało - po każdej zmianie pozycji była wywoływana ta + funkcja + // if (BrakeSystem==Pneumatic?BrakeSubsystem==Oerlikon:false) //tylko Oerlikon akceptuje ułamki + if(false) + if (fBrakeCtrlPos>0.0) + {//wartości pośrednie wyliczamy tylko dla hamowania + double u=fBrakeCtrlPos-double(x); //ułamek ponad wartość całkowitą + if (u>0.0) + {//wyliczamy wartości ważone + BrakePressureActual.PipePressureVal+=-u*BrakePressureActual.PipePressureVal+u*BrakePressureTable[BrakeCtrlPos+1+2].PipePressureVal; + //BrakePressureActual.BrakePressureVal+=-u*BrakePressureActual.BrakePressureVal+u*BrakePressureTable[BrakeCtrlPos+1].BrakePressureVal; + //to chyba nie będzie tak działać, zwłaszcza w EN57 + BrakePressureActual.FlowSpeedVal+=-u*BrakePressureActual.FlowSpeedVal+u*BrakePressureTable[BrakeCtrlPos+1+2].FlowSpeedVal; + } + } + */ }; bool TMoverParameters::BrakeLevelAdd(double b) { // dodanie wartości (b) do pozycji hamulca (w tym ujemnej) - // zwraca false, gdy po dodaniu było by poza zakresem - BrakeLevelSet(fBrakeCtrlPos + b); - return b > 0.0 ? (fBrakeCtrlPos < BrakeCtrlPosNo) : - (BrakeCtrlPos > -1.0); // true, jeśli można kontynuować + // zwraca false, gdy po dodaniu było by poza zakresem + BrakeLevelSet(fBrakeCtrlPos + b); + return b > 0.0 ? (fBrakeCtrlPos < BrakeCtrlPosNo) : (BrakeCtrlPos > -1.0); // true, jeśli można kontynuować }; bool TMoverParameters::IncBrakeLevel() { // nowa wersja na użytek AI, false gdy osiągnięto pozycję BrakeCtrlPosNo - return BrakeLevelAdd(1.0); + return BrakeLevelAdd(1.0); }; bool TMoverParameters::DecBrakeLevel() { - return BrakeLevelAdd(-1.0); + return BrakeLevelAdd(-1.0); }; // nowa wersja na użytek AI, false gdy osiągnięto pozycję -1 bool TMoverParameters::ChangeCab(int direction) { // zmiana kabiny i resetowanie ustawien - if (std::abs(CabOccupied + direction) < 2) - { - CabOccupied = CabOccupied + direction; - if( ( BrakeCtrlPosNo > 0 ) - && ( ( BrakeSystem == TBrakeSystem::Pneumatic ) - || ( BrakeSystem == TBrakeSystem::ElectroPneumatic ) ) ) { - BrakeLevelSet(Handle->GetPos(bh_NP)); - LimPipePress = PipePress; - ActFlowSpeed = 0; - } - else - BrakeLevelSet(Handle->GetPos(bh_NP)); - MainCtrlPos = MainCtrlNoPowerPos(); - ScndCtrlPos = 0; - return true; - } - return false; + if (std::abs(CabOccupied + direction) < 2) + { + CabOccupied = CabOccupied + direction; + if ((BrakeCtrlPosNo > 0) && ((BrakeSystem == TBrakeSystem::Pneumatic) || (BrakeSystem == TBrakeSystem::ElectroPneumatic))) + { + BrakeLevelSet(Handle->GetPos(bh_NP)); + LimPipePress = PipePress; + ActFlowSpeed = 0; + } + else + BrakeLevelSet(Handle->GetPos(bh_NP)); + MainCtrlPos = MainCtrlNoPowerPos(); + ScndCtrlPos = 0; + return true; + } + return false; }; // rozruch wysoki (true) albo niski (false) -bool -TMoverParameters::CurrentSwitch(bool const State) { +bool TMoverParameters::CurrentSwitch(bool const State) +{ - if( MaxCurrentSwitch( State ) ) { - if( TrainType != dt_EZT ) { - ( MinCurrentSwitch( State ) ); - } - return true; - } - // TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that - // dla 2Ls150 - if( ( EngineType == TEngineType::DieselEngine ) - && ( true == ShuntModeAllow ) - && ( DirActive == 0 ) ) { - // przed ustawieniem kierunku - ShuntMode = State; - return true; - } - // for SM42/SP42 - if( ( EngineType == TEngineType::DieselElectric ) - && ( true == ShuntModeAllow ) - && ( IsMainCtrlNoPowerPos() ) ) { - ShuntMode = State; - return true; - } + if (MaxCurrentSwitch(State)) + { + if (TrainType != dt_EZT) + { + (MinCurrentSwitch(State)); + } + return true; + } + // TBD, TODO: split off shunt mode toggle into a separate command? It doesn't make much sense to have these two together like that + // dla 2Ls150 + if ((EngineType == TEngineType::DieselEngine) && (true == ShuntModeAllow) && (DirActive == 0)) + { + // przed ustawieniem kierunku + ShuntMode = State; + return true; + } + // for SM42/SP42 + if ((EngineType == TEngineType::DieselElectric) && (true == ShuntModeAllow) && (IsMainCtrlNoPowerPos())) + { + ShuntMode = State; + return true; + } - return false; + return false; }; -bool -TMoverParameters::IsMotorOverloadRelayHighThresholdOn() const { +bool TMoverParameters::IsMotorOverloadRelayHighThresholdOn() const +{ - return ( ( ImaxHi > ImaxLo ) && ( Imax > ImaxLo ) ); + return ((ImaxHi > ImaxLo) && (Imax > ImaxLo)); } - // KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak -void TMoverParameters::UpdatePantVolume(double dt) { - // check the pantograph compressor while at it - // TODO: move the check to a separate method - // automatic start if the pressure is too low - PantCompFlag |= ( - ( PantPress < 4.2 ) - && ( true == ( Pantographs[ end::front ].is_active | Pantographs[ end::rear ].is_active ) ) // TODO: any_pantograph_is_active method - && ( ( PantographCompressorStart == start_t::automatic ) - || ( PantographCompressorStart == start_t::manualwithautofallback ) ) ); +// KURS90 - sprężarka pantografów; Ra 2014-07: teraz jest to zbiornik rozrządu, chociaż to jeszcze nie tak +void TMoverParameters::UpdatePantVolume(double dt) +{ + // check the pantograph compressor while at it + // TODO: move the check to a separate method + // automatic start if the pressure is too low + PantCompFlag |= ((PantPress < 4.2) && (true == (Pantographs[end::front].is_active | Pantographs[end::rear].is_active)) // TODO: any_pantograph_is_active method + && ((PantographCompressorStart == start_t::automatic) || (PantographCompressorStart == start_t::manualwithautofallback))); - auto const lowvoltagepower { Power24vIsAvailable || Power110vIsAvailable }; - PantCompFlag &= lowvoltagepower; + auto const lowvoltagepower{Power24vIsAvailable || Power110vIsAvailable}; + PantCompFlag &= lowvoltagepower; - if( ( EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) // tylko jeśli pantografujący - && ( EnginePowerSource.CollectorParameters.CollectorsNo > 0 ) ) - { - // Ra 2014-07: zasadniczo, to istnieje zbiornik rozrządu i zbiornik pantografów - na razie mamy razem - // 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 (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 - // Ra 2013-12: Niebugocław mówi, że w EZT nie ma potrzeby odcinać kurkiem - PantPress = ScndPipePress; - // ograniczenie ciśnienia do MaxPress (tylko w pantografach!) - PantPress = clamp( ScndPipePress, 0.0, EnginePowerSource.CollectorParameters.MaxPress ); - PantVolume = (PantPress + 1.0) * 0.1; // objętość, na wypadek odcięcia kurkiem - } - else - { // zbiornik główny odcięty, można pompować pantografy - if( PantCompFlag ) { - // włączona mała sprężarka - PantVolume += - dt - // Ra 2013-12: Niebugocław mówi, że w EZT nabija 1.5 raz wolniej niż jak było 0.005 - * ( TrainType == dt_EZT ? 0.003 : 0.005 ) / std::max( 1.0, PantPress ) - * ( 0.45 - ( ( 0.1 / PantVolume / 10 ) - 0.1 ) ) / 0.45; - } - PantPress = clamp( ( 10.0 * PantVolume ) - 1.0, 0.0, EnginePowerSource.CollectorParameters.MaxPress ); // tu by się przydała objętość zbiornika - } - if( !PantCompFlag && ( PantVolume > 0.1 ) ) - PantVolume -= dt * 0.0003 * std::max( 1.0, PantPress * 0.5 ); // nieszczelności: 0.0003=0.3l/s + if ((EnginePowerSource.SourceType == TPowerSource::CurrentCollector) // tylko jeśli pantografujący + && (EnginePowerSource.CollectorParameters.CollectorsNo > 0)) + { + // Ra 2014-07: zasadniczo, to istnieje zbiornik rozrządu i zbiornik pantografów - na razie mamy razem + // 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 (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 + // Ra 2013-12: Niebugocław mówi, że w EZT nie ma potrzeby odcinać kurkiem + PantPress = ScndPipePress; + // ograniczenie ciśnienia do MaxPress (tylko w pantografach!) + PantPress = clamp(ScndPipePress, 0.0, EnginePowerSource.CollectorParameters.MaxPress); + PantVolume = (PantPress + 1.0) * 0.1; // objętość, na wypadek odcięcia kurkiem + } + else + { // zbiornik główny odcięty, można pompować pantografy + if (PantCompFlag) + { + // włączona mała sprężarka + PantVolume += dt + // Ra 2013-12: Niebugocław mówi, że w EZT nabija 1.5 raz wolniej niż jak było 0.005 + * (TrainType == dt_EZT ? 0.003 : 0.005) / std::max(1.0, PantPress) * (0.45 - ((0.1 / PantVolume / 10) - 0.1)) / 0.45; + } + PantPress = clamp((10.0 * PantVolume) - 1.0, 0.0, EnginePowerSource.CollectorParameters.MaxPress); // tu by się przydała objętość zbiornika + } + if (!PantCompFlag && (PantVolume > 0.1)) + PantVolume -= dt * 0.0003 * std::max(1.0, PantPress * 0.5); // nieszczelności: 0.0003=0.3l/s - if( PantPress < EnginePowerSource.CollectorParameters.MinPress ) { - // 3.5 wg http://www.transportszynowy.pl/eu06-07pneumat.php - if( true == PantPressSwitchActive ) { - // opuszczenie pantografów przy niskim ciśnieniu - if( TrainType != dt_EZT ) { - // pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage - if( GetTrainsetHighVoltage() < EnginePowerSource.CollectorParameters.MinV ) { - // TODO: check whether line breaker should be open EMU-wide - MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ); - } - } - else { - // specialized variant for EMU -- pwr system disables converter and heating, - // and prevents their activation until pressure switch is set again - PantPressLockActive = true; - // TODO: separate 'heating allowed' from actual heating flag, so we can disable it here without messing up heating toggle - ConverterSwitch( false, range_t::unit ); - } - // mark the pressure switch as spent - PantPressSwitchActive = false; - } - } - else { - if( PantPress >= 4.6 ) { - // NOTE: we require active low power source to prime the pressure switch - // this is a work-around for potential isssues caused by the switch activating on otherwise idle vehicles, but should check whether it's accurate - if( ( true == Power24vIsAvailable ) - || ( true == Power110vIsAvailable ) ) { - // prime the pressure switch - PantPressSwitchActive = true; - // turn off the subsystems lock - PantPressLockActive = false; - } + if (PantPress < EnginePowerSource.CollectorParameters.MinPress) + { + // 3.5 wg http://www.transportszynowy.pl/eu06-07pneumat.php + if (true == PantPressSwitchActive) + { + // opuszczenie pantografów przy niskim ciśnieniu + if (TrainType != dt_EZT) + { + // pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage + if (GetTrainsetHighVoltage() < EnginePowerSource.CollectorParameters.MinV) + { + // TODO: check whether line breaker should be open EMU-wide + MainSwitch(false, (TrainType == dt_EZT ? range_t::unit : range_t::local)); + } + } + else + { + // specialized variant for EMU -- pwr system disables converter and heating, + // and prevents their activation until pressure switch is set again + PantPressLockActive = true; + // TODO: separate 'heating allowed' from actual heating flag, so we can disable it here without messing up heating toggle + ConverterSwitch(false, range_t::unit); + } + // mark the pressure switch as spent + PantPressSwitchActive = false; + } + } + else + { + if (PantPress >= 4.6) + { + // NOTE: we require active low power source to prime the pressure switch + // this is a work-around for potential isssues caused by the switch activating on otherwise idle vehicles, but should check whether it's accurate + if ((true == Power24vIsAvailable) || (true == Power110vIsAvailable)) + { + // prime the pressure switch + PantPressSwitchActive = true; + // turn off the subsystems lock + PantPressLockActive = false; + } - if( PantPress >= 4.8 ) { - // Winger - automatyczne wylaczanie malej sprezarki - // TODO: governor lock, disables usage until pressure drop below 3.8 (should really make compressor object we could reuse) - PantCompFlag = false; - } - } - } - } - else - { // a tu coś dla SM42 i SM31, aby pokazywać na manometrze - PantPress = CntrlPipePress; - } + if (PantPress >= 4.8) + { + // Winger - automatyczne wylaczanie malej sprezarki + // TODO: governor lock, disables usage until pressure drop below 3.8 (should really make compressor object we could reuse) + PantCompFlag = false; + } + } + } + } + else + { // a tu coś dla SM42 i SM31, aby pokazywać na manometrze + PantPress = CntrlPipePress; + } }; void TMoverParameters::UpdateBatteryVoltage(double dt) { // przeliczenie obciążenia baterii - double sn1 = 0.0, - sn2 = 0.0, - sn3 = 0.0, - sn4 = 0.0, - sn5 = 0.0; // Ra: zrobić z tego amperomierz NN - if( ( BatteryVoltage > 0 ) - && ( EngineType != TEngineType::DieselEngine ) - && ( EngineType != TEngineType::WheelsDriven ) - && ( NominalBatteryVoltage > 0 ) ) { + double sn1 = 0.0, sn2 = 0.0, sn3 = 0.0, sn4 = 0.0, + sn5 = 0.0; // Ra: zrobić z tego amperomierz NN + if ((BatteryVoltage > 0) && (EngineType != TEngineType::DieselEngine) && (EngineType != TEngineType::WheelsDriven) && (NominalBatteryVoltage > 0)) + { - // HACK: allow to draw power also from adjacent converter, applicable for EMUs - // TODO: expand power cables system to include low voltage power transfers - // HACK: emulate low voltage generator powered directly by the diesel engine - auto const converteractive{ - ( Power110vIsAvailable ) - || ( ( EngineType == TEngineType::DieselElectric ) && ( true == Mains ) ) - || ( ( EngineType == TEngineType::DieselEngine ) && ( true == Mains ) ) }; + // HACK: allow to draw power also from adjacent converter, applicable for EMUs + // TODO: expand power cables system to include low voltage power transfers + // HACK: emulate low voltage generator powered directly by the diesel engine + auto const converteractive{(Power110vIsAvailable) || ((EngineType == TEngineType::DieselElectric) && (true == Mains)) || ((EngineType == TEngineType::DieselEngine) && (true == Mains))}; - if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery) - { // 110V - if (!converteractive) - sn1 = (dt * 2.0); // szybki spadek do ok 90V - else - sn1 = 0; - if (converteractive) - sn2 = -(dt * 2.0); // szybki wzrost do 110V - else - sn2 = 0; - if (Mains) - sn3 = (dt * 0.05); - else - sn3 = 0; - if (iLights[0] & 63) // 64=blachy, nie ciągną prądu //rozpisać na poszczególne żarówki... - sn4 = dt * 0.003; - else - sn4 = 0; - if (iLights[1] & 63) // 64=blachy, nie ciągną prądu - sn5 = dt * 0.001; - else - sn5 = 0; - }; - if ((NominalBatteryVoltage / BatteryVoltage >= 1.22) && Battery) - { // 90V - if (PantCompFlag) - sn1 = (dt * 0.0046); - else - sn1 = 0; - if (converteractive) - sn2 = -(dt * 50); // szybki wzrost do 110V - else - sn2 = 0; - if (Mains) - sn3 = (dt * 0.001); - else - sn3 = 0; - if (iLights[0] & 63) // 64=blachy, nie ciągną prądu - sn4 = (dt * 0.0030); - else - sn4 = 0; - if (iLights[1] & 63) // 64=blachy, nie ciągną prądu - sn5 = (dt * 0.0010); - else - sn5 = 0; - }; - if (!Battery) - { - if (NominalBatteryVoltage / BatteryVoltage < 1.22) - sn1 = dt * 50; - else - sn1 = 0; - sn2 = dt * 0.000001; - sn3 = dt * 0.000001; - sn4 = dt * 0.000001; - sn5 = dt * 0.000001; // bardzo powolny spadek przy wyłączonych bateriach - }; - BatteryVoltage -= (sn1 + sn2 + sn3 + sn4 + sn5); - if (NominalBatteryVoltage / BatteryVoltage > 1.57) - if (MainSwitch(false) && (EngineType != TEngineType::DieselEngine) && (EngineType != TEngineType::WheelsDriven)) - EventFlag = true; // wywalanie szybkiego z powodu zbyt niskiego napiecia - if (BatteryVoltage > NominalBatteryVoltage) - BatteryVoltage = NominalBatteryVoltage; // wstrzymanie ładowania pow. 110V - if (BatteryVoltage < 0.01) - BatteryVoltage = 0.01; - } - else { - // TODO: check and implement proper way to handle this for diesel engines - BatteryVoltage = NominalBatteryVoltage; - } + if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery) + { // 110V + if (!converteractive) + sn1 = (dt * 2.0); // szybki spadek do ok 90V + else + sn1 = 0; + if (converteractive) + sn2 = -(dt * 2.0); // szybki wzrost do 110V + else + sn2 = 0; + if (Mains) + sn3 = (dt * 0.05); + else + sn3 = 0; + if (iLights[0] & 63) // 64=blachy, nie ciągną prądu //rozpisać na poszczególne żarówki... + sn4 = dt * 0.003; + else + sn4 = 0; + if (iLights[1] & 63) // 64=blachy, nie ciągną prądu + sn5 = dt * 0.001; + else + sn5 = 0; + }; + if ((NominalBatteryVoltage / BatteryVoltage >= 1.22) && Battery) + { // 90V + if (PantCompFlag) + sn1 = (dt * 0.0046); + else + sn1 = 0; + if (converteractive) + sn2 = -(dt * 50); // szybki wzrost do 110V + else + sn2 = 0; + if (Mains) + sn3 = (dt * 0.001); + else + sn3 = 0; + if (iLights[0] & 63) // 64=blachy, nie ciągną prądu + sn4 = (dt * 0.0030); + else + sn4 = 0; + if (iLights[1] & 63) // 64=blachy, nie ciągną prądu + sn5 = (dt * 0.0010); + else + sn5 = 0; + }; + if (!Battery) + { + if (NominalBatteryVoltage / BatteryVoltage < 1.22) + sn1 = dt * 50; + else + sn1 = 0; + sn2 = dt * 0.000001; + sn3 = dt * 0.000001; + sn4 = dt * 0.000001; + sn5 = dt * 0.000001; // bardzo powolny spadek przy wyłączonych bateriach + }; + BatteryVoltage -= (sn1 + sn2 + sn3 + sn4 + sn5); + if (NominalBatteryVoltage / BatteryVoltage > 1.57) + if (MainSwitch(false) && (EngineType != TEngineType::DieselEngine) && (EngineType != TEngineType::WheelsDriven)) + EventFlag = true; // wywalanie szybkiego z powodu zbyt niskiego napiecia + if (BatteryVoltage > NominalBatteryVoltage) + BatteryVoltage = NominalBatteryVoltage; // wstrzymanie ładowania pow. 110V + if (BatteryVoltage < 0.01) + BatteryVoltage = 0.01; + } + else + { + // TODO: check and implement proper way to handle this for diesel engines + BatteryVoltage = NominalBatteryVoltage; + } }; /* Ukrotnienie EN57: @@ -1064,12 +1065,12 @@ ZN //masa // ***************************************************************************** double TMoverParameters::LocalBrakeRatio(void) { - double LBR; - if (BrakeHandle == TBrakeHandle::MHZ_EN57) - if ((BrakeOpModeFlag >= bom_EP)) - LBR = Handle->GetEP(BrakeCtrlPosR); - else - LBR = 0; + double LBR; + if (BrakeHandle == TBrakeHandle::MHZ_EN57) + if ((BrakeOpModeFlag >= bom_EP)) + LBR = Handle->GetEP(BrakeCtrlPosR); + else + LBR = 0; else { if (LocalBrakePosNo > 0) @@ -1077,9 +1078,9 @@ double TMoverParameters::LocalBrakeRatio(void) else LBR = 0; } - // if (TestFlag(BrakeStatus, b_antislip)) - // LBR = Max0R(LBR, PipeRatio) + 0.4; - return LBR; + // if (TestFlag(BrakeStatus, b_antislip)) + // LBR = Max0R(LBR, PipeRatio) + 0.4; + return LBR; } // ***************************************************************************** @@ -1088,13 +1089,13 @@ double TMoverParameters::LocalBrakeRatio(void) // ***************************************************************************** double TMoverParameters::ManualBrakeRatio(void) { - double MBR; + double MBR; - if (ManualBrakePosNo > 0) - MBR = (double)ManualBrakePos / ManualBrakePosNo; - else - MBR = 0; - return MBR; + if (ManualBrakePosNo > 0) + MBR = (double)ManualBrakePos / ManualBrakePosNo; + else + MBR = 0; + return MBR; } // ***************************************************************************** @@ -1103,10 +1104,10 @@ double TMoverParameters::ManualBrakeRatio(void) // ***************************************************************************** double TMoverParameters::BrakeVP(void) const { - if (BrakeVVolume > 0) - return Volume / (10.0 * BrakeVVolume); - else - return 0; + if (BrakeVVolume > 0) + return Volume / (10.0 * BrakeVVolume); + else + return 0; } // ***************************************************************************** @@ -1115,13 +1116,13 @@ double TMoverParameters::BrakeVP(void) const // ***************************************************************************** double TMoverParameters::RealPipeRatio(void) { - double rpp; + double rpp; - if (DeltaPipePress > 0) - rpp = (CntrlPipePress - PipePress) / (DeltaPipePress); - else - rpp = 0; - return rpp; + if (DeltaPipePress > 0) + rpp = (CntrlPipePress - PipePress) / (DeltaPipePress); + else + rpp = 0; + return rpp; } // ***************************************************************************** @@ -1130,57 +1131,51 @@ double TMoverParameters::RealPipeRatio(void) // ***************************************************************************** double TMoverParameters::PipeRatio(void) { - double pr; + double pr; - if (DeltaPipePress > 0) - if (false) // SPKS!! no to jak nie wchodzimy to po co branch? - { - if ((3.0 * PipePress) > (HighPipePress + LowPipePress + LowPipePress)) - pr = (HighPipePress - Min0R(HighPipePress, PipePress)) / - (DeltaPipePress * 4.0 / 3.0); - else - pr = (HighPipePress - 1.0 / 3.0 * DeltaPipePress - Max0R(LowPipePress, PipePress)) / - (DeltaPipePress * 2.0 / 3.0); - //if (not TestFlag(BrakeStatus, b_Ractive)) - // and(BrakeMethod and 1 = 0) and TestFlag(BrakeDelays, bdelay_R) and (Power < 1) and - // (BrakeCtrlPos < 1) then pr : = Min0R(0.5, pr); - //if (Compressor > 0.5) - // then pr : = pr * 1.333; // dziwny rapid wywalamy - } - else - pr = (HighPipePress - Max0R(LowPipePress, Min0R(HighPipePress, PipePress))) / - DeltaPipePress; - else - pr = 0; - return pr; + if (DeltaPipePress > 0) + if (false) // SPKS!! no to jak nie wchodzimy to po co branch? + { + if ((3.0 * PipePress) > (HighPipePress + LowPipePress + LowPipePress)) + pr = (HighPipePress - Min0R(HighPipePress, PipePress)) / (DeltaPipePress * 4.0 / 3.0); + else + pr = (HighPipePress - 1.0 / 3.0 * DeltaPipePress - Max0R(LowPipePress, PipePress)) / (DeltaPipePress * 2.0 / 3.0); + // if (not TestFlag(BrakeStatus, b_Ractive)) + // and(BrakeMethod and 1 = 0) and TestFlag(BrakeDelays, bdelay_R) and (Power < 1) and + // (BrakeCtrlPos < 1) then pr : = Min0R(0.5, pr); + // if (Compressor > 0.5) + // then pr : = pr * 1.333; // dziwny rapid wywalamy + } + else + pr = (HighPipePress - Max0R(LowPipePress, Min0R(HighPipePress, PipePress))) / DeltaPipePress; + else + pr = 0; + return pr; } -double -TMoverParameters::EngineRPMRatio() const { +double TMoverParameters::EngineRPMRatio() const +{ - return clamp( ( - EngineType == TEngineType::DieselElectric ? ( ( 60.0 * std::abs( enrot ) ) / DElist[ MainCtrlPosNo ].RPM ) : - EngineType == TEngineType::DieselEngine ? ( std::abs( enrot ) / nmax ) : - 1.0 ), // shouldn't ever get here but, eh - 0.0, 1.0 ); + return clamp((EngineType == TEngineType::DieselElectric ? ((60.0 * std::abs(enrot)) / DElist[MainCtrlPosNo].RPM) : + EngineType == TEngineType::DieselEngine ? (std::abs(enrot) / nmax) : + 1.0), // shouldn't ever get here but, eh + 0.0, 1.0); } -double -TMoverParameters::EngineIdleRPM() const { +double TMoverParameters::EngineIdleRPM() const +{ - return ( - EngineType == TEngineType::DieselEngine ? dizel_nmin * 60 : - EngineType == TEngineType::DieselElectric ? DElist[ MainCtrlNoPowerPos() ].RPM : - std::numeric_limits::max() ); // shouldn't ever get here but, eh + return (EngineType == TEngineType::DieselEngine ? dizel_nmin * 60 : + EngineType == TEngineType::DieselElectric ? DElist[MainCtrlNoPowerPos()].RPM : + std::numeric_limits::max()); // shouldn't ever get here but, eh } -double -TMoverParameters::EngineMaxRPM() const { +double TMoverParameters::EngineMaxRPM() const +{ - return ( - EngineType == TEngineType::DieselEngine ? dizel_nmax * 60 : - EngineType == TEngineType::DieselElectric ? DElist[ MainCtrlPosNo ].RPM : - std::numeric_limits::max() ); // shouldn't ever get here but, eh + return (EngineType == TEngineType::DieselEngine ? dizel_nmax * 60 : + EngineType == TEngineType::DieselElectric ? DElist[MainCtrlPosNo].RPM : + std::numeric_limits::max()); // shouldn't ever get here but, eh } // ************************************************************************************************* @@ -1189,398 +1184,395 @@ TMoverParameters::EngineMaxRPM() const { // ************************************************************************************************* void TMoverParameters::CollisionDetect(int const End, double const dt) { - if( Neighbours[ End ].vehicle == nullptr ) { return; } // shouldn't normally happen but, eh + if (Neighbours[End].vehicle == nullptr) + { + return; + } // shouldn't normally happen but, eh - auto &coupler { Couplers[ End ] }; - auto *othervehicle { Neighbours[ End ].vehicle->MoverParameters }; - auto const otherend { Neighbours[ End ].vehicle_end }; - auto &othercoupler { othervehicle->Couplers[ otherend ] }; + auto &coupler{Couplers[End]}; + auto *othervehicle{Neighbours[End].vehicle->MoverParameters}; + auto const otherend{Neighbours[End].vehicle_end}; + auto &othercoupler{othervehicle->Couplers[otherend]}; - auto velocity { V }; - auto othervehiclevelocity { othervehicle->V }; - // calculate collision force and new velocities for involved vehicles - auto const VirtualCoupling { ( coupler.CouplingFlag == coupling::faux ) }; - auto CCF { 0.0 }; + auto velocity{V}; + auto othervehiclevelocity{othervehicle->V}; + // calculate collision force and new velocities for involved vehicles + auto const VirtualCoupling{(coupler.CouplingFlag == coupling::faux)}; + auto CCF{0.0}; - switch( End ) { - case 0: { - CCF = - ComputeCollision( - velocity, othervehiclevelocity, - TotalMass, othervehicle->TotalMass, - ( coupler.beta + othercoupler.beta ) / 2.0, - VirtualCoupling ) - / ( dt ); - break; // yB: ej ej ej, a po - } - case 1: { - CCF = - ComputeCollision( - othervehiclevelocity, velocity, - othervehicle->TotalMass, TotalMass, - ( coupler.beta + othercoupler.beta ) / 2.0, - VirtualCoupling ) - / ( dt ); - break; - } - default: { - break; - } - } + switch (End) + { + case 0: + { + CCF = ComputeCollision(velocity, othervehiclevelocity, TotalMass, othervehicle->TotalMass, (coupler.beta + othercoupler.beta) / 2.0, VirtualCoupling) / (dt); + break; // yB: ej ej ej, a po + } + case 1: + { + CCF = ComputeCollision(othervehiclevelocity, velocity, othervehicle->TotalMass, TotalMass, (coupler.beta + othercoupler.beta) / 2.0, VirtualCoupling) / (dt); + break; + } + default: + { + break; + } + } - if (Global.crash_damage) { - if( ( -coupler.Dist >= coupler.DmaxB ) - && ( FuzzyLogic( std::abs( CCF ), 5.0 * ( coupler.FmaxC + 1.0 ), p_coupldmg ) ) ) { - // small chance to smash the coupler if it's hit with excessive force - damage_coupler( End ); - } + if (Global.crash_damage) + { + if ((-coupler.Dist >= coupler.DmaxB) && (FuzzyLogic(std::abs(CCF), 5.0 * (coupler.FmaxC + 1.0), p_coupldmg))) + { + // small chance to smash the coupler if it's hit with excessive force + damage_coupler(End); + } - if( ( coupler.CouplingFlag == coupling::faux - || ( true == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) ) { // HACK: limit excessive speed derailment checks to vehicles which aren't part of the same consist - auto const safevelocitylimit { 15.0 }; - auto const velocitydifference { - glm::length( - glm::angleAxis( Rot.Rz, glm::dvec3{ 0, 1, 0 } ) * V - - glm::angleAxis( othervehicle->Rot.Rz, glm::dvec3{ 0, 1, 0 } ) * othervehicle->V ) - * 3.6 }; // m/s -> km/h + if ((coupler.CouplingFlag == coupling::faux || (true == TestFlag(othervehicle->DamageFlag, dtrain_out)))) + { // HACK: limit excessive speed derailment checks to vehicles which aren't part of the same consist + auto const safevelocitylimit{15.0}; + auto const velocitydifference{glm::length(glm::angleAxis(Rot.Rz, glm::dvec3{0, 1, 0}) * V - glm::angleAxis(othervehicle->Rot.Rz, glm::dvec3{0, 1, 0}) * othervehicle->V) * + 3.6}; // m/s -> km/h - if( velocitydifference > safevelocitylimit ) { - // HACK: crude estimation for potential derail, will take place with velocity difference > 15 km/h adjusted for vehicle mass ratio - if( ( false == TestFlag( DamageFlag, dtrain_out ) ) - || ( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) { - WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" ); - } + if (velocitydifference > safevelocitylimit) + { + // HACK: crude estimation for potential derail, will take place with velocity difference > 15 km/h adjusted for vehicle mass ratio + if ((false == TestFlag(DamageFlag, dtrain_out)) || (false == TestFlag(othervehicle->DamageFlag, dtrain_out))) + { + WriteLog("Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string(velocitydifference, 0) + " km/h"); + } - if( velocitydifference > safevelocitylimit * ( TotalMass / othervehicle->TotalMass ) ) { - Derail(COLLISION); - } - if( velocitydifference > safevelocitylimit * ( othervehicle->TotalMass / TotalMass ) ) { - othervehicle->Derail(COLLISION); - } - } - } - } - - // adjust velocity and acceleration of affected vehicles - if( false == TestFlag( DamageFlag, dtrain_out ) ) { - auto const accelerationchange{ ( velocity - V ) / dt }; - // if( accelerationchange / AccS < 1.0 ) { - // HACK: prevent excessive vehicle pinball cases - AccS += accelerationchange; - // AccS = clamp( AccS, -2.0, 2.0 ); - V = velocity; -// } - } - if( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) { - auto const othervehicleaccelerationchange{ ( othervehiclevelocity - othervehicle->V ) / dt }; -// if( othervehicleaccelerationchange / othervehicle->AccS < 1.0 ) { - // HACK: prevent excessive vehicle pinball cases - othervehicle->AccS += othervehicleaccelerationchange; - othervehicle->V = othervehiclevelocity; -// } - } + if (velocitydifference > safevelocitylimit * (TotalMass / othervehicle->TotalMass)) + { + Derail(COLLISION); + } + if (velocitydifference > safevelocitylimit * (othervehicle->TotalMass / TotalMass)) + { + othervehicle->Derail(COLLISION); + } + } + } + } + + // adjust velocity and acceleration of affected vehicles + if (false == TestFlag(DamageFlag, dtrain_out)) + { + auto const accelerationchange{(velocity - V) / dt}; + // if( accelerationchange / AccS < 1.0 ) { + // HACK: prevent excessive vehicle pinball cases + AccS += accelerationchange; + // AccS = clamp( AccS, -2.0, 2.0 ); + V = velocity; + // } + } + if (false == TestFlag(othervehicle->DamageFlag, dtrain_out)) + { + auto const othervehicleaccelerationchange{(othervehiclevelocity - othervehicle->V) / dt}; + // if( othervehicleaccelerationchange / othervehicle->AccS < 1.0 ) { + // HACK: prevent excessive vehicle pinball cases + othervehicle->AccS += othervehicleaccelerationchange; + othervehicle->V = othervehiclevelocity; + // } + } } -void -TMoverParameters::damage_coupler( int const End ) { +void TMoverParameters::damage_coupler(int const End) +{ - auto &coupler{ Couplers[ End ] }; + auto &coupler{Couplers[End]}; - if( coupler.type() == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what + if (coupler.type() == TCouplerType::Articulated) + { + return; + } // HACK: don't break articulated couplings no matter what - if( SetFlag( DamageFlag, dtrain_coupling ) ) - EventFlag = true; + if (SetFlag(DamageFlag, dtrain_coupling)) + EventFlag = true; - if( ( coupler.CouplingFlag & coupling::brakehose ) == coupling::brakehose ) { - // hamowanie nagle - zerwanie przewodow hamulcowych - AlarmChainFlag = true; - } + if ((coupler.CouplingFlag & coupling::brakehose) == coupling::brakehose) + { + // hamowanie nagle - zerwanie przewodow hamulcowych + AlarmChainFlag = true; + } - coupler.CouplingFlag = 0; + coupler.CouplingFlag = 0; - if( coupler.Connected != nullptr ) { - switch( End ) { - // break connection with other vehicle, if there's any - case 0: { - coupler.Connected->Couplers[ end::rear ].CouplingFlag = coupling::faux; - break; - } - case 1: { - coupler.Connected->Couplers[ end::front ].CouplingFlag = coupling::faux; - break; - } - default: { - break; - } - } - } + if (coupler.Connected != nullptr) + { + switch (End) + { + // break connection with other vehicle, if there's any + case 0: + { + coupler.Connected->Couplers[end::rear].CouplingFlag = coupling::faux; + break; + } + case 1: + { + coupler.Connected->Couplers[end::front].CouplingFlag = coupling::faux; + break; + } + default: + { + break; + } + } + } - WriteLog( "Bad driving: " + Name + " broke a coupler" ); + WriteLog("Bad driving: " + Name + " broke a coupler"); } -void TMoverParameters::Derail( DerailReason const Reason ) { - if( SetFlag( DamageFlag, dtrain_out ) ) { - EventFlag = true; - MainSwitch( false, range_t::local ); +void TMoverParameters::Derail(DerailReason const Reason) +{ + if (SetFlag(DamageFlag, dtrain_out)) + { + EventFlag = true; + MainSwitch(false, range_t::local); - AccS *= 0.65; - V *= 0.65; - RunningShape.R = 0; - if( Vel < 5.0 ) { - // HACK: prevent permanent axle spin in static vehicle after a collision - nrot = 0.0; - SlippingWheels = false; - } + AccS *= 0.65; + V *= 0.65; + RunningShape.R = 0; + if (Vel < 5.0) + { + // HACK: prevent permanent axle spin in static vehicle after a collision + nrot = 0.0; + SlippingWheels = false; + } - // Print a message in the log. - if (Reason == END_OF_TRACK) - ErrorLog("Bad driving: " + Name + " derailed due to end of track"); - else if (Reason == TOO_HIGH_SPEED) - ErrorLog("Bad driving: " + Name + " derailed due to too high speed"); - else if (Reason == GAUGE_MISMATCH) - ErrorLog("Bad dynamic: " + Name + " derailed due to track width"); // błąd w scenerii - else if (Reason == WRONG_TRACK_TYPE) - ErrorLog("Bad dynamic: " + Name + " derailed due to wrong track type"); // błąd w scenerii - else if (Reason == COLLISION) + // Print a message in the log. + if (Reason == END_OF_TRACK) + ErrorLog("Bad driving: " + Name + " derailed due to end of track"); + else if (Reason == TOO_HIGH_SPEED) + ErrorLog("Bad driving: " + Name + " derailed due to too high speed"); + else if (Reason == GAUGE_MISMATCH) + ErrorLog("Bad dynamic: " + Name + " derailed due to track width"); // błąd w scenerii + else if (Reason == WRONG_TRACK_TYPE) + ErrorLog("Bad dynamic: " + Name + " derailed due to wrong track type"); // błąd w scenerii + else if (Reason == COLLISION) WriteLog("Bad driving: " + Name + " derailed"); // This reason also generates its own message in `TMoverParameters::CollisionDetect()` - } + } } // ************************************************************************************************* // Oblicza przemieszczenie taboru // ************************************************************************************************* -double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShape &Shape, - TTrackParam &Track, TTractionParam &ElectricTraction, - TLocation const &NewLoc, TRotation const &NewRot) +double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, TLocation const &NewLoc, TRotation const &NewRot) { - const double Vepsilon = 1e-5; - const double Aepsilon = 1e-3; // ASBSpeed=0.8; + const double Vepsilon = 1e-5; + const double Aepsilon = 1e-3; // ASBSpeed=0.8; - if (!TestFlag(DamageFlag, dtrain_out)) - { // Ra: to przepisywanie tu jest bez sensu - RunningShape = Shape; - RunningTrack = Track; - RunningTraction = ElectricTraction; + if (!TestFlag(DamageFlag, dtrain_out)) + { // Ra: to przepisywanie tu jest bez sensu + RunningShape = Shape; + RunningTrack = Track; + RunningTraction = ElectricTraction; - //if (!DynamicBrakeFlag) - // RunningTraction.TractionVoltage = ElectricTraction.TractionVoltage /*- - // abs(ElectricTraction.TractionResistivity * - // (Itot + HVCouplers[0][0] + HVCouplers[1][0]))*/; - //else - // RunningTraction.TractionVoltage = - // ElectricTraction.TractionVoltage /*- - // abs(ElectricTraction.TractionResistivity * Itot * - // 0)*/; // zasadniczo ED oporowe nie zmienia napięcia w sieci - } + // if (!DynamicBrakeFlag) + // RunningTraction.TractionVoltage = ElectricTraction.TractionVoltage /*- + // abs(ElectricTraction.TractionResistivity * + // (Itot + HVCouplers[0][0] + HVCouplers[1][0]))*/; + // else + // RunningTraction.TractionVoltage = + // ElectricTraction.TractionVoltage /*- + // abs(ElectricTraction.TractionResistivity * Itot * + // 0)*/; // zasadniczo ED oporowe nie zmienia napięcia w sieci + } - if (CategoryFlag == 4) - OffsetTrackV = TotalMass / (Dim.L * Dim.W * 1000.0); - else if (TestFlag(CategoryFlag, 1) && TestFlag(RunningTrack.CategoryFlag, 1)) - if (TestFlag(DamageFlag, dtrain_out)) - { - OffsetTrackV = -0.2; - OffsetTrackH = Sign(RunningShape.R) * 0.2; - } + if (CategoryFlag == 4) + OffsetTrackV = TotalMass / (Dim.L * Dim.W * 1000.0); + else if (TestFlag(CategoryFlag, 1) && TestFlag(RunningTrack.CategoryFlag, 1)) + if (TestFlag(DamageFlag, dtrain_out)) + { + OffsetTrackV = -0.2; + OffsetTrackH = Sign(RunningShape.R) * 0.2; + } - // TODO: investigate, seems supplied NewRot is always 0 although the code here suggests some actual values are expected - Loc = NewLoc; - Rot = NewRot; + // TODO: investigate, seems supplied NewRot is always 0 although the code here suggests some actual values are expected + Loc = NewLoc; + Rot = NewRot; - if (dL == 0) // oblicz przesuniecie} - { - auto const AccSprev { AccS }; - // przyspieszenie styczne - AccS = interpolate( - AccSprev, - FTotal / TotalMass, - 0.5 ); - // clamp( dt * 3.0, 0.0, 1.0 ) ); // prawo Newtona ale z wygladzaniem (średnia z poprzednim) + if (dL == 0) // oblicz przesuniecie} + { + auto const AccSprev{AccS}; + // przyspieszenie styczne + AccS = interpolate(AccSprev, FTotal / TotalMass, 0.5); + // clamp( dt * 3.0, 0.0, 1.0 ) ); // prawo Newtona ale z wygladzaniem (średnia z poprzednim) - if (TestFlag(DamageFlag, dtrain_out)) - AccS = -Sign(V) * g * 1; // random(0.0, 0.1) + if (TestFlag(DamageFlag, dtrain_out)) + AccS = -Sign(V) * g * 1; // random(0.0, 0.1) - // przyspieszenie normalne - if (abs(Shape.R) > 0.01) - AccN = square(V) / Shape.R + g * Shape.dHrail / TrackW; // Q: zamieniam SQR() na sqr() - else - AccN = g * Shape.dHrail / TrackW; + // przyspieszenie normalne + if (abs(Shape.R) > 0.01) + AccN = square(V) / Shape.R + g * Shape.dHrail / TrackW; // Q: zamieniam SQR() na sqr() + else + AccN = g * Shape.dHrail / TrackW; - // velocity change - auto const Vprev { V }; - V += ( 3.0 * AccS - AccSprev ) * dt / 2.0; // przyrost predkosci - if( ( V * Vprev <= 0 ) - && ( std::abs( FStand ) > std::abs( FTrain ) ) ) { - // tlumienie predkosci przy hamowaniu - // zahamowany - V = 0; - } + // velocity change + auto const Vprev{V}; + V += (3.0 * AccS - AccSprev) * dt / 2.0; // przyrost predkosci + if ((V * Vprev <= 0) && (std::abs(FStand) > std::abs(FTrain))) + { + // tlumienie predkosci przy hamowaniu + // zahamowany + V = 0; + } - // tangential acceleration, from velocity change - AccSVBased = interpolate( - AccSVBased, - ( V - Vprev ) / dt, - clamp( dt * 3.0, 0.0, 1.0 ) ); + // tangential acceleration, from velocity change + AccSVBased = interpolate(AccSVBased, (V - Vprev) / dt, clamp(dt * 3.0, 0.0, 1.0)); - // vertical acceleration - AccVert = ( - std::abs( AccVert ) < 0.01 ? - 0.0 : - AccVert * 0.5 ); - // szarpanie -/* -#ifdef EU07_USE_FUZZYLOGIC - if( FuzzyLogic( ( 10.0 + Track.DamageFlag ) * Mass * Vel / Vmax, 500000.0, p_accn ) ) { - // Ra: czemu tu masa bez ładunku? - AccV /= ( 2.0 * 0.95 + 2.0 * Random() * 0.1 ); // 95-105% of base modifier (2.0) - } - else -#endif - AccV = AccV / 2.0; + // vertical acceleration + AccVert = (std::abs(AccVert) < 0.01 ? 0.0 : AccVert * 0.5); + // szarpanie + /* + #ifdef EU07_USE_FUZZYLOGIC + if( FuzzyLogic( ( 10.0 + Track.DamageFlag ) * Mass * Vel / Vmax, 500000.0, p_accn ) ) { + // Ra: czemu tu masa bez ładunku? + AccV /= ( 2.0 * 0.95 + 2.0 * Random() * 0.1 ); // 95-105% of base modifier (2.0) + } + else + #endif + AccV = AccV / 2.0; - if (AccV > 1.0) - AccN += (7.0 - Random(5)) * (100.0 + Track.DamageFlag / 2.0) * AccV / 2000.0; -*/ - // wykolejanie na luku oraz z braku szyn - if (TestFlag(CategoryFlag, 1)) - { - if (TestFlag(Track.DamageFlag, dtrack_norail)) - Derail(END_OF_TRACK); - if (FuzzyLogic((AccN / g) * (1.0 + 0.1 * (Track.DamageFlag & dtrack_freerail)), TrackW / Dim.H, 1)) - Derail(TOO_HIGH_SPEED); - // wykolejanie na poszerzeniu toru - if (FuzzyLogic(abs(Track.Width - TrackW), TrackW / 10.0, 1)) - Derail(GAUGE_MISMATCH); - } - // wykolejanie wkutek niezgodnosci kategorii toru i pojazdu - if (!TestFlag(RunningTrack.CategoryFlag, CategoryFlag)) - Derail(WRONG_TRACK_TYPE); + if (AccV > 1.0) + AccN += (7.0 - Random(5)) * (100.0 + Track.DamageFlag / 2.0) * AccV / 2000.0; + */ + // wykolejanie na luku oraz z braku szyn + if (TestFlag(CategoryFlag, 1)) + { + if (TestFlag(Track.DamageFlag, dtrack_norail)) + Derail(END_OF_TRACK); + if (FuzzyLogic((AccN / g) * (1.0 + 0.1 * (Track.DamageFlag & dtrack_freerail)), TrackW / Dim.H, 1)) + Derail(TOO_HIGH_SPEED); + // wykolejanie na poszerzeniu toru + if (FuzzyLogic(abs(Track.Width - TrackW), TrackW / 10.0, 1)) + Derail(GAUGE_MISMATCH); + } + // wykolejanie wkutek niezgodnosci kategorii toru i pojazdu + if (!TestFlag(RunningTrack.CategoryFlag, CategoryFlag)) + Derail(WRONG_TRACK_TYPE); - // dL:=(V+AccS*dt/2)*dt; - // przyrost dlugosci czyli przesuniecie - dL = (3.0 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha} - // ale jesli jest kolizja (zas. zach. pedu) to...} - for (int b = 0; b < 2; b++) - if (Couplers[b].CheckCollision) - CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!! + // dL:=(V+AccS*dt/2)*dt; + // przyrost dlugosci czyli przesuniecie + dL = (3.0 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha} + // ale jesli jest kolizja (zas. zach. pedu) to...} + for (int b = 0; b < 2; b++) + if (Couplers[b].CheckCollision) + CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!! - } // liczone dL, predkosc i przyspieszenie + } // liczone dL, predkosc i przyspieszenie - auto const d { ( - EngineType == TEngineType::WheelsDriven ? - dL * CabActive : // na chwile dla testu - dL ) }; + auto const d{(EngineType == TEngineType::WheelsDriven ? dL * CabActive : // na chwile dla testu + dL)}; - DistCounter += fabs(dL) / 1000.0; - dL = 0; + DistCounter += fabs(dL) / 1000.0; + dL = 0; - // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze - compute_movement_( dt ); + // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze + compute_movement_(dt); - // security system - SecuritySystemCheck(dt1); + // security system + SecuritySystemCheck(dt1); - return d; + return d; }; // ************************************************************************************************* // Oblicza przemieszczenie taboru - uproszczona wersja // ************************************************************************************************* -double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape, - TTrackParam &Track, TLocation const &NewLoc, - TRotation const &NewRot) +double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, TLocation const &NewLoc, TRotation const &NewRot) { - int b; - // T_MoverParameters::FastComputeMovement(dt, Shape, Track, NewLoc, NewRot); + int b; + // T_MoverParameters::FastComputeMovement(dt, Shape, Track, NewLoc, NewRot); - Loc = NewLoc; - Rot = NewRot; + Loc = NewLoc; + Rot = NewRot; - if (dL == 0) // oblicz przesuniecie - { - auto const AccSprev { AccS }; - // przyspieszenie styczne - AccS = interpolate( - AccSprev, - FTotal / TotalMass, - 0.5 ); - // clamp( dt * 3.0, 0.0, 1.0 ) ); // prawo Newtona ale z wygladzaniem (średnia z poprzednim) + if (dL == 0) // oblicz przesuniecie + { + auto const AccSprev{AccS}; + // przyspieszenie styczne + AccS = interpolate(AccSprev, FTotal / TotalMass, 0.5); + // clamp( dt * 3.0, 0.0, 1.0 ) ); // prawo Newtona ale z wygladzaniem (średnia z poprzednim) - if (TestFlag(DamageFlag, dtrain_out)) - AccS = -Sign(V) * g * 1; // * random(0.0, 0.1) + if (TestFlag(DamageFlag, dtrain_out)) + AccS = -Sign(V) * g * 1; // * random(0.0, 0.1) - // simple mode skips calculation of normal acceleration + // simple mode skips calculation of normal acceleration - // velocity change - auto const Vprev { V }; - V += ( 3.0 * AccS - AccSprev ) * dt / 2.0; // przyrost predkosci - if( ( V * Vprev <= 0 ) - && ( std::abs( FStand ) > std::abs( FTrain ) ) ) { - // tlumienie predkosci przy hamowaniu - // zahamowany - V = 0; - } + // velocity change + auto const Vprev{V}; + V += (3.0 * AccS - AccSprev) * dt / 2.0; // przyrost predkosci + if ((V * Vprev <= 0) && (std::abs(FStand) > std::abs(FTrain))) + { + // tlumienie predkosci przy hamowaniu + // zahamowany + V = 0; + } - // simple mode skips calculation of tangential acceleration + // simple mode skips calculation of tangential acceleration - // simple mode skips calculation of vertical acceleration - AccVert = 0.0; + // simple mode skips calculation of vertical acceleration + AccVert = 0.0; - if( ( true == TestFlag( DamageFlag, dtrain_out ) ) - && ( Vel < 1.0 ) ) { - V = 0.0; - AccS = 0.0; - } + if ((true == TestFlag(DamageFlag, dtrain_out)) && (Vel < 1.0)) + { + V = 0.0; + AccS = 0.0; + } - dL = (3.0 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha - // ale jesli jest kolizja (zas. zach. pedu) to... - for (b = 0; b < 2; b++) - if (Couplers[b].CheckCollision) - CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!! - } // liczone dL, predkosc i przyspieszenie + dL = (3.0 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha + // ale jesli jest kolizja (zas. zach. pedu) to... + for (b = 0; b < 2; b++) + if (Couplers[b].CheckCollision) + CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!! + } // liczone dL, predkosc i przyspieszenie - auto const d { ( - EngineType == TEngineType::WheelsDriven ? - dL * CabActive : // na chwile dla testu - dL ) }; + auto const d{(EngineType == TEngineType::WheelsDriven ? dL * CabActive : // na chwile dla testu + dL)}; - DistCounter += fabs(dL) / 1000.0; - dL = 0; + DistCounter += fabs(dL) / 1000.0; + dL = 0; - // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze - compute_movement_( dt ); + // koniec procedury, tu nastepuja dodatkowe procedury pomocnicze + compute_movement_(dt); - return d; + return d; }; // updates shared between 'fast' and regular movement computation methods -void TMoverParameters::compute_movement_( double const Deltatime ) { +void TMoverParameters::compute_movement_(double const Deltatime) +{ - // sprawdzanie i ewentualnie wykonywanie->kasowanie poleceń - if (LoadStatus > 0) // czas doliczamy tylko jeśli trwa (roz)ładowanie - LastLoadChangeTime += Deltatime; // czas (roz)ładunku + // sprawdzanie i ewentualnie wykonywanie->kasowanie poleceń + if (LoadStatus > 0) // czas doliczamy tylko jeśli trwa (roz)ładowanie + LastLoadChangeTime += Deltatime; // czas (roz)ładunku - RunInternalCommand(); + RunInternalCommand(); - // relay settings - if( EngineType == TEngineType::ElectricSeriesMotor ) { - // adjust motor overload relay threshold - if( ImaxHi > ImaxLo ) { - if( MotorOverloadRelayHighThreshold ) { // set high threshold - if( ( TrainType != dt_ET42 ) ? ( RList[ MainCtrlPos ].Bn < 2 ) : ( MainCtrlPos == 0 ) ) { - Imax = ImaxHi; - } - } - else { // set low threshold - if( ( TrainType != dt_ET42 ) || ( MainCtrlPos == 0 ) ) { - Imax = ImaxLo; - } - } - } - } + // relay settings + if (EngineType == TEngineType::ElectricSeriesMotor) + { + // adjust motor overload relay threshold + if (ImaxHi > ImaxLo) + { + if (MotorOverloadRelayHighThreshold) + { // set high threshold + if ((TrainType != dt_ET42) ? (RList[MainCtrlPos].Bn < 2) : (MainCtrlPos == 0)) + { + Imax = ImaxHi; + } + } + else + { // set low threshold + if ((TrainType != dt_ET42) || (MainCtrlPos == 0)) + { + Imax = ImaxLo; + } + } + } + } + + // Uproszczona symulacja wentylatorow rezystora hamowania - // Uproszczona symulacja wentylatorow rezystora hamowania - // Prad oddawany na rezystor double Irh = abs(eimv[eimv_Pe]) - abs(eimv[eimv_Ipoj]); @@ -1589,633 +1581,660 @@ void TMoverParameters::compute_movement_( double const Deltatime ) { { BRVtimer = 0; BRVentilators = true; - } - else { + } + else + { BRVtimer += Deltatime; if (BRVtimer > BRVto) BRVentilators = false; - } + } + // automatyczny rozruch + if (EngineType == TEngineType::ElectricSeriesMotor) + { + if (AutoRelayCheck()) + { + SetFlag(SoundFlag, sound::relay); + } + } + if ((EngineType == TEngineType::DieselEngine) || (EngineType == TEngineType::DieselElectric)) + { + if (dizel_Update(Deltatime)) + { + SetFlag(SoundFlag, sound::relay); + } + } + // TODO: gather and move current calculations to dedicated method + TotalCurrent = 0; - // automatyczny rozruch - if( EngineType == TEngineType::ElectricSeriesMotor ) { - if( AutoRelayCheck() ) { - SetFlag( SoundFlag, sound::relay ); - } - } + // low voltage power sources + LowVoltagePowerCheck(Deltatime); + // power sources + PantographsCheck(Deltatime); + // main circuit + MainsCheck(Deltatime); + // traction motors + MotorBlowersCheck(Deltatime); + // uklady hamulcowe: + ConverterCheck(Deltatime); + if (VeselVolume > 0) + Compressor = CompressedVolume / VeselVolume; + else + { + Compressor = 0; + CompressorFlag = false; + }; + if (VeselVolume > 0.0) + { + // sprężarka musi mieć jakąś niezerową wydajność żeby rozważać jej załączenie i pracę + CompressorCheck(Deltatime); + } + if (Power > 1.0) + { + // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich + UpdatePantVolume(Deltatime); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów + } + // heating + HeatingCheck(Deltatime); + // lighting + LightsCheck(Deltatime); - if( ( EngineType == TEngineType::DieselEngine ) - || ( EngineType == TEngineType::DieselElectric ) ) { - if( dizel_Update( Deltatime ) ) { - SetFlag( SoundFlag, sound::relay ); - } - } + UpdateBrakePressure(Deltatime); + UpdatePipePressure(Deltatime); + UpdateBatteryVoltage(Deltatime); + UpdateScndPipePressure(Deltatime); // druga rurka, youBy - // TODO: gather and move current calculations to dedicated method - TotalCurrent = 0; + if (((DCEMUED_CC & 1) != 0) && ((Couplers[end::front].CouplingFlag & coupling::control) != 0)) + { + DynamicBrakeEMUStatus &= Couplers[end::front].Connected->DynamicBrakeEMUStatus; + } + if (((DCEMUED_CC & 2) != 0) && ((Couplers[end::rear].CouplingFlag & coupling::control) != 0)) + { + DynamicBrakeEMUStatus &= Couplers[end::rear].Connected->DynamicBrakeEMUStatus; + } - // low voltage power sources - LowVoltagePowerCheck( Deltatime ); - // power sources - PantographsCheck( Deltatime ); - // main circuit - MainsCheck( Deltatime ); - // traction motors - MotorBlowersCheck( Deltatime ); - // uklady hamulcowe: - ConverterCheck( Deltatime ); - if (VeselVolume > 0) - Compressor = CompressedVolume / VeselVolume; - else - { - Compressor = 0; - CompressorFlag = false; - }; - if( VeselVolume > 0.0 ) { - // sprężarka musi mieć jakąś niezerową wydajność żeby rozważać jej załączenie i pracę - CompressorCheck( Deltatime ); - } - if( Power > 1.0 ) { - // w rozrządczym nie (jest błąd w FIZ!) - Ra 2014-07: teraz we wszystkich - UpdatePantVolume( Deltatime ); // Ra 2014-07: obsługa zbiornika rozrządu oraz pantografów - } - // heating - HeatingCheck( Deltatime ); - // lighting - LightsCheck( Deltatime ); + if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) + { // ASBSpeed=0.8 + // hamulec antypoślizgowy - wyłączanie + Hamulec->ASB(0); + } + BrakeSlippingTimer += Deltatime; + // automatic doors + update_doors(Deltatime); - UpdateBrakePressure(Deltatime); - UpdatePipePressure(Deltatime); - UpdateBatteryVoltage(Deltatime); - UpdateScndPipePressure(Deltatime); // druga rurka, youBy + m_plc.update(Deltatime); - if( ( ( DCEMUED_CC & 1 ) != 0 ) && ( ( Couplers[ end::front ].CouplingFlag & coupling::control ) != 0 ) ) { DynamicBrakeEMUStatus &= Couplers[ end::front ].Connected->DynamicBrakeEMUStatus; } - if( ( ( DCEMUED_CC & 2 ) != 0 ) && ( ( Couplers[ end::rear ].CouplingFlag & coupling::control ) != 0 ) ) { DynamicBrakeEMUStatus &= Couplers[ end::rear ].Connected->DynamicBrakeEMUStatus; } - - if( ( BrakeSlippingTimer > 0.8 ) && ( ASBType != 128 ) ) { // ASBSpeed=0.8 - // hamulec antypoślizgowy - wyłączanie - Hamulec->ASB( 0 ); - } - BrakeSlippingTimer += Deltatime; - // automatic doors - update_doors( Deltatime ); + PowerCouplersCheck(Deltatime, coupling::highvoltage); + PowerCouplersCheck(Deltatime, coupling::power110v); + PowerCouplersCheck(Deltatime, coupling::power24v); - m_plc.update( Deltatime ); - - PowerCouplersCheck( Deltatime, coupling::highvoltage ); - PowerCouplersCheck( Deltatime, coupling::power110v ); - PowerCouplersCheck( Deltatime, coupling::power24v ); - - Power24vVoltage = std::max( PowerCircuits[ 0 ].first, GetTrainsetVoltage( coupling::power24v ) ); - Power24vIsAvailable = ( Power24vVoltage > 0 ); - Power110vIsAvailable = ( ( PowerCircuits[ 1 ].first > 0 ) || ( GetTrainsetVoltage( coupling::power110v ) > 0 ) ); + Power24vVoltage = std::max(PowerCircuits[0].first, GetTrainsetVoltage(coupling::power24v)); + Power24vIsAvailable = (Power24vVoltage > 0); + Power110vIsAvailable = ((PowerCircuits[1].first > 0) || (GetTrainsetVoltage(coupling::power110v) > 0)); } -void TMoverParameters::MainsCheck( double const Deltatime ) { +void TMoverParameters::MainsCheck(double const Deltatime) +{ -// if( MainsInitTime == 0.0 ) { return; } + // if( MainsInitTime == 0.0 ) { return; } - // 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, - PantographVoltage ); - break; - } - case TPowerSource::Accumulator: { - localvoltage = - std::max( - localvoltage, - Power24vVoltage ); - break; - } - default: { - break; - } - } - auto const maincircuitpowersupply { - ( std::abs( localvoltage ) > 0.1 ) - || ( GetTrainsetHighVoltage() > 0.1 ) }; + // 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, PantographVoltage); + break; + } + case TPowerSource::Accumulator: + { + localvoltage = std::max(localvoltage, Power24vVoltage); + break; + } + default: + { + break; + } + } + auto const maincircuitpowersupply{(std::abs(localvoltage) > 0.1) || (GetTrainsetHighVoltage() > 0.1)}; - if( true == maincircuitpowersupply ) { - // all is well - if( MainsInitTimeCountdown >= 0.0 ) { - // NOTE: we ensure main circuit readiness meets condition MainsInitTimeCountdown < 0 - // this allows for simpler rejection of cases where MainsInitTime == 0 - MainsInitTimeCountdown -= Deltatime; - } - else { - // optional automatic circuit start - if( ( MainsStart != start_t::manual ) - && ( false == ( Mains || dizel_startup ) ) ) { - MainSwitch( true ); - } - } - } - else { - // no power supply - MainsInitTimeCountdown = MainsInitTime; - } + if (true == maincircuitpowersupply) + { + // all is well + if (MainsInitTimeCountdown >= 0.0) + { + // NOTE: we ensure main circuit readiness meets condition MainsInitTimeCountdown < 0 + // this allows for simpler rejection of cases where MainsInitTime == 0 + MainsInitTimeCountdown -= Deltatime; + } + else + { + // optional automatic circuit start + if ((MainsStart != start_t::manual) && (false == (Mains || dizel_startup))) + { + MainSwitch(true); + } + } + } + else + { + // no power supply + MainsInitTimeCountdown = MainsInitTime; + } } -void TMoverParameters::LowVoltagePowerCheck( double const Deltatime ) { +void TMoverParameters::LowVoltagePowerCheck(double const Deltatime) +{ - auto const lowvoltagepower { Power24vIsAvailable || Power110vIsAvailable }; + auto const lowvoltagepower{Power24vIsAvailable || Power110vIsAvailable}; - switch( EngineType ) { - case TEngineType::ElectricSeriesMotor: { - GroundRelay &= lowvoltagepower; - if( GroundRelayStart != start_t::manual ) { - // NOTE: we're ignoring intricaties of battery and converter types as they're unlikely to be used - // TODO: generic check method which takes these into account - GroundRelay |= lowvoltagepower; - } - break; - } - default: { - break; - } - } + switch (EngineType) + { + case TEngineType::ElectricSeriesMotor: + { + GroundRelay &= lowvoltagepower; + if (GroundRelayStart != start_t::manual) + { + // NOTE: we're ignoring intricaties of battery and converter types as they're unlikely to be used + // TODO: generic check method which takes these into account + GroundRelay |= lowvoltagepower; + } + break; + } + default: + { + break; + } + } } -void TMoverParameters::PowerCouplersCheck( double const Deltatime, coupling const Coupling ) { +void TMoverParameters::PowerCouplersCheck(double const Deltatime, coupling const Coupling) +{ - auto localvoltage { 0.0 }; + auto localvoltage{0.0}; - // local power sources - // TODO: make local voltage calculations a separate method, store results in PowerCircuit fields - switch( Coupling ) { + // local power sources + // TODO: make local voltage calculations a separate method, store results in PowerCircuit fields + switch (Coupling) + { - case coupling::highvoltage: { - // heating power sources - if( Heating ) { - switch( HeatingPowerSource.SourceType ) { - case TPowerSource::Generator: { - localvoltage = HeatingPowerSource.EngineGenerator.voltage - TotalCurrent * 0.02; - break; - } - case TPowerSource::CurrentCollector: { - localvoltage = PantographVoltage; - break; - } - case TPowerSource::Main: { - // HACK: main circuit can be fed through couplers, so we explicitly check pantograph supply here - localvoltage = ( - true == Mains ? - PantographVoltage : - 0.0 ); - break; - } - default: { - break; - } - } - } - // high voltage power sources - switch( EnginePowerSource.SourceType ) { - case TPowerSource::CurrentCollector: { - localvoltage = - std::max( - localvoltage, - PantographVoltage ); - break; - } - default: { - break; - } - } - break; - } + case coupling::highvoltage: + { + // heating power sources + if (Heating) + { + switch (HeatingPowerSource.SourceType) + { + case TPowerSource::Generator: + { + localvoltage = HeatingPowerSource.EngineGenerator.voltage - TotalCurrent * 0.02; + break; + } + case TPowerSource::CurrentCollector: + { + localvoltage = PantographVoltage; + break; + } + case TPowerSource::Main: + { + // HACK: main circuit can be fed through couplers, so we explicitly check pantograph supply here + localvoltage = (true == Mains ? PantographVoltage : 0.0); + break; + } + default: + { + break; + } + } + } + // high voltage power sources + switch (EnginePowerSource.SourceType) + { + case TPowerSource::CurrentCollector: + { + localvoltage = std::max(localvoltage, PantographVoltage); + break; + } + default: + { + break; + } + } + break; + } - case coupling::power110v: { - if( ConverterFlag ) { - localvoltage = NominalBatteryVoltage; - } - // TBD, TODO: reduce by current draw? - PowerCircuits[ 1 ].first = localvoltage; - break; - } + case coupling::power110v: + { + if (ConverterFlag) + { + localvoltage = NominalBatteryVoltage; + } + // TBD, TODO: reduce by current draw? + PowerCircuits[1].first = localvoltage; + break; + } - case coupling::power24v: { - if( Battery ) { - localvoltage = BatteryVoltage; - } - // TBD, TODO: reduce by current draw? - PowerCircuits[ 0 ].first = localvoltage; - break; - } + case coupling::power24v: + { + if (Battery) + { + localvoltage = BatteryVoltage; + } + // TBD, TODO: reduce by current draw? + PowerCircuits[0].first = localvoltage; + break; + } - default: { - break; - } - } + default: + { + break; + } + } - auto const abslocalvoltage { std::abs( localvoltage ) }; - auto const localpowersource { ( abslocalvoltage > 1.0 ) }; + auto const abslocalvoltage{std::abs(localvoltage)}; + auto const localpowersource{(abslocalvoltage > 1.0)}; - // 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 ) ] }; + // przekazywanie napiec + for (auto side = 0; side < 2; ++side) + { - bool oppositecouplingispresent; - bool localpowerexportisenabled; + 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)]}; - switch( Coupling ) { + bool oppositecouplingispresent; + bool localpowerexportisenabled; - case coupling::highvoltage: { - auto const oppositehighvoltagecoupling{ ( oppositecoupler.CouplingFlag & coupling::highvoltage ) != 0 }; - auto const oppositeheatingcoupling{ ( oppositecoupler.CouplingFlag & coupling::heating ) != 0 }; + switch (Coupling) + { - oppositecouplingispresent = ( oppositehighvoltagecoupling || oppositeheatingcoupling ); - localpowerexportisenabled = ( oppositehighvoltagecoupling || ( oppositeheatingcoupling && localpowersource && Heating ) ); - break; - } + case coupling::highvoltage: + { + auto const oppositehighvoltagecoupling{(oppositecoupler.CouplingFlag & coupling::highvoltage) != 0}; + auto const oppositeheatingcoupling{(oppositecoupler.CouplingFlag & coupling::heating) != 0}; - case coupling::power110v: { - oppositecouplingispresent = ( TestFlag( oppositecoupler.CouplingFlag, oppositecoupler.PowerCoupling ) ) && ( ( oppositecoupler.PowerFlag & coupling::power110v ) != 0 ); - localpowerexportisenabled = ( oppositecouplingispresent ); - break; - } + oppositecouplingispresent = (oppositehighvoltagecoupling || oppositeheatingcoupling); + localpowerexportisenabled = (oppositehighvoltagecoupling || (oppositeheatingcoupling && localpowersource && Heating)); + break; + } - case coupling::power24v: { - oppositecouplingispresent = ( TestFlag( oppositecoupler.CouplingFlag, oppositecoupler.PowerCoupling ) ) && ( ( oppositecoupler.PowerFlag & coupling::power24v ) != 0 ); - localpowerexportisenabled = ( oppositecouplingispresent ); - break; - } + case coupling::power110v: + { + oppositecouplingispresent = (TestFlag(oppositecoupler.CouplingFlag, oppositecoupler.PowerCoupling)) && ((oppositecoupler.PowerFlag & coupling::power110v) != 0); + localpowerexportisenabled = (oppositecouplingispresent); + break; + } - default: { - break; - } - } + case coupling::power24v: + { + oppositecouplingispresent = (TestFlag(oppositecoupler.CouplingFlag, oppositecoupler.PowerCoupling)) && ((oppositecoupler.PowerFlag & coupling::power24v) != 0); + localpowerexportisenabled = (oppositecouplingispresent); + break; + } - auto const *coupling = ( - Coupling == coupling::highvoltage ? &coupler.power_high : - Coupling == coupling::power110v ? &coupler.power_110v : - Coupling == coupling::power24v ? &coupler.power_24v : - nullptr ); - auto *oppositecoupling = ( - Coupling == coupling::highvoltage ? &oppositecoupler.power_high : - Coupling == coupling::power110v ? &oppositecoupler.power_110v : - Coupling == coupling::power24v ? &oppositecoupler.power_24v : - nullptr ); - - // start with base voltage - oppositecoupling->voltage = abslocalvoltage; - oppositecoupling->is_live = false; - oppositecoupling->is_local = localpowersource; // indicate power source - // draw from external source - if( coupler.Connected != nullptr ) { - auto const &connectedcoupler { coupler.Connected->Couplers[ coupler.ConnectedNr ] }; - auto const *connectedcoupling = ( - Coupling == coupling::highvoltage ? &connectedcoupler.power_high : - Coupling == coupling::power110v ? &connectedcoupler.power_110v : - Coupling == coupling::power24v ? &connectedcoupler.power_24v : - nullptr ); - auto const connectedvoltage { ( - connectedcoupling->is_live ? - connectedcoupling->voltage : - 0.0 ) }; - oppositecoupling->voltage = std::max( - oppositecoupling->voltage, - connectedvoltage - coupling->current * 0.02 ); - oppositecoupling->is_live = - ( connectedvoltage > 0.1 ) - && ( oppositecouplingispresent ); - } - // draw from local source - if( localpowersource ) { - oppositecoupling->voltage = std::max( - oppositecoupling->voltage, - abslocalvoltage - coupling->current * 0.02 ); - oppositecoupling->is_live |= - ( abslocalvoltage > 0.1 ) - && ( localpowerexportisenabled ); - } - } + default: + { + break; + } + } - // przekazywanie pradow - auto couplervoltage { 0 }; - switch( Coupling ) { - case coupling::highvoltage: { - couplervoltage = Couplers[ end::front ].power_high.voltage + Couplers[ end::rear ].power_high.voltage; - break; - } - case coupling::power110v: { - couplervoltage = Couplers[ end::front ].power_110v.voltage + Couplers[ end::rear ].power_110v.voltage; - break; - } - case coupling::power24v: { - couplervoltage = Couplers[ end::front ].power_24v.voltage + Couplers[ end::rear ].power_24v.voltage; - break; - } - default: { - break; - } - } + auto const *coupling = (Coupling == coupling::highvoltage ? &coupler.power_high : + Coupling == coupling::power110v ? &coupler.power_110v : + Coupling == coupling::power24v ? &coupler.power_24v : + nullptr); + auto *oppositecoupling = (Coupling == coupling::highvoltage ? &oppositecoupler.power_high : + Coupling == coupling::power110v ? &oppositecoupler.power_110v : + Coupling == coupling::power24v ? &oppositecoupler.power_24v : + nullptr); - auto *totalcurrent = ( - Coupling == coupling::highvoltage ? &TotalCurrent : - Coupling == coupling::power110v ? &PowerCircuits[ 1 ].second : - Coupling == coupling::power24v ? &PowerCircuits[ 0 ].second : - nullptr ); + // start with base voltage + oppositecoupling->voltage = abslocalvoltage; + oppositecoupling->is_live = false; + oppositecoupling->is_local = localpowersource; // indicate power source + // draw from external source + if (coupler.Connected != nullptr) + { + auto const &connectedcoupler{coupler.Connected->Couplers[coupler.ConnectedNr]}; + auto const *connectedcoupling = (Coupling == coupling::highvoltage ? &connectedcoupler.power_high : + Coupling == coupling::power110v ? &connectedcoupler.power_110v : + Coupling == coupling::power24v ? &connectedcoupler.power_24v : + nullptr); + auto const connectedvoltage{(connectedcoupling->is_live ? connectedcoupling->voltage : 0.0)}; + oppositecoupling->voltage = std::max(oppositecoupling->voltage, connectedvoltage - coupling->current * 0.02); + oppositecoupling->is_live = (connectedvoltage > 0.1) && (oppositecouplingispresent); + } + // draw from local source + if (localpowersource) + { + oppositecoupling->voltage = std::max(oppositecoupling->voltage, abslocalvoltage - coupling->current * 0.02); + oppositecoupling->is_live |= (abslocalvoltage > 0.1) && (localpowerexportisenabled); + } + } - for( auto side = 0; side < 2; ++side ) { + // przekazywanie pradow + auto couplervoltage{0}; + switch (Coupling) + { + case coupling::highvoltage: + { + couplervoltage = Couplers[end::front].power_high.voltage + Couplers[end::rear].power_high.voltage; + break; + } + case coupling::power110v: + { + couplervoltage = Couplers[end::front].power_110v.voltage + Couplers[end::rear].power_110v.voltage; + break; + } + case coupling::power24v: + { + couplervoltage = Couplers[end::front].power_24v.voltage + Couplers[end::rear].power_24v.voltage; + break; + } + default: + { + break; + } + } - auto &coupler { Couplers[ side ] }; - auto *coupling = ( - Coupling == coupling::highvoltage ? &coupler.power_high : - Coupling == coupling::power110v ? &coupler.power_110v : - Coupling == coupling::power24v ? &coupler.power_24v : - nullptr ); + auto *totalcurrent = (Coupling == coupling::highvoltage ? &TotalCurrent : + Coupling == coupling::power110v ? &PowerCircuits[1].second : + Coupling == coupling::power24v ? &PowerCircuits[0].second : + nullptr); - coupling->current = 0.0; + for (auto side = 0; side < 2; ++side) + { - if( coupler.Connected == nullptr ) { continue; } + auto &coupler{Couplers[side]}; + auto *coupling = (Coupling == coupling::highvoltage ? &coupler.power_high : + Coupling == coupling::power110v ? &coupler.power_110v : + Coupling == coupling::power24v ? &coupler.power_24v : + nullptr); - auto const &connectedothercoupler { coupler.Connected->Couplers[ ( coupler.ConnectedNr == end::front ? end::rear : end::front ) ] }; - auto const *connectedothercoupling = ( - Coupling == coupling::highvoltage ? &connectedothercoupler.power_high : - Coupling == coupling::power110v ? &connectedothercoupler.power_110v : - Coupling == coupling::power24v ? &connectedothercoupler.power_24v : - nullptr ); - auto const extracurrent = ( - Coupling == coupling::highvoltage ? std::abs( Itot ) * IsVehicleEIMBrakingFactor() : - 0.0 ); + coupling->current = 0.0; - if( false == localpowersource ) { - // bez napiecia... - if( couplervoltage != 0.0 ) { - // ...ale jest cos na sprzegach: - coupling->current = ( *totalcurrent + extracurrent ) * coupling->voltage / couplervoltage; // obciążenie rozkladane stosownie do napiec - if( true == coupling->is_live ) { - coupling->current += connectedothercoupling->current; - } - } - } - else { - if( true == coupling->is_live ) { - *totalcurrent += connectedothercoupling->current; - } - } - } + if (coupler.Connected == nullptr) + { + continue; + } + auto const &connectedothercoupler{coupler.Connected->Couplers[(coupler.ConnectedNr == end::front ? end::rear : end::front)]}; + auto const *connectedothercoupling = (Coupling == coupling::highvoltage ? &connectedothercoupler.power_high : + Coupling == coupling::power110v ? &connectedothercoupler.power_110v : + Coupling == coupling::power24v ? &connectedothercoupler.power_24v : + nullptr); + auto const extracurrent = (Coupling == coupling::highvoltage ? std::abs(Itot) * IsVehicleEIMBrakingFactor() : 0.0); + + if (false == localpowersource) + { + // bez napiecia... + if (couplervoltage != 0.0) + { + // ...ale jest cos na sprzegach: + coupling->current = (*totalcurrent + extracurrent) * coupling->voltage / couplervoltage; // obciążenie rozkladane stosownie do napiec + if (true == coupling->is_live) + { + coupling->current += connectedothercoupling->current; + } + } + } + else + { + if (true == coupling->is_live) + { + *totalcurrent += connectedothercoupling->current; + } + } + } } double TMoverParameters::ShowEngineRotation(int VehN) { // Zwraca wartość prędkości obrotowej silnika wybranego pojazdu. Do 3 pojazdów (3×SN61). - int b; - switch (VehN) - { // numer obrotomierza - case 1: - return std::abs(enrot); - case 2: - for (b = 0; b <= 1; ++b) - if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) - if (Couplers[b].Connected->Power > 0.01) - return fabs(Couplers[b].Connected->enrot); - break; - case 3: // to nie uwzględnia ewentualnego odwrócenia pojazdu w środku - for (b = 0; b <= 1; ++b) - if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) - if (Couplers[b].Connected->Power > 0.01) - if (TestFlag(Couplers[b].Connected->Couplers[b].CouplingFlag, coupling::control)) - if (Couplers[b].Connected->Couplers[b].Connected->Power > 0.01) - return fabs(Couplers[b].Connected->Couplers[b].Connected->enrot); - break; - }; - return 0.0; + int b; + switch (VehN) + { // numer obrotomierza + case 1: + return std::abs(enrot); + case 2: + for (b = 0; b <= 1; ++b) + if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) + if (Couplers[b].Connected->Power > 0.01) + return fabs(Couplers[b].Connected->enrot); + break; + case 3: // to nie uwzględnia ewentualnego odwrócenia pojazdu w środku + for (b = 0; b <= 1; ++b) + if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) + if (Couplers[b].Connected->Power > 0.01) + if (TestFlag(Couplers[b].Connected->Couplers[b].CouplingFlag, coupling::control)) + if (Couplers[b].Connected->Couplers[b].Connected->Power > 0.01) + return fabs(Couplers[b].Connected->Couplers[b].Connected->enrot); + break; + }; + return 0.0; }; // sprawdzanie przetwornicy -void TMoverParameters::ConverterCheck( double const Timestep ) { - // TODO: move other converter checks here, to have it all in one place for potential device object - if( ( ConverterStart != start_t::disabled ) - && ( ConverterOverloadRelayOffWhenMainIsOff ) ) { - ConvOvldFlag |= ( !Mains && Power24vIsAvailable ); - } +void TMoverParameters::ConverterCheck(double const Timestep) +{ + // TODO: move other converter checks here, to have it all in one place for potential device object + if ((ConverterStart != start_t::disabled) && (ConverterOverloadRelayOffWhenMainIsOff)) + { + ConvOvldFlag |= (!Mains && Power24vIsAvailable); + } - switch( ConverterStart ) { - case start_t::disabled: { - ConverterAllow = false; - // NOTE: if there's no converter in vehicle we can end the check here - return; - } - case start_t::automatic: { - ConverterAllow = Mains; - break; - } - case start_t::direction: { - ConverterAllow = ( DirActive != 0 ); - } - default: { - break; - } - } + switch (ConverterStart) + { + case start_t::disabled: + { + ConverterAllow = false; + // NOTE: if there's no converter in vehicle we can end the check here + return; + } + case start_t::automatic: + { + ConverterAllow = Mains; + break; + } + case start_t::direction: + { + ConverterAllow = (DirActive != 0); + } + default: + { + break; + } + } - if( ( ConverterAllow ) - && ( ConverterAllowLocal ) - && ( false == ConvOvldFlag ) - && ( false == PantPressLockActive ) - // HACK: allow carriages to operate converter without (missing) fuse prerequisite - && ( ( Power > 1.0 ? Mains : GetTrainsetHighVoltage() > 0.0 ) ) ) { - // delay timer can be optionally configured, and is set anew whenever converter goes off - if( ConverterStartDelayTimer <= 0.0 ) { - ConverterFlag = true; - } - else { - ConverterStartDelayTimer -= Timestep; - } - } - else { - ConverterFlag = false; - ConverterStartDelayTimer = static_cast( ConverterStartDelay ); - } + if ((ConverterAllow) && (ConverterAllowLocal) && (false == ConvOvldFlag) && + (false == PantPressLockActive) + // HACK: allow carriages to operate converter without (missing) fuse prerequisite + && ((Power > 1.0 ? Mains : GetTrainsetHighVoltage() > 0.0))) + { + // delay timer can be optionally configured, and is set anew whenever converter goes off + if (ConverterStartDelayTimer <= 0.0) + { + ConverterFlag = true; + } + else + { + ConverterStartDelayTimer -= Timestep; + } + } + else + { + ConverterFlag = false; + ConverterStartDelayTimer = static_cast(ConverterStartDelay); + } - if( ( ConverterOverloadRelayStart == start_t::converter ) - && ( false == ( ConverterAllow && ConverterAllowLocal ) ) - && ( false == TestFlag( EngDmgFlag, 4 ) ) ) { - // reset converter overload relay if the converter was switched off, unless it's damaged - ConvOvldFlag = false; - } + if ((ConverterOverloadRelayStart == start_t::converter) && (false == (ConverterAllow && ConverterAllowLocal)) && (false == TestFlag(EngDmgFlag, 4))) + { + // reset converter overload relay if the converter was switched off, unless it's damaged + ConvOvldFlag = false; + } }; // heating system status check -void TMoverParameters::HeatingCheck( double const Timestep ) { +void TMoverParameters::HeatingCheck(double const Timestep) +{ - // 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 ) ) { + // 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 &generator{HeatingPowerSource.EngineGenerator}; + // TBD, TODO: engine-generator transmission + generator.revolutions = *(generator.engine_revolutions); - auto const absrevolutions { std::abs( generator.revolutions ) }; - generator.voltage = ( - false == HeatingAllow ? 0.0 : - // TODO: add support for desired voltage selector - 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; - } - } + auto const absrevolutions{std::abs(generator.revolutions)}; + generator.voltage = (false == HeatingAllow ? 0.0 : + // TODO: add support for desired voltage selector + 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 blank slate - auto voltage { 0.0 }; - // then try specified power source - switch( HeatingPowerSource.SourceType ) { - case TPowerSource::Generator: { - voltage = HeatingPowerSource.EngineGenerator.voltage; - break; - } - case TPowerSource::CurrentCollector: { - voltage = PantographVoltage; - break; - } - case TPowerSource::PowerCable: { - if( HeatingPowerSource.PowerType == TPowerType::ElectricPower ) { - // TBD, TODO: limit input voltage to heating coupling type? - voltage = GetTrainsetHighVoltage(); - } - break; - } - case TPowerSource::Main: { - voltage = ( true == Mains ? std::max( GetTrainsetHighVoltage(), PantographVoltage ) : 0.0 ); - 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 blank slate + auto voltage{0.0}; + // then try specified power source + switch (HeatingPowerSource.SourceType) + { + case TPowerSource::Generator: + { + voltage = HeatingPowerSource.EngineGenerator.voltage; + break; + } + case TPowerSource::CurrentCollector: + { + voltage = PantographVoltage; + break; + } + case TPowerSource::PowerCable: + { + if (HeatingPowerSource.PowerType == TPowerType::ElectricPower) + { + // TBD, TODO: limit input voltage to heating coupling type? + voltage = GetTrainsetHighVoltage(); + } + break; + } + case TPowerSource::Main: + { + voltage = (true == Mains ? std::max(GetTrainsetHighVoltage(), PantographVoltage) : 0.0); + break; + } + default: + { + break; + } + } - Heating = ( voltage > heatingpowerthreshold ); + Heating = (voltage > heatingpowerthreshold); - if( Heating ) { - TotalCurrent += 1000 * HeatingPower / voltage; // heater power cost presumably specified in kilowatts - } + if (Heating) + { + TotalCurrent += 1000 * HeatingPower / voltage; // heater power cost presumably specified in kilowatts + } } // water pump status check -void TMoverParameters::WaterPumpCheck( double const Timestep ) { - // NOTE: breaker override with start type is sm42 specific hack, replace with ability to define the presence of the breaker - WaterPump.is_active = ( - ( true == ( Power24vIsAvailable || Power110vIsAvailable ) ) - && ( true == WaterPump.breaker ) - && ( false == WaterPump.is_disabled ) - && ( ( true == WaterPump.is_active ) - || ( true == WaterPump.is_enabled ) || ( WaterPump.start_type == start_t::battery ) ) ); +void TMoverParameters::WaterPumpCheck(double const Timestep) +{ + // NOTE: breaker override with start type is sm42 specific hack, replace with ability to define the presence of the breaker + WaterPump.is_active = ((true == (Power24vIsAvailable || Power110vIsAvailable)) && (true == WaterPump.breaker) && (false == WaterPump.is_disabled) && + ((true == WaterPump.is_active) || (true == WaterPump.is_enabled) || (WaterPump.start_type == start_t::battery))); } // water heater status check -void TMoverParameters::WaterHeaterCheck( double const Timestep ) { +void TMoverParameters::WaterHeaterCheck(double const Timestep) +{ - WaterHeater.is_active = ( - ( false == WaterHeater.is_damaged ) - && ( true == ( Power24vIsAvailable || Power110vIsAvailable ) ) - && ( true == WaterHeater.is_enabled ) - && ( true == WaterHeater.breaker ) - && ( ( WaterHeater.is_active ) || ( WaterHeater.config.temp_min < 0 ) || ( dizel_heat.temperatura1 < WaterHeater.config.temp_min ) ) ); + WaterHeater.is_active = ((false == WaterHeater.is_damaged) && (true == (Power24vIsAvailable || Power110vIsAvailable)) && (true == WaterHeater.is_enabled) && (true == WaterHeater.breaker) && + ((WaterHeater.is_active) || (WaterHeater.config.temp_min < 0) || (dizel_heat.temperatura1 < WaterHeater.config.temp_min))); - WaterHeater.is_damaged = ( - ( true == WaterHeater.is_damaged ) - || ( ( true == WaterHeater.is_active ) - && ( false == WaterPump.is_active ) ) ); + WaterHeater.is_damaged = ((true == WaterHeater.is_damaged) || ((true == WaterHeater.is_active) && (false == WaterPump.is_active))); - if( ( WaterHeater.config.temp_max > 0 ) - && ( dizel_heat.temperatura1 > WaterHeater.config.temp_max ) ) { - WaterHeater.is_active = false; - } + if ((WaterHeater.config.temp_max > 0) && (dizel_heat.temperatura1 > WaterHeater.config.temp_max)) + { + WaterHeater.is_active = false; + } } // fuel pump status update -void TMoverParameters::FuelPumpCheck( double const Timestep ) { +void TMoverParameters::FuelPumpCheck(double const Timestep) +{ - FuelPump.is_active = ( - ( true == ( Power24vIsAvailable || Power110vIsAvailable ) ) - && ( false == FuelPump.is_disabled ) - && ( ( FuelPump.is_active ) - || ( FuelPump.start_type == start_t::manual ? ( FuelPump.is_enabled ) : - FuelPump.start_type == start_t::automatic ? ( dizel_startup || Mains ) : - FuelPump.start_type == start_t::manualwithautofallback ? ( FuelPump.is_enabled || dizel_startup || Mains ) : - false ) ) ); // shouldn't ever get this far but, eh + FuelPump.is_active = ((true == (Power24vIsAvailable || Power110vIsAvailable)) && (false == FuelPump.is_disabled) && + ((FuelPump.is_active) || (FuelPump.start_type == start_t::manual ? (FuelPump.is_enabled) : + FuelPump.start_type == start_t::automatic ? (dizel_startup || Mains) : + FuelPump.start_type == start_t::manualwithautofallback ? (FuelPump.is_enabled || dizel_startup || Mains) : + false))); // shouldn't ever get this far but, eh } // oil pump status update -void TMoverParameters::OilPumpCheck( double const Timestep ) { +void TMoverParameters::OilPumpCheck(double const Timestep) +{ - OilPump.is_active = ( - ( true == ( Power24vIsAvailable || Power110vIsAvailable ) ) - && ( false == Mains ) - && ( false == OilPump.is_disabled ) - && ( ( OilPump.is_active ) - || ( OilPump.start_type == start_t::manual ? ( OilPump.is_enabled ) : - OilPump.start_type == start_t::automatic ? ( dizel_startup ) : - OilPump.start_type == start_t::manualwithautofallback ? ( OilPump.is_enabled || dizel_startup ) : - false ) ) ); // shouldn't ever get this far but, eh + OilPump.is_active = ((true == (Power24vIsAvailable || Power110vIsAvailable)) && (false == Mains) && (false == OilPump.is_disabled) && + ((OilPump.is_active) || (OilPump.start_type == start_t::manual ? (OilPump.is_enabled) : + OilPump.start_type == start_t::automatic ? (dizel_startup) : + OilPump.start_type == start_t::manualwithautofallback ? (OilPump.is_enabled || dizel_startup) : + false))); // shouldn't ever get this far but, eh - auto const minpressure { - OilPump.pressure_minimum > 0.f ? - OilPump.pressure_minimum : - 0.15f }; // arbitrary fallback value + auto const minpressure{OilPump.pressure_minimum > 0.f ? OilPump.pressure_minimum : 0.15f}; // arbitrary fallback value - OilPump.pressure_target = ( + OilPump.pressure_target = ( enrot > 0.1 ? interpolate( minpressure, OilPump.pressure_maximum, static_cast( EngineRPMRatio() ) ) * OilPump.resource_amount : true == OilPump.is_active ? std::min( minpressure + 0.1f, OilPump.pressure_maximum ) : // slight pressure margin to give time to switch off the pump and start the engine 0.f ); - if( OilPump.pressure < OilPump.pressure_target ) { - // TODO: scale change rate from 0.01-0.05 with oil/engine temperature/idle time - OilPump.pressure = - std::min( - OilPump.pressure_target, - OilPump.pressure + ( enrot > 5.0 ? 0.05 : 0.035 ) * Timestep ); - } - if( OilPump.pressure > OilPump.pressure_target ) { - OilPump.pressure = - std::max( - OilPump.pressure_target, - OilPump.pressure - ( enrot > 5.0 ? 0.05 : 0.035 ) * 0.5 * Timestep ); - } - OilPump.pressure = clamp( OilPump.pressure, 0.f, 1.5f ); + if (OilPump.pressure < OilPump.pressure_target) + { + // TODO: scale change rate from 0.01-0.05 with oil/engine temperature/idle time + OilPump.pressure = std::min(OilPump.pressure_target, OilPump.pressure + (enrot > 5.0 ? 0.05 : 0.035) * Timestep); + } + if (OilPump.pressure > OilPump.pressure_target) + { + OilPump.pressure = std::max(OilPump.pressure_target, OilPump.pressure - (enrot > 5.0 ? 0.05 : 0.035) * 0.5 * Timestep); + } + OilPump.pressure = clamp(OilPump.pressure, 0.f, 1.5f); } -void TMoverParameters::MotorBlowersCheck( double const Timestep ) { - // activation check - for( auto &blower : MotorBlowers ) { +void TMoverParameters::MotorBlowersCheck(double const Timestep) +{ + // activation check + for (auto &blower : MotorBlowers) + { auto disable = blower.is_disabled; - auto const start { ( Vel >= blower.min_start_velocity && std::abs(Im) > 0.5 ) }; - auto const stop { ( Vel < 0.5 && std::abs(Im) < 0.5 ) }; + auto const start{(Vel >= blower.min_start_velocity && std::abs(Im) > 0.5)}; + auto const stop{(Vel < 0.5 && std::abs(Im) < 0.5)}; if (blower.min_start_velocity >= 0) { - if ( stop ) + if (stop) { blower.stop_timer += Timestep; if (blower.stop_timer > blower.sustain_time) @@ -2223,7 +2242,7 @@ void TMoverParameters::MotorBlowersCheck( double const Timestep ) { disable = true; } } - else if ( start ) + else if (start) { blower.stop_timer = 0; } @@ -2232,134 +2251,119 @@ void TMoverParameters::MotorBlowersCheck( double const Timestep ) { disable |= !blower.is_active; } } - blower.is_active = ( - // TODO: bind properly power source when ld is in place - ( blower.start_type == start_t::battery ? Power24vIsAvailable : - blower.start_type == start_t::converter ? Power110vIsAvailable : - Mains ) // power source - // breaker condition disabled until it's implemented in the class data -// && ( true == blower.breaker ) - && ( false == disable) - && ( ( true == blower.is_active ) - || ( ( blower.stop_timer == 0.f ) // HACK: will be true for blower with exceeded start_velocity, and for one without start_velocity - && ( blower.start_type == start_t::manual ? - blower.is_enabled : - true ) ) ) ); - } - // update - for( auto &fan : MotorBlowers ) { + blower.is_active = ( + // TODO: bind properly power source when ld is in place + (blower.start_type == start_t::battery ? Power24vIsAvailable : + blower.start_type == start_t::converter ? Power110vIsAvailable : + Mains) // power source + // breaker condition disabled until it's implemented in the class data + // && ( true == blower.breaker ) + && (false == disable) && + ((true == blower.is_active) || ((blower.stop_timer == 0.f) // HACK: will be true for blower with exceeded start_velocity, and for one without start_velocity + && (blower.start_type == start_t::manual ? blower.is_enabled : true)))); + } + // update + for (auto &fan : MotorBlowers) + { - auto const revolutionstarget { ( - fan.is_active ? - ( fan.speed > 0.f ? fan.speed * static_cast( enrot ) * 60 : fan.speed * -1 ) : - 0.f ) }; + auto const revolutionstarget{(fan.is_active ? (fan.speed > 0.f ? fan.speed * static_cast(enrot) * 60 : fan.speed * -1) : 0.f)}; - if( std::abs( fan.revolutions - revolutionstarget ) < 0.01f ) { - fan.revolutions = revolutionstarget; - continue; - } - if( revolutionstarget > 0.f ) { - auto const speedincreasecap { std::max( 50.f, fan.speed * 0.05f * -1 ) }; // 5% of fixed revolution speed, or 50 - fan.revolutions += clamp( revolutionstarget - fan.revolutions, speedincreasecap * -2, speedincreasecap ) * Timestep; - } - else { - fan.revolutions *= std::max( 0.0, 1.0 - Timestep ); - } - } + if (std::abs(fan.revolutions - revolutionstarget) < 0.01f) + { + fan.revolutions = revolutionstarget; + continue; + } + if (revolutionstarget > 0.f) + { + auto const speedincreasecap{std::max(50.f, fan.speed * 0.05f * -1)}; // 5% of fixed revolution speed, or 50 + fan.revolutions += clamp(revolutionstarget - fan.revolutions, speedincreasecap * -2, speedincreasecap) * Timestep; + } + else + { + fan.revolutions *= std::max(0.0, 1.0 - Timestep); + } + } } -void TMoverParameters::PantographsCheck( double const Timestep ) { +void TMoverParameters::PantographsCheck(double const Timestep) +{ - { - auto &valve { PantsValve }; - auto const lowvoltagepower{ valve.solenoid ? ( Power24vIsAvailable || Power110vIsAvailable ) : true }; - auto const autostart{ valve.start_type == start_t::automatic || valve.start_type == start_t::manualwithautofallback }; - auto const manualcontrol{ valve.start_type == start_t::manual || valve.start_type == start_t::manualwithautofallback }; + { + auto &valve{PantsValve}; + auto const lowvoltagepower{valve.solenoid ? (Power24vIsAvailable || Power110vIsAvailable) : true}; + auto const autostart{valve.start_type == start_t::automatic || valve.start_type == start_t::manualwithautofallback}; + auto const manualcontrol{valve.start_type == start_t::manual || valve.start_type == start_t::manualwithautofallback}; - PantsValve.is_active = ( - ( ( valve.spring ? lowvoltagepower : true ) ) // spring actuator needs power to maintain non-default state - && ( ( ( manualcontrol && lowvoltagepower ) ? false == valve.is_disabled : true ) ) // needs power to change state - && ( ( valve.is_active ) - || ( autostart ? lowvoltagepower : - !autostart ? ( lowvoltagepower && valve.is_enabled ) : - false ) ) ); // shouldn't ever get this far but, eh - } + PantsValve.is_active = (((valve.spring ? lowvoltagepower : true)) // spring actuator needs power to maintain non-default state + && (((manualcontrol && lowvoltagepower) ? false == valve.is_disabled : true)) // needs power to change state + && ((valve.is_active) || (autostart ? lowvoltagepower : + !autostart ? (lowvoltagepower && valve.is_enabled) : + false))); // shouldn't ever get this far but, eh + } - size_t pant_id = 0; - for( auto &pantograph : Pantographs ) { + size_t pant_id = 0; + for (auto &pantograph : Pantographs) + { - auto &valve { pantograph.valve }; - auto const lowvoltagepower { valve.solenoid ? ( Power24vIsAvailable || Power110vIsAvailable ) : true }; - auto const autostart { valve.start_type == start_t::automatic || valve.start_type == start_t::manualwithautofallback }; - auto const manualcontrol { valve.start_type == start_t::manual || valve.start_type == start_t::manualwithautofallback }; + auto &valve{pantograph.valve}; + auto const lowvoltagepower{valve.solenoid ? (Power24vIsAvailable || Power110vIsAvailable) : true}; + auto const autostart{valve.start_type == start_t::automatic || valve.start_type == start_t::manualwithautofallback}; + auto const manualcontrol{valve.start_type == start_t::manual || valve.start_type == start_t::manualwithautofallback}; - valve.is_active = ( - ( ( valve.spring ? lowvoltagepower : true ) ) // spring actuator needs power to maintain non-default state - && ( ( ( manualcontrol && lowvoltagepower ) ? false == valve.is_disabled : true ) ) // needs power to change state, without it just pass through - && ( ( ( manualcontrol && lowvoltagepower ) ? false == PantAllDown : true ) ) - && ( ( valve.is_active ) - || ( manualcontrol && lowvoltagepower && valve.is_enabled ) - || ( autostart && lowvoltagepower ) ) ); // shouldn't ever get this far but, eh + valve.is_active = (((valve.spring ? lowvoltagepower : true)) // spring actuator needs power to maintain non-default state + && (((manualcontrol && lowvoltagepower) ? false == valve.is_disabled : true)) // needs power to change state, without it just pass through + && (((manualcontrol && lowvoltagepower) ? false == PantAllDown : true)) && + ((valve.is_active) || (manualcontrol && lowvoltagepower && valve.is_enabled) || (autostart && lowvoltagepower))); // shouldn't ever get this far but, eh - auto const pantographexists { (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) - && (EnginePowerSource.CollectorParameters.PhysicalLayout & (1 << pant_id)) }; + auto const pantographexists{(EnginePowerSource.SourceType == TPowerSource::CurrentCollector) && (EnginePowerSource.CollectorParameters.PhysicalLayout & (1 << pant_id))}; - pantograph.is_active = ( - ( valve.is_active ) - && ( PantsValve.is_active ) - && ( pantographexists ) -// && ( ) // TODO: add other checks - ); + pantograph.is_active = ((valve.is_active) && (PantsValve.is_active) && (pantographexists) + // && ( ) // TODO: add other checks + ); - pant_id++; - } + pant_id++; + } } -void TMoverParameters::LightsCheck( double const Timestep ) { +void TMoverParameters::LightsCheck(double const Timestep) +{ - auto &light { CompartmentLights }; + auto &light{CompartmentLights}; - light.is_active = ( - // TODO: bind properly power source when ld is in place - ( Power24vIsAvailable || Power110vIsAvailable ) // power source - && ( false == light.is_disabled ) - && ( ( true == light.is_active ) - || ( light.start_type == start_t::manual ? - light.is_enabled : - true ) ) ); + light.is_active = ( + // TODO: bind properly power source when ld is in place + (Power24vIsAvailable || Power110vIsAvailable) // power source + && (false == light.is_disabled) && ((true == light.is_active) || (light.start_type == start_t::manual ? light.is_enabled : true))); - light.intensity = - ( light.is_active ? - 1.0f : - 0.0f ) - // TODO: bind properly power source when ld is in place - * ( Power110vIsAvailable ? 1.0f : - Power24vIsAvailable ? 0.5f : - 0.0f ) - * light.dimming; + light.intensity = (light.is_active ? 1.0f : 0.0f) + // TODO: bind properly power source when ld is in place + * (Power110vIsAvailable ? 1.0f : + Power24vIsAvailable ? 0.5f : + 0.0f) * + light.dimming; } double TMoverParameters::ShowCurrent(int AmpN) const { // Odczyt poboru prądu na podanym amperomierzu - switch (EngineType) - { - case TEngineType::ElectricInductionMotor: - switch (AmpN) - { // do asynchronicznych - case 1: - return WindingRes * Mm / Vadd; - case 2: - return eimv_pr * WindingRes; - default: - return ShowCurrentP(AmpN); // T_MoverParameters:: - } - break; - case TEngineType::DieselElectric: - return fabs(Im); - break; - default: - return ShowCurrentP(AmpN); // T_MoverParameters:: - } + switch (EngineType) + { + case TEngineType::ElectricInductionMotor: + switch (AmpN) + { // do asynchronicznych + case 1: + return WindingRes * Mm / Vadd; + case 2: + return eimv_pr * WindingRes; + default: + return ShowCurrentP(AmpN); // T_MoverParameters:: + } + break; + case TEngineType::DieselElectric: + return fabs(Im); + break; + default: + return ShowCurrentP(AmpN); // T_MoverParameters:: + } }; // ************************************************************************************************* @@ -2374,159 +2378,180 @@ double TMoverParameters::ShowCurrent(int AmpN) const bool TMoverParameters::IncMainCtrl(int CtrlSpeed) { // basic fail conditions: - if( ( MainCtrlPosNo <= 0 ) - || ( CabActive == 0 ) ) { + if ((MainCtrlPosNo <= 0) || (CabActive == 0)) + { // nie ma sterowania return false; } - if( ( TrainType == dt_ET22 ) && ( ScndCtrlPos != 0 ) ) { - // w ET22 nie da się kręcić nastawnikiem przy włączonym boczniku + if ((TrainType == dt_ET22) && (ScndCtrlPos != 0)) + { + // w ET22 nie da się kręcić nastawnikiem przy włączonym boczniku return false; } - if( ( TrainType == dt_EZT ) && ( DirActive == 0 ) ) { - // w EZT nie da się załączyć pozycji bez ustawienia kierunku + if ((TrainType == dt_EZT) && (DirActive == 0)) + { + // w EZT nie da się załączyć pozycji bez ustawienia kierunku return false; } - bool OK = false; - if (MainCtrlPos < MainCtrlPosNo) - { - switch( EngineType ) { - case TEngineType::None: - case TEngineType::Dumb: - case TEngineType::DieselElectric: - case TEngineType::ElectricInductionMotor: - { - if( CtrlSpeed > 1 ) { - OK = ( IncMainCtrl( 1 ) - && IncMainCtrl( CtrlSpeed - 1 ) ); // a fail will propagate up the recursion chain. should this be || instead? + bool OK = false; + if (MainCtrlPos < MainCtrlPosNo) + { + switch (EngineType) + { + case TEngineType::None: + case TEngineType::Dumb: + case TEngineType::DieselElectric: + case TEngineType::ElectricInductionMotor: + { + if (CtrlSpeed > 1) + { + OK = (IncMainCtrl(1) && IncMainCtrl(CtrlSpeed - 1)); // a fail will propagate up the recursion chain. should this be || instead? + } + else + { + ++MainCtrlPos; + OK = true; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag & 1 == 1) && (MainCtrlActualPos != MainCtrlPos)) + { + DecScndCtrl(2); + SpeedCtrlUnit.IsActive = false; } - else { - ++MainCtrlPos; - OK = true; - if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag & 1 == 1) && (MainCtrlActualPos != MainCtrlPos)) - { - DecScndCtrl(2); - SpeedCtrlUnit.IsActive = false; - } - } - break; - } - - case TEngineType::ElectricSeriesMotor: - { - if( DirActive == 0 ) { return false; } - - if( CtrlSpeed > 1 ) { - // szybkie przejœcie na bezoporow¹ - if( TrainType == dt_ET40 ) { - break; // this means ET40 won't react at all to fast acceleration command. should it issue just IncMainCtrl(1) instead? - } - while( ( RList[ MainCtrlPos ].R > 0.0 ) - && IncMainCtrl( 1 ) ) { - // all work is done in the loop header - ; - } - OK = false; // shouldn't this be part of the loop above? - // if (TrainType=dt_ET40) then - // while Abs (Im)>IminHi do - // dec(MainCtrlPos); - // OK:=false ; - } - else { // CtrlSpeed == 1 - ++MainCtrlPos; - OK = true; - if( Imax == ImaxHi ) { - if( RList[ MainCtrlPos ].Bn > 1 ) { -/* NOTE: disabled, relay configuration was moved to compute_movement_ - if( true == MaxCurrentSwitch( false )) { - // wylaczanie wysokiego rozruchu - SetFlag( SoundFlag, sound::relay ); - } -*/ - if( TrainType == dt_ET42 ) { - --MainCtrlPos; - OK = false; - } - } - } - // - // if (TrainType == "et40") - // if (Abs(Im) > IminHi) - // { - // MainCtrlPos--; //Blokada nastawnika po przekroczeniu minimalnego pradu - // OK = false; - // } - //} - } - - if( ( TrainType == dt_ET42 ) && ( true == DynamicBrakeFlag ) ) { - if( MainCtrlPos > 20 ) { - MainCtrlPos = 20; - OK = false; - } - } - break; - } - - case TEngineType::DieselEngine: - { - if( CtrlSpeed > 1 ) { - while( ( MainCtrlPos < MainCtrlPosNo ) - && ( IncMainCtrl( 1 ) ) ) { - ; - } - } - else { - ++MainCtrlPos; - } - CompressorAllow = ( MainCtrlPowerPos() > 0 ); - OK = true; - break; - } - - case TEngineType::WheelsDriven: - { - OK = AddPulseForce( CtrlSpeed ); - break; - } - } // switch EngineType of - } - else {// MainCtrlPos>=MainCtrlPosNo - if( true == CoupledCtrl ) { - // wspólny wał nastawnika jazdy i bocznikowania - if( ScndCtrlPos < ScndCtrlPosNo ) { // 3<3 -> false - ++ScndCtrlPos; - OK = true; - } - else { - OK = false; - } + } + break; } - } - if( true == OK ) - { - SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); //??? - SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); - } + case TEngineType::ElectricSeriesMotor: + { + if (DirActive == 0) + { + return false; + } - // hunter-101012: poprawka - // poprzedni warunek byl niezbyt dobry, bo przez to przy trzymaniu + - // styczniki tkwily na tej samej pozycji (LastRelayTime byl caly czas 0 i rosl - // po puszczeniu plusa) + if (CtrlSpeed > 1) + { + // szybkie przejœcie na bezoporow¹ + if (TrainType == dt_ET40) + { + break; // this means ET40 won't react at all to fast acceleration command. should it issue just IncMainCtrl(1) instead? + } + while ((RList[MainCtrlPos].R > 0.0) && IncMainCtrl(1)) + { + // all work is done in the loop header + ; + } + OK = false; // shouldn't this be part of the loop above? + // if (TrainType=dt_ET40) then + // while Abs (Im)>IminHi do + // dec(MainCtrlPos); + // OK:=false ; + } + else + { // CtrlSpeed == 1 + ++MainCtrlPos; + OK = true; + if (Imax == ImaxHi) + { + if (RList[MainCtrlPos].Bn > 1) + { + /* NOTE: disabled, relay configuration was moved to compute_movement_ + if( true == MaxCurrentSwitch( false )) { + // wylaczanie wysokiego rozruchu + SetFlag( SoundFlag, sound::relay ); + } + */ + if (TrainType == dt_ET42) + { + --MainCtrlPos; + OK = false; + } + } + } + // + // if (TrainType == "et40") + // if (Abs(Im) > IminHi) + // { + // MainCtrlPos--; //Blokada nastawnika po przekroczeniu minimalnego pradu + // OK = false; + // } + //} + } - if (OK) - { - if (DelayCtrlFlag) - { - if ((LastRelayTime >= InitialCtrlDelay) && (MainCtrlPos == 1)) - LastRelayTime = 0; - } - else if (LastRelayTime > CtrlDelay) - LastRelayTime = 0; - } - return OK; + if ((TrainType == dt_ET42) && (true == DynamicBrakeFlag)) + { + if (MainCtrlPos > 20) + { + MainCtrlPos = 20; + OK = false; + } + } + break; + } + + case TEngineType::DieselEngine: + { + if (CtrlSpeed > 1) + { + while ((MainCtrlPos < MainCtrlPosNo) && (IncMainCtrl(1))) + { + ; + } + } + else + { + ++MainCtrlPos; + } + CompressorAllow = (MainCtrlPowerPos() > 0); + OK = true; + break; + } + + case TEngineType::WheelsDriven: + { + OK = AddPulseForce(CtrlSpeed); + break; + } + } // switch EngineType of + } + else + { // MainCtrlPos>=MainCtrlPosNo + if (true == CoupledCtrl) + { + // wspólny wał nastawnika jazdy i bocznikowania + if (ScndCtrlPos < ScndCtrlPosNo) + { // 3<3 -> false + ++ScndCtrlPos; + OK = true; + } + else + { + OK = false; + } + } + } + + if (true == OK) + { + SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); //??? + SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); + } + + // hunter-101012: poprawka + // poprzedni warunek byl niezbyt dobry, bo przez to przy trzymaniu + + // styczniki tkwily na tej samej pozycji (LastRelayTime byl caly czas 0 i rosl + // po puszczeniu plusa) + + if (OK) + { + if (DelayCtrlFlag) + { + if ((LastRelayTime >= InitialCtrlDelay) && (MainCtrlPos == 1)) + LastRelayTime = 0; + } + else if (LastRelayTime > CtrlDelay) + LastRelayTime = 0; + } + return OK; } // ***************************************************************************** @@ -2535,153 +2560,172 @@ bool TMoverParameters::IncMainCtrl(int CtrlSpeed) // ***************************************************************************** bool TMoverParameters::DecMainCtrl(int CtrlSpeed) { - bool OK = false; - // basic fail conditions: - if( ( MainCtrlPosNo <= 0 ) - || ( CabActive == 0 ) ) { + bool OK = false; + // basic fail conditions: + if ((MainCtrlPosNo <= 0) || (CabActive == 0)) + { // nie ma sterowania - OK = false; - } - else if( CtrlSpeed == 0 ) { - return false; - } - else - { - // TBD, TODO: replace with mainctrlpowerpos() check? - if (MainCtrlPos > 0) - { - if ((TrainType != dt_ET22) || - (ScndCtrlPos == 0)) // Ra: ET22 blokuje nastawnik przy boczniku - { - if (CoupledCtrl && (ScndCtrlPos > 0)) - { - ScndCtrlPos--; // wspolny wal - OK = true; - } - else - switch (EngineType) - { - case TEngineType::None: - case TEngineType::Dumb: - case TEngineType::DieselElectric: - case TEngineType::ElectricInductionMotor: - { - if (((CtrlSpeed == 1) && (EngineType != TEngineType::DieselElectric)) || - ((CtrlSpeed == 1) && (EngineType == TEngineType::DieselElectric))) - { - MainCtrlPos--; - OK = true; - if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag & 1 == 1) && (MainCtrlActualPos != MainCtrlPos)) { + OK = false; + } + else if (CtrlSpeed == 0) + { + return false; + } + else + { + // TBD, TODO: replace with mainctrlpowerpos() check? + if (MainCtrlPos > 0) + { + if ((TrainType != dt_ET22) || (ScndCtrlPos == 0)) // Ra: ET22 blokuje nastawnik przy boczniku + { + if (CoupledCtrl && (ScndCtrlPos > 0)) + { + ScndCtrlPos--; // wspolny wal + OK = true; + } + else + switch (EngineType) + { + case TEngineType::None: + case TEngineType::Dumb: + case TEngineType::DieselElectric: + case TEngineType::ElectricInductionMotor: + { + if (((CtrlSpeed == 1) && (EngineType != TEngineType::DieselElectric)) || ((CtrlSpeed == 1) && (EngineType == TEngineType::DieselElectric))) + { + MainCtrlPos--; + OK = true; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag & 1 == 1) && (MainCtrlActualPos != MainCtrlPos)) + { DecScndCtrl(2); SpeedCtrlUnit.IsActive = false; } - } - else if (CtrlSpeed > 1) - OK = (DecMainCtrl(1) && DecMainCtrl(CtrlSpeed - 1)); // CtrlSpeed-1); - break; - } + } + else if (CtrlSpeed > 1) + OK = (DecMainCtrl(1) && DecMainCtrl(CtrlSpeed - 1)); // CtrlSpeed-1); + break; + } - case TEngineType::ElectricSeriesMotor: - { - if (CtrlSpeed == 1) /*and (ScndCtrlPos=0)*/ - { - MainCtrlPos--; - // if (MainCtrlPos=0) and (ScndCtrlPos=0) and - // (TrainType<>dt_ET40)and(TrainType<>dt_EP05) then - // StLinFlag:=false; - // if (MainCtrlPos=0) and (TrainType<>dt_ET40) and - // (TrainType<>dt_EP05) then - // MainCtrlActualPos:=0; //yBARC: co to tutaj robi? ;) - OK = true; - } - else if (CtrlSpeed > 1) /*and (ScndCtrlPos=0)*/ - { - OK = true; - if (RList[MainCtrlPos].R == 0) // Q: tu zrobilem = ;] - DecMainCtrl(1); - while ((RList[MainCtrlPos].R > 0) && DecMainCtrl(1)) - ; // takie chamskie, potem poprawie} - } - break; - } + case TEngineType::ElectricSeriesMotor: + { + if (CtrlSpeed == 1) /*and (ScndCtrlPos=0)*/ + { + MainCtrlPos--; + // if (MainCtrlPos=0) and (ScndCtrlPos=0) and + // (TrainType<>dt_ET40)and(TrainType<>dt_EP05) then + // StLinFlag:=false; + // if (MainCtrlPos=0) and (TrainType<>dt_ET40) and + // (TrainType<>dt_EP05) then + // MainCtrlActualPos:=0; //yBARC: co to tutaj robi? ;) + OK = true; + } + else if (CtrlSpeed > 1) /*and (ScndCtrlPos=0)*/ + { + OK = true; + if (RList[MainCtrlPos].R == 0) // Q: tu zrobilem = ;] + DecMainCtrl(1); + while ((RList[MainCtrlPos].R > 0) && DecMainCtrl(1)) + ; // takie chamskie, potem poprawie} + } + break; + } - case TEngineType::DieselEngine: - { - if (CtrlSpeed == 1) - { - MainCtrlPos--; - OK = true; - } - else if (CtrlSpeed > 1) - { - while ((MainCtrlPos > 0) || (RList[MainCtrlPos].Mn > 0)) - DecMainCtrl(1); - OK = true; - } - break; - } - } // switch EngineType - } - } - else if (EngineType == TEngineType::WheelsDriven) - OK = AddPulseForce(-CtrlSpeed); - else - OK = false; + case TEngineType::DieselEngine: + { + if (CtrlSpeed == 1) + { + MainCtrlPos--; + OK = true; + } + else if (CtrlSpeed > 1) + { + while ((MainCtrlPos > 0) || (RList[MainCtrlPos].Mn > 0)) + DecMainCtrl(1); + OK = true; + } + break; + } + } // switch EngineType + } + } + else if (EngineType == TEngineType::WheelsDriven) + OK = AddPulseForce(-CtrlSpeed); + else + OK = false; - if (OK) - { - /*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); // hmmmm...???!!! - /*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); - } - } - // if OK then LastRelayTime:=0; - // hunter-101012: poprawka - if (OK) - { - if (DelayCtrlFlag) - { - if (LastRelayTime >= InitialCtrlDelay) - LastRelayTime = 0; - } - else if (LastRelayTime > CtrlDownDelay) - LastRelayTime = 0; - } - return OK; + if (OK) + { + /*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); // hmmmm...???!!! + /*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); + } + } + // if OK then LastRelayTime:=0; + // hunter-101012: poprawka + if (OK) + { + if (DelayCtrlFlag) + { + if (LastRelayTime >= InitialCtrlDelay) + LastRelayTime = 0; + } + else if (LastRelayTime > CtrlDownDelay) + LastRelayTime = 0; + } + return OK; } -bool TMoverParameters::IsMainCtrlActualNoPowerPos() const { - // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems - return MainCtrlActualPos <= MainCtrlNoPowerPos(); +bool TMoverParameters::IsMainCtrlActualNoPowerPos() const +{ + // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems + return MainCtrlActualPos <= MainCtrlNoPowerPos(); } -bool TMoverParameters::IsMainCtrlNoPowerPos() const { - // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems - return MainCtrlPos <= MainCtrlNoPowerPos(); +bool TMoverParameters::IsMainCtrlNoPowerPos() const +{ + // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems + return MainCtrlPos <= MainCtrlNoPowerPos(); } -bool TMoverParameters::IsMainCtrlMaxPowerPos() const { - // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems - return MainCtrlPos == MainCtrlPosNo; +bool TMoverParameters::IsMainCtrlMaxPowerPos() const +{ + // TODO: wrap controller pieces into a class for potential specializations, similar to brake subsystems + return MainCtrlPos == MainCtrlPosNo; } -int TMoverParameters::MainCtrlNoPowerPos() const { +int TMoverParameters::MainCtrlNoPowerPos() const +{ - switch( EIMCtrlType ) { - case 1: { return 3; } - case 2: { return 3; } - case 3: { return UniCtrlNoPowerPos; } - default: { return 0; } - } + switch (EIMCtrlType) + { + case 1: + { + return 3; + } + case 2: + { + return 3; + } + case 3: + { + return UniCtrlNoPowerPos; + } + default: + { + return 0; + } + } } -int TMoverParameters::MainCtrlActualPowerPos() const { +int TMoverParameters::MainCtrlActualPowerPos() const +{ - return MainCtrlActualPos - MainCtrlNoPowerPos(); + return MainCtrlActualPos - MainCtrlNoPowerPos(); } -int TMoverParameters::MainCtrlPowerPos() const { +int TMoverParameters::MainCtrlPowerPos() const +{ - return MainCtrlPos - MainCtrlNoPowerPos(); + return MainCtrlPos - MainCtrlNoPowerPos(); } // ************************************************************************************************* @@ -2690,71 +2734,71 @@ int TMoverParameters::MainCtrlPowerPos() const { // ************************************************************************************************* bool TMoverParameters::IncScndCtrl(int CtrlSpeed) { - bool OK = false; + bool OK = false; - if ( ( DynamicBrakeFlag ) && ( TrainType == dt_ET42 ) && ( CabActive != 0 ) && ( IsMainCtrlNoPowerPos() ) && ( ScndCtrlPos == 0 ) ) - { - OK = DynamicBrakeSwitch(false); - } - else if ((ScndCtrlPosNo > 0) && (CabActive != 0) && - !((TrainType == dt_ET42) && - ((Imax == ImaxHi) || ((DynamicBrakeFlag) && (MainCtrlPowerPos() > 0))))) - { - // if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos 1 ) { - ScndCtrlPos = ScndCtrlPosNo; // takie chamskie, potem poprawie - } - OK = true; - } - } - else // nie mozna zmienic - OK = false; - if (OK) - { - /*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); //??? - /*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); - - } - } - else // nie ma sterowania - OK = false; - // if OK then LastRelayTime:=0; - // hunter-101012: poprawka - if (OK) - if (LastRelayTime > CtrlDelay) - LastRelayTime = 0; - - if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1) && (MainCtrlPos>0)) + if ((DynamicBrakeFlag) && (TrainType == dt_ET42) && (CabActive != 0) && (IsMainCtrlNoPowerPos()) && (ScndCtrlPos == 0)) { - SpeedCtrlValue = Vel; - if ((EIMCtrlType == 0)&&(SpeedCtrlAutoTurnOffFlag & 1 == 1)) + OK = DynamicBrakeSwitch(false); + } + else if ((ScndCtrlPosNo > 0) && (CabActive != 0) && !((TrainType == dt_ET42) && ((Imax == ImaxHi) || ((DynamicBrakeFlag) && (MainCtrlPowerPos() > 0))))) + { + // if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos 1) + { + ScndCtrlPos = ScndCtrlPosNo; // takie chamskie, potem poprawie + } + OK = true; + } + } + else // nie mozna zmienic + OK = false; + if (OK) + { + /*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); //??? + /*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); + } + } + else // nie ma sterowania + OK = false; + // if OK then LastRelayTime:=0; + // hunter-101012: poprawka + if (OK) + if (LastRelayTime > CtrlDelay) + LastRelayTime = 0; + + if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1) && (MainCtrlPos > 0)) + { + SpeedCtrlValue = Vel; + if ((EIMCtrlType == 0) && (SpeedCtrlAutoTurnOffFlag & 1 == 1)) { MainCtrlActualPos = MainCtrlPos; } SpeedCtrlUnit.IsActive = true; } - if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 1) && (EngineType == TEngineType::DieselEngine)) + if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 1) && (EngineType == TEngineType::DieselEngine)) { // NOTE: round() already adds 0.5, are the ones added here as well correct? SpeedCtrlValue = Round(Vel); SpeedCtrlUnit.IsActive = true; } - return OK; + return OK; } // ************************************************************************************************* @@ -2763,64 +2807,64 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed) // ************************************************************************************************* bool TMoverParameters::DecScndCtrl(int CtrlSpeed) { - bool OK = false; + bool OK = false; - if ((IsMainCtrlNoPowerPos()) && (CabActive != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) && - !(DynamicBrakeFlag) && (CtrlSpeed == 1)) - { - // Ra: AI wywołuje z CtrlSpeed=2 albo gdy ScndCtrlPos>0 - OK = DynamicBrakeSwitch(true); - } - else if ((ScndCtrlPosNo > 0) && (CabActive != 0)) - { - if ((ScndCtrlPos > 0) && (!CoupledCtrl) && - ((EngineType != TEngineType::DieselElectric) || (!AutoRelayFlag))) - { - if (CtrlSpeed == 1) - { - ScndCtrlPos--; - } - else if (CtrlSpeed > 1) - { - ScndCtrlPos = 0; // takie chamskie, potem poprawie - } - OK = true; - } - else - OK = false; - if (OK) - { - /*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); //??? - /*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); - } - } - else - OK = false; - // if OK then LastRelayTime:=0; - // hunter-101012: poprawka - if (OK) - if (LastRelayTime > CtrlDownDelay) - LastRelayTime = 0; + if ((IsMainCtrlNoPowerPos()) && (CabActive != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) && !(DynamicBrakeFlag) && (CtrlSpeed == 1)) + { + // Ra: AI wywołuje z CtrlSpeed=2 albo gdy ScndCtrlPos>0 + OK = DynamicBrakeSwitch(true); + } + else if ((ScndCtrlPosNo > 0) && (CabActive != 0)) + { + if ((ScndCtrlPos > 0) && (!CoupledCtrl) && ((EngineType != TEngineType::DieselElectric) || (!AutoRelayFlag))) + { + if (CtrlSpeed == 1) + { + ScndCtrlPos--; + } + else if (CtrlSpeed > 1) + { + ScndCtrlPos = 0; // takie chamskie, potem poprawie + } + OK = true; + } + else + OK = false; + if (OK) + { + /*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabActive); //??? + /*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabActive); + } + } + else + OK = false; + // if OK then LastRelayTime:=0; + // hunter-101012: poprawka + if (OK) + if (LastRelayTime > CtrlDownDelay) + LastRelayTime = 0; if ((OK) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo == 1)) { SpeedCtrlValue = 0; SpeedCtrlUnit.IsActive = false; - if (SpeedCtrlUnit.ManualStateOverride) { + if (SpeedCtrlUnit.ManualStateOverride) + { eimic = 0.0; } } - if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 0) && (EngineType == TEngineType::DieselEngine)) + if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 0) && (EngineType == TEngineType::DieselEngine)) { SpeedCtrlValue = 0; SpeedCtrlUnit.IsActive = false; - if (SpeedCtrlUnit.ManualStateOverride) { + if (SpeedCtrlUnit.ManualStateOverride) + { eimic = 0.0; } } - return OK; + return OK; } int TMoverParameters::GetVirtualScndPos() @@ -2833,39 +2877,41 @@ int TMoverParameters::GetVirtualScndPos() return ScndCtrlPos; } -bool TMoverParameters::IsScndCtrlNoPowerPos() const { - // TODO: refine the check on account of potential electric series vehicles with speed control - return ( ( ScndCtrlPos == 0 ) || ( true == SpeedCtrl ) ); +bool TMoverParameters::IsScndCtrlNoPowerPos() const +{ + // TODO: refine the check on account of potential electric series vehicles with speed control + return ((ScndCtrlPos == 0) || (true == SpeedCtrl)); } -bool TMoverParameters::IsScndCtrlMaxPowerPos() const { - // TODO: refine the check on account of potential electric series vehicles with speed control - return ( ( ScndCtrlPos == ScndCtrlPosNo ) || ( true == SpeedCtrl ) ); +bool TMoverParameters::IsScndCtrlMaxPowerPos() const +{ + // TODO: refine the check on account of potential electric series vehicles with speed control + return ((ScndCtrlPos == ScndCtrlPosNo) || (true == SpeedCtrl)); } // ************************************************************************************************* // Q: 20160710 // załączenie rozrządu // ************************************************************************************************* -bool TMoverParameters::CabActivisation( bool const Enforce ) +bool TMoverParameters::CabActivisation(bool const Enforce) { - bool OK = false; + bool OK = false; - OK = Enforce || (CabActive == 0); // numer kabiny, z której jest sterowanie - if (OK) - { - CabActive = CabOccupied; // sterowanie jest z kabiny z obsadą - DirAbsolute = DirActive * CabActive; + OK = Enforce || (CabActive == 0); // numer kabiny, z której jest sterowanie + if (OK) + { + CabActive = CabOccupied; // sterowanie jest z kabiny z obsadą + DirAbsolute = DirActive * CabActive; CabMaster = true; - SecuritySystem.set_enabled(true); // activate the alerter TODO: make it part of control based cab selection - SendCtrlToNext("CabActivisation", 1, CabActive); + SecuritySystem.set_enabled(true); // activate the alerter TODO: make it part of control based cab selection + SendCtrlToNext("CabActivisation", 1, CabActive); SendCtrlToNext("Direction", DirAbsolute, CabActive); if (InactiveCabFlag & activation::springbrakeoff) { SpringBrakeActivate(false); } - } - return OK; + } + return OK; } bool TMoverParameters::CabActivisationAuto(bool const Enforce) @@ -2878,13 +2924,13 @@ bool TMoverParameters::CabActivisationAuto(bool const Enforce) // Q: 20160710 // wyłączenie rozrządu // ************************************************************************************************* -bool TMoverParameters::CabDeactivisation( bool const Enforce ) +bool TMoverParameters::CabDeactivisation(bool const Enforce) { - bool OK = false; + bool OK = false; - OK = Enforce || IsCabMaster(); // o ile obsada jest w kabinie ze sterowaniem - if (OK) - { + OK = Enforce || IsCabMaster(); // o ile obsada jest w kabinie ze sterowaniem + if (OK) + { if (InactiveCabFlag & activation::springbrakeon) { SpringBrakeActivate(true); @@ -2904,15 +2950,15 @@ bool TMoverParameters::CabDeactivisation( bool const Enforce ) SendCtrlToNext("Direction", 0, CabActive); } - CabActive = 0; - DirAbsolute = DirActive * CabActive; + CabActive = 0; + DirAbsolute = DirActive * CabActive; CabMaster = false; - DepartureSignal = false; // nie buczeć z nieaktywnej kabiny - SecuritySystem.set_enabled(false); // deactivate alerter TODO: make it part of control based cab selection + DepartureSignal = false; // nie buczeć z nieaktywnej kabiny + SecuritySystem.set_enabled(false); // deactivate alerter TODO: make it part of control based cab selection - SendCtrlToNext("CabActivisation", 0, CabOccupied); // CabActive==0! - } - return OK; + SendCtrlToNext("CabActivisation", 0, CabOccupied); // CabActive==0! + } + return OK; } bool TMoverParameters::CabDeactivisationAuto(bool const Enforce) @@ -2927,26 +2973,25 @@ bool TMoverParameters::CabDeactivisationAuto(bool const Enforce) // ************************************************************************************************* bool TMoverParameters::AddPulseForce(int Multipler) { - bool APF; - if ((EngineType == TEngineType::WheelsDriven) && (EnginePowerSource.SourceType == TPowerSource::InternalSource) && - (EnginePowerSource.PowerType == TPowerType::BioPower)) - { - DirActive = CabActive; - DirAbsolute = DirActive * CabActive; - if (Vel > 0) - PulseForce = Min0R(1000.0 * Power / (abs(V) + 0.1), Ftmax); - else - PulseForce = Ftmax; - if (PulseForceCount > 1000.0) - PulseForce = 0; - else - PulseForce = PulseForce * Multipler; - PulseForceCount = PulseForceCount + abs(Multipler); - APF = (PulseForce > 0); - } - else - APF = false; - return APF; + bool APF; + if ((EngineType == TEngineType::WheelsDriven) && (EnginePowerSource.SourceType == TPowerSource::InternalSource) && (EnginePowerSource.PowerType == TPowerType::BioPower)) + { + DirActive = CabActive; + DirAbsolute = DirActive * CabActive; + if (Vel > 0) + PulseForce = Min0R(1000.0 * Power / (abs(V) + 0.1), Ftmax); + else + PulseForce = Ftmax; + if (PulseForceCount > 1000.0) + PulseForce = 0; + else + PulseForce = PulseForce * Multipler; + PulseForceCount = PulseForceCount + abs(Multipler); + APF = (PulseForce > 0); + } + else + APF = false; + return APF; } // ************************************************************************************************* @@ -2955,17 +3000,21 @@ bool TMoverParameters::AddPulseForce(int Multipler) // ************************************************************************************************* bool TMoverParameters::SandboxManual(bool const State, range_t const Notify) { - bool result{ false }; + bool result{false}; - if (SandDoseManual != State) { - if (SandDoseManual == false) { + if (SandDoseManual != State) + { + if (SandDoseManual == false) + { // switch on - if (Sand > 0) { + if (Sand > 0) + { SandDoseManual = true; result = true; } } - else { + else + { // switch off SandDoseManual = false; result = true; @@ -2983,17 +3032,21 @@ bool TMoverParameters::SandboxManual(bool const State, range_t const Notify) // ************************************************************************************************* bool TMoverParameters::SandboxAuto(bool const State, range_t const Notify) { - bool result{ false }; + bool result{false}; bool NewState = State && SandDoseAutoAllow; - if (SandDoseAuto != NewState) { - if (SandDoseAuto == false) { + if (SandDoseAuto != NewState) + { + if (SandDoseAuto == false) + { // switch on - if (Sand > 0) { + if (Sand > 0) + { SandDoseAuto = true; result = true; } } - else { + else + { // switch off SandDoseAuto = false; result = true; @@ -3005,48 +3058,51 @@ bool TMoverParameters::SandboxAuto(bool const State, range_t const Notify) return result; } - // ************************************************************************************************* // Q: 20160713 // sypanie piasku // ************************************************************************************************* -bool TMoverParameters::Sandbox( bool const State, range_t const Notify ) +bool TMoverParameters::Sandbox(bool const State, range_t const Notify) { - bool result{ false }; + bool result{false}; - if( SandDose != State ) { - if( SandDose == false ) { - // switch on - if(( Sand > 0 ) && ( DirActive != 0 )) { - SandDose = true; - result = true; - } - } - else { - // switch off - SandDose = false; - result = true; - } - } + if (SandDose != State) + { + if (SandDose == false) + { + // switch on + if ((Sand > 0) && (DirActive != 0)) + { + SandDose = true; + result = true; + } + } + else + { + // switch off + SandDose = false; + result = true; + } + } - if( Notify != range_t::local ) { - // if requested pass the command on - auto const couplingtype = - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ); + if (Notify != range_t::local) + { + // if requested pass the command on + auto const couplingtype = (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control); - if( State == true ) { - // switch on - SendCtrlToNext( "Sandbox", 1, CabActive, couplingtype ); - } - else { - // switch off - SendCtrlToNext( "Sandbox", 0, CabActive, couplingtype ); - } - } + if (State == true) + { + // switch on + SendCtrlToNext("Sandbox", 1, CabActive, couplingtype); + } + else + { + // switch off + SendCtrlToNext("Sandbox", 0, CabActive, couplingtype); + } + } - return result; + return result; } // ************************************************************************************************* @@ -3055,7 +3111,7 @@ bool TMoverParameters::Sandbox( bool const State, range_t const Notify ) // ************************************************************************************************* bool TMoverParameters::SandboxAutoAllow(bool State) { - //SendCtrlToNext("SandboxAutoAllow", int(State), CabActive, ctrain_controll); + // SendCtrlToNext("SandboxAutoAllow", int(State), CabActive, ctrain_controll); if (SandDoseAutoAllow != State) { @@ -3064,7 +3120,6 @@ bool TMoverParameters::SandboxAutoAllow(bool State) } else return false; - } // ***************************************************************************** @@ -3087,46 +3142,36 @@ void TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP void TMoverParameters::SecuritySystemCheck(double dt) { bool isPower = Power24vIsAvailable || Power110vIsAvailable; - SecuritySystem.update(dt, Vel, isPower, CabActive); + SecuritySystem.update(dt, Vel, isPower, CabActive); - if (!Battery || !Radio) - { // wyłączenie baterii deaktywuje sprzęt + if (!Battery || !Radio) + { // wyłączenie baterii deaktywuje sprzęt RadiostopSwitch(false); - } + } } // ************************************************************************************************* // Q: 20160710 // włączenie / wyłączenie baterii // ************************************************************************************************* -bool TMoverParameters::BatterySwitch( bool State, range_t const Notify ) +bool TMoverParameters::BatterySwitch(bool State, range_t const Notify) { - auto const initialstate { Battery }; + auto const initialstate{Battery}; - // Ra: ukrotnienie załączania baterii jest jakąś fikcją... - if( BatteryStart == start_t::manual ) { - Battery = State; - } + // Ra: ukrotnienie załączania baterii jest jakąś fikcją... + if (BatteryStart == start_t::manual) + { + Battery = State; + } - //switching batteries does not require activation - if( Notify != range_t::local ) { - SendCtrlToNext( - "BatterySwitch", - ( State ? 1 : 0 ), - 1, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - SendCtrlToNext( - "BatterySwitch", - (State ? 1 : 0), - -1, - (Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control)); - } + // switching batteries does not require activation + if (Notify != range_t::local) + { + SendCtrlToNext("BatterySwitch", (State ? 1 : 0), 1, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + SendCtrlToNext("BatterySwitch", (State ? 1 : 0), -1, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( Battery != initialstate ); + return (Battery != initialstate); } // ************************************************************************************************* @@ -3135,15 +3180,15 @@ bool TMoverParameters::BatterySwitch( bool State, range_t const Notify ) // ************************************************************************************************* bool TMoverParameters::EpFuseSwitch(bool State) { - if (EpFuse != State) - { - EpFuse = State; - return true; - } - else - return false; - // if (EpFuse == true) SendCtrlToNext("EpFuseSwitch", 1, CabActive) - // else SendCtrlToNext("EpFuseSwitch", 0, CabActive); + if (EpFuse != State) + { + EpFuse = State; + return true; + } + else + return false; + // if (EpFuse == true) SendCtrlToNext("EpFuseSwitch", 1, CabActive) + // else SendCtrlToNext("EpFuseSwitch", 0, CabActive); } // ************************************************************************************************* @@ -3152,7 +3197,7 @@ bool TMoverParameters::EpFuseSwitch(bool State) // ************************************************************************************************* bool TMoverParameters::SpringBrakeActivate(bool State) { - if ( Power24vIsAvailable || Power110vIsAvailable ) + if (Power24vIsAvailable || Power110vIsAvailable) { SendCtrlToNext("SpringBrakeActivate", int(State), CabActive, SpringBrake.MultiTractionCoupler); @@ -3178,7 +3223,6 @@ bool TMoverParameters::SpringBrakeShutOff(bool State) } else return false; - } // ************************************************************************************************* @@ -3194,7 +3238,6 @@ bool TMoverParameters::SpringBrakeRelease() } else return false; - } // ************************************************************************************************* @@ -3203,38 +3246,39 @@ bool TMoverParameters::SpringBrakeRelease() // ************************************************************************************************* bool TMoverParameters::DirectionBackward(void) { - if( false == EIMDirectionChangeAllow() ) { return false; } + if (false == EIMDirectionChangeAllow()) + { + return false; + } - if ((DirActive == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor)) - if (MinCurrentSwitch(false)) - { - return true; - } - if ((MainCtrlPosNo > 0) - && (DirActive > -1) - && ( (CabActive != 0) || ( (InactiveCabFlag & activation::neutraldirection) == 0) ) ) - { - if (EngineType == TEngineType::WheelsDriven) - --CabActive; - // else - --DirActive; - DirAbsolute = DirActive * CabActive; - SendCtrlToNext("Direction", DirActive, CabActive); - return true; - } + if ((DirActive == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor)) + if (MinCurrentSwitch(false)) + { + return true; + } + if ((MainCtrlPosNo > 0) && (DirActive > -1) && ((CabActive != 0) || ((InactiveCabFlag & activation::neutraldirection) == 0))) + { + if (EngineType == TEngineType::WheelsDriven) + --CabActive; + // else + --DirActive; + DirAbsolute = DirActive * CabActive; + SendCtrlToNext("Direction", DirActive, CabActive); + return true; + } - return false; + return false; } bool TMoverParameters::EIMDirectionChangeAllow(void) const { - bool OK = false; -/* - // NOTE: disabled while eimic variables aren't immediately synced with master controller changes inside ai module - OK = (EngineType != TEngineType::ElectricInductionMotor || ((eimic <= 0) && (eimic_real <= 0) && (Vel < 0.1))); -*/ - OK = ( MainCtrlPos <= MainCtrlMaxDirChangePos ); - return OK; + bool OK = false; + /* + // NOTE: disabled while eimic variables aren't immediately synced with master controller changes inside ai module + OK = (EngineType != TEngineType::ElectricInductionMotor || ((eimic <= 0) && (eimic_real <= 0) && (Vel < 0.1))); + */ + OK = (MainCtrlPos <= MainCtrlMaxDirChangePos); + return OK; } // ************************************************************************************************* @@ -3243,569 +3287,511 @@ bool TMoverParameters::EIMDirectionChangeAllow(void) const // ************************************************************************************************* bool TMoverParameters::AntiSlippingButton(void) { - // NOTE: disabled the sandbox part, it's already controlled by another part of the AI routine - return (AntiSlippingBrake() /*|| Sandbox(true)*/); + // NOTE: disabled the sandbox part, it's already controlled by another part of the AI routine + return (AntiSlippingBrake() /*|| Sandbox(true)*/); } // water pump breaker state toggle -bool TMoverParameters::WaterPumpBreakerSwitch( bool State, range_t const Notify ) { -/* - if( FuelPump.start_type == start::automatic ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } -*/ - bool const initialstate { WaterPump.breaker }; +bool TMoverParameters::WaterPumpBreakerSwitch(bool State, range_t const Notify) +{ + /* + if( FuelPump.start_type == start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + return false; + } + */ + bool const initialstate{WaterPump.breaker}; - WaterPump.breaker = State; + WaterPump.breaker = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "WaterPumpBreakerSwitch", - ( WaterPump.breaker ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("WaterPumpBreakerSwitch", (WaterPump.breaker ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( WaterPump.breaker != initialstate ); + return (WaterPump.breaker != initialstate); } // water pump state toggle -bool TMoverParameters::WaterPumpSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::WaterPumpSwitch(bool State, range_t const Notify) +{ - if( WaterPump.start_type == start_t::battery ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } + if (WaterPump.start_type == start_t::battery) + { + // automatic fuel pump ignores 'manual' state commands + return false; + } - bool const initialstate { WaterPump.is_enabled }; + bool const initialstate{WaterPump.is_enabled}; - WaterPump.is_enabled = State; + WaterPump.is_enabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "WaterPumpSwitch", - ( WaterPump.is_enabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("WaterPumpSwitch", (WaterPump.is_enabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( WaterPump.is_enabled != initialstate ); + return (WaterPump.is_enabled != initialstate); } // water pump state toggle -bool TMoverParameters::WaterPumpSwitchOff( bool State, range_t const Notify ) { +bool TMoverParameters::WaterPumpSwitchOff(bool State, range_t const Notify) +{ - if( WaterPump.start_type == start_t::battery ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } + if (WaterPump.start_type == start_t::battery) + { + // automatic fuel pump ignores 'manual' state commands + return false; + } - bool const initialstate { WaterPump.is_disabled }; + bool const initialstate{WaterPump.is_disabled}; - WaterPump.is_disabled = State; + WaterPump.is_disabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "WaterPumpSwitchOff", - ( WaterPump.is_disabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("WaterPumpSwitchOff", (WaterPump.is_disabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( WaterPump.is_disabled != initialstate ); + return (WaterPump.is_disabled != initialstate); } // water heater breaker state toggle -bool TMoverParameters::WaterHeaterBreakerSwitch( bool State, range_t const Notify ) { -/* - if( FuelPump.start_type == start::automatic ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } -*/ - bool const initialstate { WaterHeater.breaker }; +bool TMoverParameters::WaterHeaterBreakerSwitch(bool State, range_t const Notify) +{ + /* + if( FuelPump.start_type == start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + return false; + } + */ + bool const initialstate{WaterHeater.breaker}; - WaterHeater.breaker = State; + WaterHeater.breaker = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "WaterHeaterBreakerSwitch", - ( WaterHeater.breaker ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("WaterHeaterBreakerSwitch", (WaterHeater.breaker ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( WaterHeater.breaker != initialstate ); + return (WaterHeater.breaker != initialstate); } // water heater state toggle -bool TMoverParameters::WaterHeaterSwitch( bool State, range_t const Notify ) { -/* - if( FuelPump.start_type == start::automatic ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } -*/ - bool const initialstate { WaterHeater.is_enabled }; +bool TMoverParameters::WaterHeaterSwitch(bool State, range_t const Notify) +{ + /* + if( FuelPump.start_type == start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + return false; + } + */ + bool const initialstate{WaterHeater.is_enabled}; - WaterHeater.is_enabled = State; + WaterHeater.is_enabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "WaterHeaterSwitch", - ( WaterHeater.is_enabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("WaterHeaterSwitch", (WaterHeater.is_enabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( WaterHeater.is_enabled != initialstate ); + return (WaterHeater.is_enabled != initialstate); } // water circuits link state toggle -bool TMoverParameters::WaterCircuitsLinkSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::WaterCircuitsLinkSwitch(bool State, range_t const Notify) +{ - if( false == dizel_heat.auxiliary_water_circuit ) { - // can't link the circuits if the vehicle only has one - return false; - } + if (false == dizel_heat.auxiliary_water_circuit) + { + // can't link the circuits if the vehicle only has one + return false; + } - bool const initialstate { WaterCircuitsLink }; + bool const initialstate{WaterCircuitsLink}; - WaterCircuitsLink = State; + WaterCircuitsLink = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "WaterCircuitsLinkSwitch", - ( WaterCircuitsLink ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("WaterCircuitsLinkSwitch", (WaterCircuitsLink ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( WaterCircuitsLink != initialstate ); + return (WaterCircuitsLink != initialstate); } // fuel pump state toggle -bool TMoverParameters::FuelPumpSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::FuelPumpSwitch(bool State, range_t const Notify) +{ - if( FuelPump.start_type == start_t::automatic ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } + if (FuelPump.start_type == start_t::automatic) + { + // automatic fuel pump ignores 'manual' state commands + return false; + } - bool const initialstate { FuelPump.is_enabled }; + bool const initialstate{FuelPump.is_enabled}; - FuelPump.is_enabled = State; + FuelPump.is_enabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "FuelPumpSwitch", - ( FuelPump.is_enabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("FuelPumpSwitch", (FuelPump.is_enabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( FuelPump.is_enabled != initialstate ); + return (FuelPump.is_enabled != initialstate); } -bool TMoverParameters::FuelPumpSwitchOff( bool State, range_t const Notify ) { +bool TMoverParameters::FuelPumpSwitchOff(bool State, range_t const Notify) +{ - if( FuelPump.start_type == start_t::automatic ) { - // automatic fuel pump ignores 'manual' state commands - return false; - } + if (FuelPump.start_type == start_t::automatic) + { + // automatic fuel pump ignores 'manual' state commands + return false; + } - bool const initialstate { FuelPump.is_disabled }; + bool const initialstate{FuelPump.is_disabled}; - FuelPump.is_disabled = State; + FuelPump.is_disabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "FuelPumpSwitchOff", - ( FuelPump.is_disabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("FuelPumpSwitchOff", (FuelPump.is_disabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( FuelPump.is_disabled != initialstate ); + return (FuelPump.is_disabled != initialstate); } // oil pump state toggle -bool TMoverParameters::OilPumpSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::OilPumpSwitch(bool State, range_t const Notify) +{ - if( OilPump.start_type == start_t::automatic ) { - // automatic pump ignores 'manual' state commands - return false; - } + if (OilPump.start_type == start_t::automatic) + { + // automatic pump ignores 'manual' state commands + return false; + } - bool const initialstate { OilPump.is_enabled }; + bool const initialstate{OilPump.is_enabled}; - OilPump.is_enabled = State; + OilPump.is_enabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "OilPumpSwitch", - ( OilPump.is_enabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("OilPumpSwitch", (OilPump.is_enabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( OilPump.is_enabled != initialstate ); + return (OilPump.is_enabled != initialstate); } -bool TMoverParameters::OilPumpSwitchOff( bool State, range_t const Notify ) { +bool TMoverParameters::OilPumpSwitchOff(bool State, range_t const Notify) +{ - if( OilPump.start_type == start_t::automatic ) { - // automatic pump ignores 'manual' state commands - return false; - } + if (OilPump.start_type == start_t::automatic) + { + // automatic pump ignores 'manual' state commands + return false; + } - bool const initialstate { OilPump.is_disabled }; + bool const initialstate{OilPump.is_disabled}; - OilPump.is_disabled = State; + OilPump.is_disabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "OilPumpSwitchOff", - ( OilPump.is_disabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("OilPumpSwitchOff", (OilPump.is_disabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( OilPump.is_disabled != initialstate ); + return (OilPump.is_disabled != initialstate); } -bool TMoverParameters::MotorBlowersSwitch( bool State, end const Side, range_t const Notify ) { +bool TMoverParameters::MotorBlowersSwitch(bool State, end const Side, range_t const Notify) +{ - auto &fan { MotorBlowers[ Side ] }; + auto &fan{MotorBlowers[Side]}; - if( ( fan.start_type != start_t::manual ) - && ( fan.start_type != start_t::manualwithautofallback ) ) { - // automatic device ignores 'manual' state commands - return false; - } + if ((fan.start_type != start_t::manual) && (fan.start_type != start_t::manualwithautofallback)) + { + // automatic device ignores 'manual' state commands + return false; + } - bool const initialstate { fan.is_enabled }; + bool const initialstate{fan.is_enabled}; - fan.is_enabled = State; + fan.is_enabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - ( Side == end::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch" ), - ( fan.is_enabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext((Side == end::front ? "MotorBlowersFrontSwitch" : "MotorBlowersRearSwitch"), (fan.is_enabled ? 1 : 0), CabActive, + (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( fan.is_enabled != initialstate ); + return (fan.is_enabled != initialstate); } -bool TMoverParameters::MotorBlowersSwitchOff( bool State, end const Side, range_t const Notify ) { +bool TMoverParameters::MotorBlowersSwitchOff(bool State, end const Side, range_t const Notify) +{ - auto &fan { MotorBlowers[ Side ] }; + auto &fan{MotorBlowers[Side]}; - if( ( fan.start_type != start_t::manual ) - && ( fan.start_type != start_t::manualwithautofallback ) ) { - // automatic device ignores 'manual' state commands - return false; - } + if ((fan.start_type != start_t::manual) && (fan.start_type != start_t::manualwithautofallback)) + { + // automatic device ignores 'manual' state commands + return false; + } - bool const initialstate { fan.is_disabled }; + bool const initialstate{fan.is_disabled}; - fan.is_disabled = State; + fan.is_disabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - ( Side == end::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff" ), - ( fan.is_disabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext((Side == end::front ? "MotorBlowersFrontSwitchOff" : "MotorBlowersRearSwitchOff"), (fan.is_disabled ? 1 : 0), CabActive, + (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( fan.is_disabled != initialstate ); + return (fan.is_disabled != initialstate); } -bool TMoverParameters::CompartmentLightsSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::CompartmentLightsSwitch(bool State, range_t const Notify) +{ - if( CompartmentLights.start_type == start_t::automatic ) { - // automatic lights ignore 'manual' state commands - return false; - } + if (CompartmentLights.start_type == start_t::automatic) + { + // automatic lights ignore 'manual' state commands + return false; + } - bool const initialstate { CompartmentLights.is_enabled }; + bool const initialstate{CompartmentLights.is_enabled}; - CompartmentLights.is_enabled = State; + CompartmentLights.is_enabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "CompartmentLightsSwitch", - ( CompartmentLights.is_enabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("CompartmentLightsSwitch", (CompartmentLights.is_enabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( CompartmentLights.is_enabled != initialstate ); + return (CompartmentLights.is_enabled != initialstate); } // water pump state toggle -bool TMoverParameters::CompartmentLightsSwitchOff( bool State, range_t const Notify ) { +bool TMoverParameters::CompartmentLightsSwitchOff(bool State, range_t const Notify) +{ - if( CompartmentLights.start_type == start_t::automatic ) { - // automatic lights ignore 'manual' state commands - return false; - } + if (CompartmentLights.start_type == start_t::automatic) + { + // automatic lights ignore 'manual' state commands + return false; + } - bool const initialstate { CompartmentLights.is_disabled }; + bool const initialstate{CompartmentLights.is_disabled}; - CompartmentLights.is_disabled = State; + CompartmentLights.is_disabled = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "CompartmentLightsSwitchOff", - ( CompartmentLights.is_disabled ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("CompartmentLightsSwitchOff", (CompartmentLights.is_disabled ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( CompartmentLights.is_disabled != initialstate ); + return (CompartmentLights.is_disabled != initialstate); } // ************************************************************************************************* // Q: 20160713 // włączenie / wyłączenie obwodu głownego // ************************************************************************************************* -bool TMoverParameters::MainSwitch( bool const State, range_t const Notify ) { +bool TMoverParameters::MainSwitch(bool const State, range_t const Notify) +{ - bool const initialstate { Mains || dizel_startup }; + bool const initialstate{Mains || dizel_startup}; - MainSwitch_( State ); + MainSwitch_(State); - if( Notify != range_t::local ) { - // pass the command to other vehicles - // TBD: pass the requested state, or the actual state? - SendCtrlToNext( - "MainSwitch", - ( State ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + // pass the command to other vehicles + // TBD: pass the requested state, or the actual state? + SendCtrlToNext("MainSwitch", (State ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( ( Mains || dizel_startup ) != initialstate ); + return ((Mains || dizel_startup) != initialstate); } -void TMoverParameters::MainSwitch_( bool const State ) { +void TMoverParameters::MainSwitch_(bool const State) +{ - if( ( Mains == State ) - || ( MainCtrlPosNo == 0 ) ) { - // nothing to do - return; - } + if ((Mains == State) || (MainCtrlPosNo == 0)) + { + // nothing to do + return; + } - bool const initialstate { Mains }; + bool const initialstate{Mains}; - if( ( false == State ) - || ( true == MainSwitchCheck() ) ) { + if ((false == State) || (true == MainSwitchCheck())) + { - if( true == State ) { - // switch on - if( ( EngineType == TEngineType::DieselEngine ) - || ( EngineType == TEngineType::DieselElectric ) ) { - // launch diesel engine startup procedure - dizel_startup = true; - } - else { - // additional check, as vehicles without pantographs won't fail relay checks earlier - Mains = true; - } - } - else { - Mains = false; - // potentially knock out the pumps if their switch doesn't force them on - WaterPump.is_active &= WaterPump.is_enabled; - FuelPump.is_active &= FuelPump.is_enabled; - } + if (true == State) + { + // switch on + if ((EngineType == TEngineType::DieselEngine) || (EngineType == TEngineType::DieselElectric)) + { + // launch diesel engine startup procedure + dizel_startup = true; + } + else + { + // additional check, as vehicles without pantographs won't fail relay checks earlier + Mains = true; + } + } + else + { + Mains = false; + // potentially knock out the pumps if their switch doesn't force them on + WaterPump.is_active &= WaterPump.is_enabled; + FuelPump.is_active &= FuelPump.is_enabled; + } - if( Mains != initialstate ) { - LastSwitchingTime = 0; - } - } + if (Mains != initialstate) + { + LastSwitchingTime = 0; + } + } } -bool TMoverParameters::MainSwitchCheck() const { +bool TMoverParameters::MainSwitchCheck() const +{ - // prevent the switch from working if there's no power - // TODO: consider whether it makes sense for diesel engines and such - bool powerisavailable { true }; + // prevent the switch from working if there's no power + // TODO: consider whether it makes sense for diesel engines and such + bool powerisavailable{true}; - switch( EngineType ) { - case TEngineType::DieselElectric: - case TEngineType::DieselEngine: - case TEngineType::Dumb: { - powerisavailable = Power24vIsAvailable; - break; - } - case TEngineType::ElectricSeriesMotor: - case TEngineType::ElectricInductionMotor: { - // TODO: check whether we can simplify this check and skip the outer EngineType switch - powerisavailable = ( EnginePowerSourceVoltage() > 0.5 * EnginePowerSource.MaxVoltage ); - break; - } - default: { - break; - } - } + switch (EngineType) + { + case TEngineType::DieselElectric: + case TEngineType::DieselEngine: + case TEngineType::Dumb: + { + powerisavailable = Power24vIsAvailable; + break; + } + case TEngineType::ElectricSeriesMotor: + case TEngineType::ElectricInductionMotor: + { + // TODO: check whether we can simplify this check and skip the outer EngineType switch + powerisavailable = (EnginePowerSourceVoltage() > 0.5 * EnginePowerSource.MaxVoltage); + break; + } + default: + { + break; + } + } - return ( - ( powerisavailable ) - && ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) ) - && ( MainsInitTimeCountdown <= 0.0 ) - && ( ( ConvOvldFlag == false ) || ( ConverterOverloadRelayOffWhenMainIsOff ) ) - && ( true == GroundRelay ) - && ( true == NoVoltRelay ) - && ( true == OvervoltageRelay ) - && ( LastSwitchingTime > CtrlDelay ) - && ( HasCamshaft ? IsMainCtrlActualNoPowerPos() : ( LineBreakerClosesOnlyAtNoPowerPos ? IsMainCtrlNoPowerPos() : true ) ) - && ( false == TestFlag( DamageFlag, dtrain_out ) ) - && ( false == TestFlag( EngDmgFlag, 1 ) ) ); + return ((powerisavailable) && ((ScndCtrlPos == 0) || (EngineType == TEngineType::ElectricInductionMotor)) && (MainsInitTimeCountdown <= 0.0) && + ((ConvOvldFlag == false) || (ConverterOverloadRelayOffWhenMainIsOff)) && (true == GroundRelay) && (true == NoVoltRelay) && (true == OvervoltageRelay) && (LastSwitchingTime > CtrlDelay) && + (HasCamshaft ? IsMainCtrlActualNoPowerPos() : (LineBreakerClosesOnlyAtNoPowerPos ? IsMainCtrlNoPowerPos() : true)) && (false == TestFlag(DamageFlag, dtrain_out)) && + (false == TestFlag(EngDmgFlag, 1))); } // ************************************************************************************************* // Q: 20160713 // włączenie / wyłączenie przetwornicy // ************************************************************************************************* -bool TMoverParameters::ConverterSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::ConverterSwitch(bool State, range_t const Notify) +{ - auto const initialstate { ConverterAllow }; + auto const initialstate{ConverterAllow}; - if( ConverterStart == start_t::manual ) { - ConverterAllow = State; - } + if (ConverterStart == start_t::manual) + { + ConverterAllow = State; + } - if( Notify != range_t::local ) { - SendCtrlToNext( - "ConverterSwitch", - ( State ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("ConverterSwitch", (State ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( ConverterAllow != initialstate ); + return (ConverterAllow != initialstate); } // ************************************************************************************************* // Q: 20160713 // włączenie / wyłączenie sprężarki // ************************************************************************************************* -bool TMoverParameters::CompressorSwitch( bool State, range_t const Notify ) { +bool TMoverParameters::CompressorSwitch(bool State, range_t const Notify) +{ - if( CompressorStart != start_t::manual ) { - // only pay attention if the compressor can be controlled manually - return false; - } + if (CompressorStart != start_t::manual) + { + // only pay attention if the compressor can be controlled manually + return false; + } - auto const initialstate { CompressorAllow }; + auto const initialstate{CompressorAllow}; - if( ( VeselVolume > 0.0 ) - && ( CompressorSpeed > 0.0 ) ) { - CompressorAllow = State; - } + if ((VeselVolume > 0.0) && (CompressorSpeed > 0.0)) + { + CompressorAllow = State; + } - if( Notify != range_t::local ) { - SendCtrlToNext( - "CompressorSwitch", - ( State ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("CompressorSwitch", (State ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( CompressorAllow != initialstate ); + return (CompressorAllow != initialstate); } -bool TMoverParameters::ChangeCompressorPreset( int const State, range_t const Notify ) { +bool TMoverParameters::ChangeCompressorPreset(int const State, range_t const Notify) +{ - auto const initialstate { CompressorListPos }; + auto const initialstate{CompressorListPos}; - CompressorListPos = clamp( State, 0, CompressorListPosNo ); + CompressorListPos = clamp(State, 0, CompressorListPosNo); - if( Notify != range_t::local ) { - SendCtrlToNext( - "CompressorPreset", State, CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("CompressorPreset", State, CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( CompressorListPos != initialstate ); + return (CompressorListPos != initialstate); } -bool TMoverParameters::HeatingSwitch( bool const State, range_t const Notify ) { +bool TMoverParameters::HeatingSwitch(bool const State, range_t const Notify) +{ - bool const initialstate { HeatingAllow }; + bool const initialstate{HeatingAllow}; - HeatingSwitch_( State ); + HeatingSwitch_(State); - if( Notify != range_t::local ) { - // pass the command to other vehicles - // TBD: pass the requested state, or the actual state? - SendCtrlToNext( - "HeatingSwitch", - ( State ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + // pass the command to other vehicles + // TBD: pass the requested state, or the actual state? + SendCtrlToNext("HeatingSwitch", (State ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( HeatingAllow != initialstate ); + return (HeatingAllow != initialstate); } -void TMoverParameters::HeatingSwitch_( bool const State ) { +void TMoverParameters::HeatingSwitch_(bool const State) +{ - // TBD, TODO: activation dependencies? - HeatingAllow = State; + // TBD, TODO: activation dependencies? + HeatingAllow = State; } // returns voltage of defined main engine power source -double TMoverParameters::EnginePowerSourceVoltage() const { +double TMoverParameters::EnginePowerSourceVoltage() const +{ - return ( - EnginePowerSource.SourceType == TPowerSource::CurrentCollector ? std::max( GetTrainsetHighVoltage(), PantographVoltage ) : - EnginePowerSource.SourceType == TPowerSource::Accumulator ? Power24vVoltage : - 0.0 ); + return (EnginePowerSource.SourceType == TPowerSource::CurrentCollector ? std::max(GetTrainsetHighVoltage(), PantographVoltage) : + EnginePowerSource.SourceType == TPowerSource::Accumulator ? Power24vVoltage : + 0.0); } // ************************************************************************************************* @@ -3814,25 +3800,25 @@ double TMoverParameters::EnginePowerSourceVoltage() const { // ************************************************************************************************* bool TMoverParameters::IncBrakeLevelOld(void) { - bool IBLO = false; + bool IBLO = false; - if (BrakeCtrlPosNo > 0) - { - if (BrakeCtrlPos < BrakeCtrlPosNo) - { - ++BrakeCtrlPos; - // youBy: EP po nowemu - IBLO = true; - if ((BrakePressureActual.PipePressureVal < 0) && - (BrakePressureTable[BrakeCtrlPos - 1].PipePressureVal > 0)) - LimPipePress = PipePress; - } - else { - IBLO = false; - } - } + if (BrakeCtrlPosNo > 0) + { + if (BrakeCtrlPos < BrakeCtrlPosNo) + { + ++BrakeCtrlPos; + // youBy: EP po nowemu + IBLO = true; + if ((BrakePressureActual.PipePressureVal < 0) && (BrakePressureTable[BrakeCtrlPos - 1].PipePressureVal > 0)) + LimPipePress = PipePress; + } + else + { + IBLO = false; + } + } - return IBLO; + return IBLO; } // ***************************************************************************** @@ -3841,24 +3827,24 @@ bool TMoverParameters::IncBrakeLevelOld(void) // ***************************************************************************** bool TMoverParameters::DecBrakeLevelOld(void) { - bool DBLO = false; + bool DBLO = false; - if (BrakeCtrlPosNo > 0) - { - if (BrakeCtrlPos > ( ( BrakeHandle == TBrakeHandle::FV4a ) ? -2 : -1 ) ) - { - --BrakeCtrlPos; - // youBy: EP po nowemu - DBLO = true; -// if ((BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0) && -// (BrakePressureTable[BrakeCtrlPos+1].PipePressureVal > 0)) -// LimPipePress=PipePress; - } - else - DBLO = false; - } + if (BrakeCtrlPosNo > 0) + { + if (BrakeCtrlPos > ((BrakeHandle == TBrakeHandle::FV4a) ? -2 : -1)) + { + --BrakeCtrlPos; + // youBy: EP po nowemu + DBLO = true; + // if ((BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0) && + // (BrakePressureTable[BrakeCtrlPos+1].PipePressureVal > 0)) + // LimPipePress=PipePress; + } + else + DBLO = false; + } - return DBLO; + return DBLO; } // ************************************************************************************************* @@ -3867,16 +3853,16 @@ bool TMoverParameters::DecBrakeLevelOld(void) // ************************************************************************************************* bool TMoverParameters::IncLocalBrakeLevel(float const CtrlSpeed) { - bool IBL; - if ((LocalBrakePosA < 1.0) /*and (BrakeCtrlPos<1)*/) - { - LocalBrakePosA = std::min( 1.0, LocalBrakePosA + CtrlSpeed / LocalBrakePosNo ); - IBL = true; - } - else - IBL = false; + bool IBL; + if ((LocalBrakePosA < 1.0) /*and (BrakeCtrlPos<1)*/) + { + LocalBrakePosA = std::min(1.0, LocalBrakePosA + CtrlSpeed / LocalBrakePosNo); + IBL = true; + } + else + IBL = false; - return IBL; + return IBL; } // ************************************************************************************************* @@ -3885,16 +3871,16 @@ bool TMoverParameters::IncLocalBrakeLevel(float const CtrlSpeed) // ************************************************************************************************* bool TMoverParameters::DecLocalBrakeLevel(float const CtrlSpeed) { - bool DBL; - if (LocalBrakePosA > 0) - { - LocalBrakePosA = std::max( 0.0, LocalBrakePosA - CtrlSpeed / LocalBrakePosNo ); - DBL = true; - } - else - DBL = false; + bool DBL; + if (LocalBrakePosA > 0) + { + LocalBrakePosA = std::max(0.0, LocalBrakePosA - CtrlSpeed / LocalBrakePosNo); + DBL = true; + } + else + DBL = false; - return DBL; + return DBL; } // ************************************************************************************************* @@ -3903,20 +3889,20 @@ bool TMoverParameters::DecLocalBrakeLevel(float const CtrlSpeed) // ************************************************************************************************* bool TMoverParameters::IncManualBrakeLevel(int CtrlSpeed) { - bool IMBL; - if (ManualBrakePos < ManualBrakePosNo) /*and (BrakeCtrlPos<1)*/ - { - while ((ManualBrakePos < ManualBrakePosNo) && (CtrlSpeed > 0)) - { - ManualBrakePos++; - CtrlSpeed--; - } - IMBL = true; - } - else - IMBL = false; + bool IMBL; + if (ManualBrakePos < ManualBrakePosNo) /*and (BrakeCtrlPos<1)*/ + { + while ((ManualBrakePos < ManualBrakePosNo) && (CtrlSpeed > 0)) + { + ManualBrakePos++; + CtrlSpeed--; + } + IMBL = true; + } + else + IMBL = false; - return IMBL; + return IMBL; } // ************************************************************************************************* @@ -3925,19 +3911,19 @@ bool TMoverParameters::IncManualBrakeLevel(int CtrlSpeed) // ************************************************************************************************* bool TMoverParameters::DecManualBrakeLevel(int CtrlSpeed) { - bool DMBL; - if (ManualBrakePos > 0) - { - while ((CtrlSpeed > 0) && (ManualBrakePos > 0)) - { - ManualBrakePos--; - CtrlSpeed--; - } - DMBL = true; - } - else - DMBL = false; - return DMBL; + bool DMBL; + if (ManualBrakePos > 0) + { + while ((CtrlSpeed > 0) && (ManualBrakePos > 0)) + { + ManualBrakePos--; + CtrlSpeed--; + } + DMBL = true; + } + else + DMBL = false; + return DMBL; } // ************************************************************************************************* @@ -3946,26 +3932,26 @@ bool TMoverParameters::DecManualBrakeLevel(int CtrlSpeed) // ************************************************************************************************* bool TMoverParameters::DynamicBrakeSwitch(bool Switch) { - bool DBS; + bool DBS; - if ((DynamicBrakeType == dbrake_switch) && (IsMainCtrlNoPowerPos())) - { - DynamicBrakeFlag = Switch; - DBS = true; - for (int b = 0; b < 2; b++) - // with Couplers[b] do - if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) - Couplers[b].Connected->DynamicBrakeFlag = Switch; - // end; - // if (DynamicBrakeType=dbrake_passive) and (TrainType=dt_ET42) then - // begin - // DynamicBrakeFlag:=false; - // DynamicBrakeSwitch:=false; - } - else - DBS = false; + if ((DynamicBrakeType == dbrake_switch) && (IsMainCtrlNoPowerPos())) + { + DynamicBrakeFlag = Switch; + DBS = true; + for (int b = 0; b < 2; b++) + // with Couplers[b] do + if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) + Couplers[b].Connected->DynamicBrakeFlag = Switch; + // end; + // if (DynamicBrakeType=dbrake_passive) and (TrainType=dt_ET42) then + // begin + // DynamicBrakeFlag:=false; + // DynamicBrakeSwitch:=false; + } + else + DBS = false; - return DBS; + return DBS; } // ************************************************************************************************* @@ -3974,42 +3960,47 @@ bool TMoverParameters::DynamicBrakeSwitch(bool Switch) // ************************************************************************************************* bool TMoverParameters::RadiostopSwitch(bool Switch) { - bool EBS; - if( ( BrakeSystem != TBrakeSystem::Individual ) - && ( BrakeCtrlPosNo > 0 ) ) { + bool EBS; + if ((BrakeSystem != TBrakeSystem::Individual) && (BrakeCtrlPosNo > 0)) + { - if( ( true == Switch ) - && ( false == RadioStopFlag ) ) { - RadioStopFlag = Switch; - EBS = true; - } - else { - if( ( Switch == false ) - && ( std::abs( V ) < 0.1 ) ) { - // odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu - RadioStopFlag = Switch; - EBS = true; - } - else { - EBS = false; - } - } - } - else { - // nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp. - EBS = false; - } + if ((true == Switch) && (false == RadioStopFlag)) + { + RadioStopFlag = Switch; + EBS = true; + } + else + { + if ((Switch == false) && (std::abs(V) < 0.1)) + { + // odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu + RadioStopFlag = Switch; + EBS = true; + } + else + { + EBS = false; + } + } + } + else + { + // nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp. + EBS = false; + } - return EBS; + return EBS; } -bool TMoverParameters::AlarmChainSwitch( bool const State ) { +bool TMoverParameters::AlarmChainSwitch(bool const State) +{ - if( AlarmChainFlag != State ) { - // simple routine for the time being - AlarmChainFlag = State; + if (AlarmChainFlag != State) + { + // simple routine for the time being + AlarmChainFlag = State; return true; - } + } return false; } @@ -4019,14 +4010,14 @@ bool TMoverParameters::AlarmChainSwitch( bool const State ) { // ************************************************************************************************* bool TMoverParameters::AntiSlippingBrake(void) { - bool ASB = false; // Ra: przeniesione z końca - if (ASBType == 1) - { - ASB = true; // SPKS!! - Hamulec->ASB(1); - BrakeSlippingTimer = 0; - } - return ASB; + bool ASB = false; // Ra: przeniesione z końca + if (ASBType == 1) + { + ASB = true; // SPKS!! + Hamulec->ASB(1); + BrakeSlippingTimer = 0; + } + return ASB; } // ************************************************************************************************* @@ -4035,19 +4026,22 @@ bool TMoverParameters::AntiSlippingBrake(void) // ************************************************************************************************* bool TMoverParameters::BrakeReleaser(int state) { - bool OK = true; //false tylko jeśli nie uda się wysłać, GF 20161124 - if( state != 0 ) { - // additional limitations imposed by pressure switch - if( ( false == ControlPressureSwitch ) || ( false == ReleaserEnabledOnlyAtNoPowerPos ) || ( true == IsMainCtrlNoPowerPos() ) ) { - Hamulec->Releaser( state ); - } - } - else { - Hamulec->Releaser( state ); - } - if (CabActive != 0) // rekurencyjne wysłanie do następnego - OK = SendCtrlToNext("BrakeReleaser", state, CabActive); - return OK; + bool OK = true; // false tylko jeśli nie uda się wysłać, GF 20161124 + if (state != 0) + { + // additional limitations imposed by pressure switch + if ((false == ControlPressureSwitch) || (false == ReleaserEnabledOnlyAtNoPowerPos) || (true == IsMainCtrlNoPowerPos())) + { + Hamulec->Releaser(state); + } + } + else + { + Hamulec->Releaser(state); + } + if (CabActive != 0) // rekurencyjne wysłanie do następnego + OK = SendCtrlToNext("BrakeReleaser", state, CabActive); + return OK; } // ************************************************************************************************* @@ -4056,11 +4050,13 @@ bool TMoverParameters::BrakeReleaser(int state) // ************************************************************************************************* bool TMoverParameters::UniversalBrakeButton(int button, int state) { - bool OK = true; //false tylko jeśli nie uda się wysłać, GF 20161124 + bool OK = true; // false tylko jeśli nie uda się wysłać, GF 20161124 UniversalBrakeButtonActive[button] = state > 0; int flag = 0; - if (Power24vIsAvailable || Power110vIsAvailable) { - for (int i = 0; i < 3; i++) { + if (Power24vIsAvailable || Power110vIsAvailable) + { + for (int i = 0; i < 3; i++) + { flag = flag | (UniversalBrakeButtonActive[i] ? UniversalBrakeButtonFlag[i] : 0); } } @@ -4070,11 +4066,10 @@ bool TMoverParameters::UniversalBrakeButton(int button, int state) LocHandle->SetUniversalFlag(flag); UnlockPipe = (flag & TUniversalBrake::ub_UnlockPipe) > 0; - //if the releaser can be activated by switch - if ( TestFlag ( UniversalBrakeButtonFlag[0] & UniversalBrakeButtonFlag[1] & UniversalBrakeButtonFlag[2], - TUniversalBrake::ub_Release ) ) + // if the releaser can be activated by switch + if (TestFlag(UniversalBrakeButtonFlag[0] & UniversalBrakeButtonFlag[1] & UniversalBrakeButtonFlag[2], TUniversalBrake::ub_Release)) { - BrakeReleaser( TestFlag( flag, TUniversalBrake::ub_Release ) ? 1 : 0 ); + BrakeReleaser(TestFlag(flag, TUniversalBrake::ub_Release) ? 1 : 0); } return OK; } @@ -4085,21 +4080,21 @@ bool TMoverParameters::UniversalBrakeButton(int button, int state) // ************************************************************************************************* bool TMoverParameters::SwitchEPBrake(int state) { - bool OK; + bool OK; - OK = false; - if ((BrakeHandle == TBrakeHandle::St113) && (CabOccupied != 0)) - { - if (state > 0) + OK = false; + if ((BrakeHandle == TBrakeHandle::St113) && (CabOccupied != 0)) + { + if (state > 0) EpForce = Handle->GetEP(); // TODO: przetlumaczyc - else + else EpForce = 0; - Hamulec->SetEPS(EpForce); - SendCtrlToNext("Brake", EpForce, CabActive); - } - // OK:=SetFlag(BrakeStatus,((2*State-1)*b_epused)); - // SendCtrlToNext('Brake',(state*(2*BrakeCtrlPos-1)),CabActive); - return OK; + Hamulec->SetEPS(EpForce); + SendCtrlToNext("Brake", EpForce, CabActive); + } + // OK:=SetFlag(BrakeStatus,((2*State-1)*b_epused)); + // SendCtrlToNext('Brake',(state*(2*BrakeCtrlPos-1)),CabActive); + return OK; } // ************************************************************************************************* @@ -4108,30 +4103,27 @@ bool TMoverParameters::SwitchEPBrake(int state) // ************************************************************************************************* bool TMoverParameters::IncBrakePress(double &brake, double PressLimit, double dp) { - bool IBP; - // if (DynamicBrakeType<>dbrake_switch) and (DynamicBrakeType<>dbrake_none) and - // ((BrakePress>2.0) or (PipePress<3.7{(LowPipePress+0.5)})) then - if ((DynamicBrakeType != dbrake_switch) && (DynamicBrakeType != dbrake_none) && - (BrakePress > 2.0) && - (TrainType != dt_EZT)) // yB radzi nie sprawdzać ciśnienia w przewodzie - // hunter-301211: dla EN57 silnikow nie odlaczamy - { - DynamicBrakeFlag = true; // uruchamianie hamulca ED albo odlaczanie silnikow - if ((DynamicBrakeType == dbrake_automatic) && - (abs(Im) > 60)) // nie napelniaj wiecej, jak na EP09 - dp = 0.0; - } - if (brake + dp < PressLimit) - { - brake = brake + dp; - IBP = true; - } - else - { - IBP = false; - brake = PressLimit; - } - return IBP; + bool IBP; + // if (DynamicBrakeType<>dbrake_switch) and (DynamicBrakeType<>dbrake_none) and + // ((BrakePress>2.0) or (PipePress<3.7{(LowPipePress+0.5)})) then + if ((DynamicBrakeType != dbrake_switch) && (DynamicBrakeType != dbrake_none) && (BrakePress > 2.0) && (TrainType != dt_EZT)) // yB radzi nie sprawdzać ciśnienia w przewodzie + // hunter-301211: dla EN57 silnikow nie odlaczamy + { + DynamicBrakeFlag = true; // uruchamianie hamulca ED albo odlaczanie silnikow + if ((DynamicBrakeType == dbrake_automatic) && (abs(Im) > 60)) // nie napelniaj wiecej, jak na EP09 + dp = 0.0; + } + if (brake + dp < PressLimit) + { + brake = brake + dp; + IBP = true; + } + else + { + IBP = false; + brake = PressLimit; + } + return IBP; } // ************************************************************************************************* @@ -4140,25 +4132,24 @@ bool TMoverParameters::IncBrakePress(double &brake, double PressLimit, double dp // ************************************************************************************************* bool TMoverParameters::DecBrakePress(double &brake, double PressLimit, double dp) { - bool DBP; + bool DBP; - if (brake - dp > PressLimit) - { - brake = brake - dp; - DBP = true; - } - else - { - DBP = false; - brake = PressLimit; - } - // if ((DynamicBrakeType != dbrake_switch) && ((BrakePress < 0.1) && (PipePress > 0.45 - // /*(LowPipePress+0.06)*/ ))) - if ((DynamicBrakeType != dbrake_switch) && - (BrakePress < 0.1)) // yB radzi nie sprawdzać ciśnienia w przewodzie - DynamicBrakeFlag = false; // wylaczanie hamulca ED i/albo zalaczanie silnikow + if (brake - dp > PressLimit) + { + brake = brake - dp; + DBP = true; + } + else + { + DBP = false; + brake = PressLimit; + } + // if ((DynamicBrakeType != dbrake_switch) && ((BrakePress < 0.1) && (PipePress > 0.45 + // /*(LowPipePress+0.06)*/ ))) + if ((DynamicBrakeType != dbrake_switch) && (BrakePress < 0.1)) // yB radzi nie sprawdzać ciśnienia w przewodzie + DynamicBrakeFlag = false; // wylaczanie hamulca ED i/albo zalaczanie silnikow - return DBP; + return DBP; } // ************************************************************************************************* @@ -4167,20 +4158,20 @@ bool TMoverParameters::DecBrakePress(double &brake, double PressLimit, double dp // ************************************************************************************************* bool TMoverParameters::BrakeDelaySwitch(int BDS) { - bool rBDS; + bool rBDS; if (Hamulec->SetBDF(BDS)) - { - BrakeDelayFlag = BDS; - rBDS = true; - Hamulec->SetBrakeStatus( Hamulec->GetBrakeStatus() & ~64 ); - // kopowanie nastawy hamulca do kolejnego czlonu - do przemyślenia - if (CabActive != 0) - SendCtrlToNext("BrakeDelay", BrakeDelayFlag, CabActive); - } - else - rBDS = false; + { + BrakeDelayFlag = BDS; + rBDS = true; + Hamulec->SetBrakeStatus(Hamulec->GetBrakeStatus() & ~64); + // kopowanie nastawy hamulca do kolejnego czlonu - do przemyślenia + if (CabActive != 0) + SendCtrlToNext("BrakeDelay", BrakeDelayFlag, CabActive); + } + else + rBDS = false; - return rBDS; + return rBDS; } // ************************************************************************************************* @@ -4189,22 +4180,22 @@ bool TMoverParameters::BrakeDelaySwitch(int BDS) // ************************************************************************************************* bool TMoverParameters::IncBrakeMult(void) { - bool IBM; + bool IBM; - if ((LoadFlag > 0) && (MBPM < 2) && (LoadFlag < 3)) - { - if ((MaxBrakePress[2] > 0) && (LoadFlag == 1)) - LoadFlag = 2; - else - LoadFlag = 3; - IBM = true; - if (BrakeCylMult[2] > 0) - BrakeCylMult[0] = BrakeCylMult[2]; - } - else - IBM = false; + if ((LoadFlag > 0) && (MBPM < 2) && (LoadFlag < 3)) + { + if ((MaxBrakePress[2] > 0) && (LoadFlag == 1)) + LoadFlag = 2; + else + LoadFlag = 3; + IBM = true; + if (BrakeCylMult[2] > 0) + BrakeCylMult[0] = BrakeCylMult[2]; + } + else + IBM = false; - return IBM; + return IBM; } // ************************************************************************************************* @@ -4213,21 +4204,21 @@ bool TMoverParameters::IncBrakeMult(void) // ************************************************************************************************* bool TMoverParameters::DecBrakeMult(void) { - bool DBM; - if ((LoadFlag > 1) && (MBPM < 2)) - { - if ((MaxBrakePress[2] > 0) && (LoadFlag == 3)) - LoadFlag = 2; - else - LoadFlag = 1; - DBM = true; - if (BrakeCylMult[1] > 0) - BrakeCylMult[0] = BrakeCylMult[1]; - } - else - DBM = false; + bool DBM; + if ((LoadFlag > 1) && (MBPM < 2)) + { + if ((MaxBrakePress[2] > 0) && (LoadFlag == 3)) + LoadFlag = 2; + else + LoadFlag = 1; + DBM = true; + if (BrakeCylMult[1] > 0) + BrakeCylMult[0] = BrakeCylMult[1]; + } + else + DBM = false; - return DBM; + return DBM; } // ************************************************************************************************* @@ -4236,29 +4227,31 @@ bool TMoverParameters::DecBrakeMult(void) // ************************************************************************************************* void TMoverParameters::UpdateBrakePressure(double dt) { - //const double LBDelay = 5.0; // stala czasowa hamulca - //double Rate, Speed, dp, sm; + // const double LBDelay = 5.0; // stala czasowa hamulca + // double Rate, Speed, dp, sm; - dpLocalValve = 0; - dpBrake = 0; + dpLocalValve = 0; + dpBrake = 0; - Hamulec->ForceLeak( dt * AirLeakRate * 0.25 ); // fake air leaks from brake system reservoirs + Hamulec->ForceLeak(dt * AirLeakRate * 0.25); // fake air leaks from brake system reservoirs - BrakePress = Hamulec->GetBCP(); - // BrakePress:=(Hamulec as TEst4).ImplsRes.pa; - Volume = Hamulec->GetBRP(); + BrakePress = Hamulec->GetBCP(); + // BrakePress:=(Hamulec as TEst4).ImplsRes.pa; + Volume = Hamulec->GetBRP(); } // ************************************************************************************************* // Q: 20160712 // Obliczanie pracy sprężarki // ************************************************************************************************* -void TMoverParameters::CompressorCheck(double dt) { +void TMoverParameters::CompressorCheck(double dt) +{ - if( CompressorSpeed == 0.0 ) { - CompressorAllow = false; - return; - } + if (CompressorSpeed == 0.0) + { + CompressorAllow = false; + return; + } if (CabDependentCompressor) { @@ -4274,141 +4267,135 @@ void TMoverParameters::CompressorCheck(double dt) { } } - //EmergencyValve + // EmergencyValve EmergencyValveOpen = (Compressor > (EmergencyValveOpen ? EmergencyValveOff : EmergencyValveOn)); - if (EmergencyValveOpen) { - float dV = PF(0, Compressor, EmergencyValveArea)* dt; + if (EmergencyValveOpen) + { + float dV = PF(0, Compressor, EmergencyValveArea) * dt; CompressedVolume -= dV; } - CompressedVolume = std::max( 0.0, CompressedVolume - dt * AirLeakRate * 0.1 ); // nieszczelności: 0.001=1l/s + CompressedVolume = std::max(0.0, CompressedVolume - dt * AirLeakRate * 0.1); // nieszczelności: 0.001=1l/s - Compressor = CompressedVolume / VeselVolume; + Compressor = CompressedVolume / VeselVolume; - // assorted operational logic - auto const MaxCompressorF { CompressorList[ TCompressorList::cl_MaxFactor ][ CompressorListPos ] * MaxCompressor }; - auto const MinCompressorF { CompressorList[ TCompressorList::cl_MinFactor ][ CompressorListPos ] * MinCompressor }; - auto const CompressorSpeedF { CompressorList[ TCompressorList::cl_SpeedFactor ][ CompressorListPos ] * CompressorSpeed }; - auto const AllowFactor { CompressorList[ TCompressorList::cl_Allow ][ CompressorListPos ] }; - //checking the impact on the compressor allowance - if (AllowFactor > 0.5) { - CompressorAllow = ( AllowFactor > 1.5 ); + // assorted operational logic + auto const MaxCompressorF{CompressorList[TCompressorList::cl_MaxFactor][CompressorListPos] * MaxCompressor}; + auto const MinCompressorF{CompressorList[TCompressorList::cl_MinFactor][CompressorListPos] * MinCompressor}; + auto const CompressorSpeedF{CompressorList[TCompressorList::cl_SpeedFactor][CompressorListPos] * CompressorSpeed}; + auto const AllowFactor{CompressorList[TCompressorList::cl_Allow][CompressorListPos]}; + // checking the impact on the compressor allowance + if (AllowFactor > 0.5) + { + CompressorAllow = (AllowFactor > 1.5); } - switch( CompressorPower ) { - case 2: { - CompressorAllow = ConverterAllow; - break; - } - case 3: { - // HACK: make sure compressor coupled with diesel engine is always ready for work - CompressorStart = start_t::automatic; - break; - } - default: { - break; - } - } + switch (CompressorPower) + { + case 2: + { + CompressorAllow = ConverterAllow; + break; + } + case 3: + { + // HACK: make sure compressor coupled with diesel engine is always ready for work + CompressorStart = start_t::automatic; + break; + } + default: + { + break; + } + } - auto const compressorpower { ( - CompressorPower == 0 ? Mains : - CompressorPower == 3 ? Mains : - Power110vIsAvailable ) }; - // TBD: split CompressorAllow into separate enable/disable flags, inherit compressor from basic_device - auto const compressorenable { - ( CompressorAllowLocal ) - && ( ( CompressorStart == start_t::automatic ) - || ( CompressorAllow ) ) }; - auto const compressordisable { false == compressorenable }; + auto const compressorpower{(CompressorPower == 0 ? Mains : CompressorPower == 3 ? Mains : Power110vIsAvailable)}; + // TBD: split CompressorAllow into separate enable/disable flags, inherit compressor from basic_device + auto const compressorenable{(CompressorAllowLocal) && ((CompressorStart == start_t::automatic) || (CompressorAllow))}; + auto const compressordisable{false == compressorenable}; - auto const pressureistoolow { Compressor < MinCompressorF }; - auto const pressureistoohigh { Compressor > MaxCompressorF }; + auto const pressureistoolow{Compressor < MinCompressorF}; + auto const pressureistoohigh{Compressor > MaxCompressorF}; - // TBD, TODO: break the lock with no low voltage power? - auto const governorlockispresent { MaxCompressorF - MinCompressorF > 0.0001 }; - CompressorGovernorLock = - ( governorlockispresent ) - && ( false == pressureistoolow ) // unlock if pressure drops below minimal threshold - && ( pressureistoohigh || CompressorGovernorLock ); // lock if pressure goes above maximum threshold - // for these multi-unit engines compressors turn off whenever any of them was affected by the governor - // NOTE: this is crude implementation, limited only to adjacent vehicles - // TODO: re-implement when a more elegant/flexible system is in place - auto const coupledgovernorlock { - ( ( Couplers[ end::rear ].Connected != nullptr ) - && ( true == TestFlag( Couplers[ end::rear ].CouplingFlag, coupling::permanent ) ) - && ( Couplers[ end::rear ].Connected->CompressorGovernorLock ) ) - || ( ( Couplers[ end::front ].Connected != nullptr ) - && ( true == TestFlag( Couplers[ end::front ].CouplingFlag, coupling::permanent ) ) - && ( Couplers[ end::front ].Connected->CompressorGovernorLock ) ) }; - auto const governorlock { CompressorGovernorLock || coupledgovernorlock }; + // TBD, TODO: break the lock with no low voltage power? + auto const governorlockispresent{MaxCompressorF - MinCompressorF > 0.0001}; + CompressorGovernorLock = (governorlockispresent) && (false == pressureistoolow) // unlock if pressure drops below minimal threshold + && (pressureistoohigh || CompressorGovernorLock); // lock if pressure goes above maximum threshold + // for these multi-unit engines compressors turn off whenever any of them was affected by the governor + // NOTE: this is crude implementation, limited only to adjacent vehicles + // TODO: re-implement when a more elegant/flexible system is in place + auto const coupledgovernorlock{ + ((Couplers[end::rear].Connected != nullptr) && (true == TestFlag(Couplers[end::rear].CouplingFlag, coupling::permanent)) && (Couplers[end::rear].Connected->CompressorGovernorLock)) || + ((Couplers[end::front].Connected != nullptr) && (true == TestFlag(Couplers[end::front].CouplingFlag, coupling::permanent)) && (Couplers[end::front].Connected->CompressorGovernorLock))}; + auto const governorlock{CompressorGovernorLock || coupledgovernorlock}; - auto const compressorflag { CompressorFlag }; - CompressorFlag = - ( compressorpower ) - && ( false == compressordisable ) - && ( ( false == governorlock ) || ( CompressorPower == 3 ) ) - && ( ( CompressorFlag ) - || ( ( compressorenable ) && ( LastSwitchingTime > CtrlDelay ) ) ); + auto const compressorflag{CompressorFlag}; + CompressorFlag = + (compressorpower) && (false == compressordisable) && ((false == governorlock) || (CompressorPower == 3)) && ((CompressorFlag) || ((compressorenable) && (LastSwitchingTime > CtrlDelay))); - if( ( CompressorFlag ) && ( CompressorFlag != compressorflag ) ) { - // jeśli została załączona to trzeba ograniczyć ponowne włączenie - LastSwitchingTime = 0; - } + if ((CompressorFlag) && (CompressorFlag != compressorflag)) + { + // jeśli została załączona to trzeba ograniczyć ponowne włączenie + LastSwitchingTime = 0; + } - if( false == CompressorFlag ) { return; } + if (false == CompressorFlag) + { + return; + } - // working compressor adds air to the air reservoir - switch( CompressorPower ) { - case 3: { - // the compressor is coupled with the diesel engine, engine revolutions affect the output - CompressedVolume += - CompressorSpeedF - * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF - * EngineRPMRatio() - * dt - * ( CompressorGovernorLock ? 0.0 : 1.0 ); // with the lock active air is vented out - break; - } - default: { - // the compressor is a stand-alone device, working at steady pace - CompressedVolume += - CompressorSpeedF - * ( 2.0 * MaxCompressorF - Compressor ) / MaxCompressorF - * dt; - break; - } - } + // working compressor adds air to the air reservoir + switch (CompressorPower) + { + case 3: + { + // the compressor is coupled with the diesel engine, engine revolutions affect the output + CompressedVolume += + CompressorSpeedF * (2.0 * MaxCompressorF - Compressor) / MaxCompressorF * EngineRPMRatio() * dt * (CompressorGovernorLock ? 0.0 : 1.0); // with the lock active air is vented out + break; + } + default: + { + // the compressor is a stand-alone device, working at steady pace + CompressedVolume += CompressorSpeedF * (2.0 * MaxCompressorF - Compressor) / MaxCompressorF * dt; + break; + } + } - if( ( pressureistoohigh ) - && ( ( false == governorlockispresent ) || ( CompressorPower == 3 ) ) ) { - // vent some air out if there's no governor lock to stop the compressor from exceeding acceptable pressure level - SetFlag( SoundFlag, sound::relay | sound::loud ); - CompressedVolume *= ( + if ((pressureistoohigh) && ((false == governorlockispresent) || (CompressorPower == 3))) + { + // vent some air out if there's no governor lock to stop the compressor from exceeding acceptable pressure level + SetFlag(SoundFlag, sound::relay | sound::loud); + CompressedVolume *= ( false == governorlockispresent ? 0.80 : // arbitrary amount CompressorTankValve ? MinCompressorF / MaxCompressorF : // drop to mincompressor level 0.999 ); // HACK: drop a tiny bit so the sound doesn't trigger repeatedly - if( ( false == governorlockispresent ) || ( CompressorTankValve ) ) { - CompressorGovernorLock = false; - } - } + if ((false == governorlockispresent) || (CompressorTankValve)) + { + CompressorGovernorLock = false; + } + } - // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę - // TODO: draw power from proper high- or low voltage circuit - switch( CompressorPower ) { - case 3: { - // diesel-powered compressor doesn't draw power - break; - } - default: { - // TODO: drain power from 110v circuit -/* - if( compressorowner != nullptr ) { - compressorowner->TotalCurrent += 0.0015 * compressorowner->PantographVoltage; - } -*/ - break; - } - } + // tymczasowo tylko obciążenie sprężarki, tak z 5A na sprężarkę + // TODO: draw power from proper high- or low voltage circuit + switch (CompressorPower) + { + case 3: + { + // diesel-powered compressor doesn't draw power + break; + } + default: + { + // TODO: drain power from 110v circuit + /* + if( compressorowner != nullptr ) { + compressorowner->TotalCurrent += 0.0015 * compressorowner->PantographVoltage; + } + */ + break; + } + } } // ************************************************************************************************* @@ -4417,32 +4404,36 @@ void TMoverParameters::CompressorCheck(double dt) { // ************************************************************************************************* void TMoverParameters::UpdatePipePressure(double dt) { - if( PipePress > 1.0 ) { - Pipe->Flow( -(PipePress)* AirLeakRate * dt ); - Pipe->Act(); - } + if (PipePress > 1.0) + { + Pipe->Flow(-(PipePress)*AirLeakRate * dt); + Pipe->Act(); + } - const double LBDelay = 100; - const double kL = 0.5; - //double dV; - //TMoverParameters *c; // T_MoverParameters - double temp; - //int b; + const double LBDelay = 100; + const double kL = 0.5; + // double dV; + // TMoverParameters *c; // T_MoverParameters + double temp; + // int b; - PipePress = Pipe->P(); - // PPP:=PipePress; + PipePress = Pipe->P(); + // PPP:=PipePress; - dpMainValve = 0; + dpMainValve = 0; - if( BrakeCtrlPosNo > 1 ) { + if (BrakeCtrlPosNo > 1) + { - if ((EngineType != TEngineType::ElectricInductionMotor)) { + if ((EngineType != TEngineType::ElectricInductionMotor)) + { double lbpa = LocalBrakePosA; if ((EIMCtrlType > 0) && (UniCtrlIntegratedLocalBrakeCtrl)) { lbpa = std::max(0.0, -eimic_real); } - if (SpeedCtrlUnit.Parking) { + if (SpeedCtrlUnit.Parking) + { lbpa = std::max(lbpa, StopBrakeDecc); } dpLocalValve = LocHandle->GetPF(std::max(lbpa, LocalBrakePosAEIM), Hamulec->GetBCP(), ScndPipePress, dt, 0); @@ -4451,257 +4442,241 @@ void TMoverParameters::UpdatePipePressure(double dt) dpLocalValve = LocHandle->GetPF(LocalBrakePosAEIM, Hamulec->GetBCP(), ScndPipePress, dt, 0); LockPipe = PipePress < (LockPipe ? LockPipeOff : LockPipeOn); - bool lock_new = (LockPipe && !UnlockPipe && (BrakeCtrlPosR > HandleUnlock)) - || ((EmergencyCutsOffHandle) && (EmergencyValveFlow > 0)); //new simple codition based on .fiz - bool lock_old = ((BrakeHandle == TBrakeHandle::FV4a) //old complex condition based on assumptions - && ((PipePress < 2.75) - && ((Hamulec->GetStatus() & b_rls) == 0)) - && (BrakeSubsystem == TBrakeSubSystem::ss_LSt) - && (TrainType != dt_EZT) - && (!UnlockPipe)); + bool lock_new = (LockPipe && !UnlockPipe && (BrakeCtrlPosR > HandleUnlock)) || ((EmergencyCutsOffHandle) && (EmergencyValveFlow > 0)); // new simple codition based on .fiz + bool lock_old = ((BrakeHandle == TBrakeHandle::FV4a) // old complex condition based on assumptions + && ((PipePress < 2.75) && ((Hamulec->GetStatus() & b_rls) == 0)) && (BrakeSubsystem == TBrakeSubSystem::ss_LSt) && (TrainType != dt_EZT) && (!UnlockPipe)); - if( ( lock_old ) || ( lock_new ) ) { - temp = PipePress + 0.00001; - } - else { - temp = ScndPipePress; - } - Handle->SetReductor(BrakeCtrlPos2); - - if( ( ( BrakeOpModes & bom_PS ) == 0 ) - || ( ( CabOccupied != 0 ) - && ( BrakeOpModeFlag != bom_PS ) ) ) { + if ((lock_old) || (lock_new)) + { + temp = PipePress + 0.00001; + } + else + { + temp = ScndPipePress; + } + Handle->SetReductor(BrakeCtrlPos2); - if( ( BrakeOpModeFlag < bom_EP ) - || ( ( Handle->GetPos( bh_EB ) - 0.5 ) < BrakeCtrlPosR ) - || ( ( BrakeHandle != TBrakeHandle::MHZ_EN57 ) - && ( BrakeHandle != TBrakeHandle::MHZ_K8P ) ) ) { + if (((BrakeOpModes & bom_PS) == 0) || ((CabOccupied != 0) && (BrakeOpModeFlag != bom_PS))) + { + + if ((BrakeOpModeFlag < bom_EP) || ((Handle->GetPos(bh_EB) - 0.5) < BrakeCtrlPosR) || ((BrakeHandle != TBrakeHandle::MHZ_EN57) && (BrakeHandle != TBrakeHandle::MHZ_K8P))) + { double pos = BrakeCtrlPosR; - if (SpeedCtrlUnit.IsActive && SpeedCtrlUnit.BrakeIntervention && !SpeedCtrlUnit.Standby && (BrakeCtrlPos != Handle->GetPos(bh_EB))) { + if (SpeedCtrlUnit.IsActive && SpeedCtrlUnit.BrakeIntervention && !SpeedCtrlUnit.Standby && (BrakeCtrlPos != Handle->GetPos(bh_EB))) + { pos = Handle->GetPos(bh_NP); if (SpeedCtrlUnit.BrakeInterventionBraking) pos = Handle->GetPos(bh_FB); if (SpeedCtrlUnit.BrakeInterventionUnbraking) pos = Handle->GetPos(bh_RP); } - dpMainValve = Handle->GetPF( pos, PipePress, temp, dt, EqvtPipePress ); - } - else { - dpMainValve = Handle->GetPF( 0, PipePress, temp, dt, EqvtPipePress ); - } - } - else if (BrakeCtrlPos == Handle->GetPos(bh_EB)) - { - dpMainValve = Handle->GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress); + dpMainValve = Handle->GetPF(pos, PipePress, temp, dt, EqvtPipePress); + } + else + { + dpMainValve = Handle->GetPF(0, PipePress, temp, dt, EqvtPipePress); + } } - + else if (BrakeCtrlPos == Handle->GetPos(bh_EB)) + { + dpMainValve = Handle->GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress); + } + if (dpMainValve < 0) // && (PipePressureVal > 0.01) //50 - if (Compressor > ScndPipePress) - { - CompressedVolume = CompressedVolume + dpMainValve / 1500.0; - Pipe2->Flow(dpMainValve / 3.0); - } - else - Pipe2->Flow(dpMainValve); - } + if (Compressor > ScndPipePress) + { + CompressedVolume = CompressedVolume + dpMainValve / 1500.0; + Pipe2->Flow(dpMainValve / 3.0); + } + else + Pipe2->Flow(dpMainValve); + } - // ulepszony hamulec bezp. - EmergencyValveFlow = 0.0; + // ulepszony hamulec bezp. + EmergencyValveFlow = 0.0; - auto const lowvoltagepower { Power24vIsAvailable || Power110vIsAvailable }; + auto const lowvoltagepower{Power24vIsAvailable || Power110vIsAvailable}; - if( (( true == RadioStopFlag ) - || ( true == AlarmChainFlag ) - || (( true == EIMCtrlEmergency) - && (LocalBrakePosA >= 1.0)) - || SecuritySystem.is_braking()) - || ( ( SpringBrakeDriveEmergencyVel >= 0 ) - && ( Vel > SpringBrakeDriveEmergencyVel ) - && ( SpringBrake.IsActive ) ) -/* - // NOTE: disabled because 32 is 'load destroyed' flag, what does this have to do with emergency brake? - // (if it's supposed to be broken coupler, such event sets alarmchainflag instead when appropriate) - || ( true == TestFlag( EngDmgFlag, 32 ) ) -*/ - || ( ( 0 == CabActive ) - && ( InactiveCabFlag & activation::emergencybrake ) ) - || ( ( SpringBrakeDriveEmergencyVel >= 0 ) - && ( Vel > SpringBrakeDriveEmergencyVel ) - && ( SpringBrake.IsActive ) ) ) { - EmergencyValveFlow = PF( 0, PipePress, 0.15 ) * dt; - } - dpMainValve += EmergencyValveFlow; + if (((true == RadioStopFlag) || (true == AlarmChainFlag) || ((true == EIMCtrlEmergency) && (LocalBrakePosA >= 1.0)) || SecuritySystem.is_braking()) || + ((SpringBrakeDriveEmergencyVel >= 0) && (Vel > SpringBrakeDriveEmergencyVel) && (SpringBrake.IsActive)) + /* + // NOTE: disabled because 32 is 'load destroyed' flag, what does this have to do with emergency brake? + // (if it's supposed to be broken coupler, such event sets alarmchainflag instead when appropriate) + || ( true == TestFlag( EngDmgFlag, 32 ) ) + */ + || ((0 == CabActive) && (InactiveCabFlag & activation::emergencybrake)) || ((SpringBrakeDriveEmergencyVel >= 0) && (Vel > SpringBrakeDriveEmergencyVel) && (SpringBrake.IsActive))) + { + EmergencyValveFlow = PF(0, PipePress, 0.15) * dt; + } + dpMainValve += EmergencyValveFlow; - // 0.2*Spg - Pipe->Flow(-dpMainValve); - Pipe->Flow(-(PipePress)*0.001 * dt); - // if Heating then - // Pipe.Flow(PF(PipePress, 0, d2A(7)) * dt); - // if ConverterFlag then - // Pipe.Flow(PF(PipePress, 0, d2A(12)) * dt); - dpMainValve = dpMainValve / (Dim.L * Spg * 20); + // 0.2*Spg + Pipe->Flow(-dpMainValve); + Pipe->Flow(-(PipePress) * 0.001 * dt); + // if Heating then + // Pipe.Flow(PF(PipePress, 0, d2A(7)) * dt); + // if ConverterFlag then + // Pipe.Flow(PF(PipePress, 0, d2A(12)) * dt); + dpMainValve = dpMainValve / (Dim.L * Spg * 20); - CntrlPipePress = Hamulec->GetVRP(); // ciśnienie komory wstępnej rozdzielacza + CntrlPipePress = Hamulec->GetVRP(); // ciśnienie komory wstępnej rozdzielacza - // if (Hamulec is typeid(TWest)) return 0; + // if (Hamulec is typeid(TWest)) return 0; - switch (BrakeValve) { + switch (BrakeValve) + { - case TBrakeValve::K: - case TBrakeValve::W: { + case TBrakeValve::K: + case TBrakeValve::W: + { - if( BrakeLocHandle != TBrakeHandle::NoHandle ) { - LocBrakePress = LocHandle->GetCP(); + if (BrakeLocHandle != TBrakeHandle::NoHandle) + { + LocBrakePress = LocHandle->GetCP(); - //(Hamulec as TWest).SetLBP(LocBrakePress); - Hamulec->SetLBP( LocBrakePress ); - } - if( MBPM < 2 ) - //(Hamulec as TWest).PLC(MaxBrakePress[LoadFlag]) - Hamulec->PLC( MaxBrakePress[ LoadFlag ] ); - else - //(Hamulec as TWest).PLC(TotalMass); - Hamulec->PLC( TotalMass-Mred ); - break; - } + //(Hamulec as TWest).SetLBP(LocBrakePress); + Hamulec->SetLBP(LocBrakePress); + } + if (MBPM < 2) + //(Hamulec as TWest).PLC(MaxBrakePress[LoadFlag]) + Hamulec->PLC(MaxBrakePress[LoadFlag]); + else + //(Hamulec as TWest).PLC(TotalMass); + Hamulec->PLC(TotalMass - Mred); + break; + } - case TBrakeValve::LSt: - case TBrakeValve::EStED: { + case TBrakeValve::LSt: + case TBrakeValve::EStED: + { - LocBrakePress = LocHandle->GetCP(); - for( int b = 0; b < 2; b++ ) - if( ( ( TrainType & ( dt_ET41 | dt_ET42 ) ) != 0 ) && - ( Couplers[ b ].Connected != NULL ) ) // nie podoba mi się to rozwiązanie, chyba trzeba - // dodać jakiś wpis do fizyki na to - if( ( ( Couplers[ b ].Connected->TrainType & ( dt_ET41 | dt_ET42 ) ) != 0 ) && - ( ( Couplers[ b ].CouplingFlag & 36 ) == 36 ) ) - LocBrakePress = std::max( Couplers[ b ].Connected->LocHandle->GetCP(), LocBrakePress ); + LocBrakePress = LocHandle->GetCP(); + for (int b = 0; b < 2; b++) + if (((TrainType & (dt_ET41 | dt_ET42)) != 0) && (Couplers[b].Connected != NULL)) // nie podoba mi się to rozwiązanie, chyba trzeba + // dodać jakiś wpis do fizyki na to + if (((Couplers[b].Connected->TrainType & (dt_ET41 | dt_ET42)) != 0) && ((Couplers[b].CouplingFlag & 36) == 36)) + LocBrakePress = std::max(Couplers[b].Connected->LocHandle->GetCP(), LocBrakePress); - //if ((DynamicBrakeFlag) && (EngineType == ElectricInductionMotor)) - //{ - // //if (Vel > 10) - // // LocBrakePress = 0; - // //else if (Vel > 5) - // // LocBrakePress = (10 - Vel) / 5 * LocBrakePress; - //} + // if ((DynamicBrakeFlag) && (EngineType == ElectricInductionMotor)) + //{ + // //if (Vel > 10) + // // LocBrakePress = 0; + // //else if (Vel > 5) + // // LocBrakePress = (10 - Vel) / 5 * LocBrakePress; + // } - //(Hamulec as TLSt).SetLBP(LocBrakePress); - Hamulec->SetLBP( LocBrakePress ); - if( ( BrakeValve == TBrakeValve::EStED ) ) - if( MBPM < 2 ) - Hamulec->PLC( MaxBrakePress[ LoadFlag ] ); - else - Hamulec->PLC( TotalMass-Mred ); - break; - } + //(Hamulec as TLSt).SetLBP(LocBrakePress); + Hamulec->SetLBP(LocBrakePress); + if ((BrakeValve == TBrakeValve::EStED)) + if (MBPM < 2) + Hamulec->PLC(MaxBrakePress[LoadFlag]); + else + Hamulec->PLC(TotalMass - Mred); + break; + } - case TBrakeValve::CV1_L_TR: - { - LocBrakePress = LocHandle->GetCP(); - //(Hamulec as TCV1L_TR).SetLBP(LocBrakePress); - Hamulec->SetLBP( LocBrakePress ); - break; - } + case TBrakeValve::CV1_L_TR: + { + LocBrakePress = LocHandle->GetCP(); + //(Hamulec as TCV1L_TR).SetLBP(LocBrakePress); + Hamulec->SetLBP(LocBrakePress); + break; + } - case TBrakeValve::EP2: - case TBrakeValve::EP1: - { - Hamulec->PLC( TotalMass-Mred ); - break; - } - case TBrakeValve::ESt3AL2: - case TBrakeValve::NESt3: - case TBrakeValve::ESt4: - case TBrakeValve::ESt3: - { - if( MBPM < 2 ) - //(Hamulec as TNESt3).PLC(MaxBrakePress[LoadFlag]) - Hamulec->PLC( MaxBrakePress[ LoadFlag ] ); - else - //(Hamulec as TNESt3).PLC(TotalMass); - Hamulec->PLC( TotalMass-Mred ); - LocBrakePress = LocHandle->GetCP(); - //(Hamulec as TNESt3).SetLBP(LocBrakePress); - Hamulec->SetLBP( LocBrakePress ); - break; - } - case TBrakeValve::KE: - { - LocBrakePress = LocHandle->GetCP(); - //(Hamulec as TKE).SetLBP(LocBrakePress); - Hamulec->SetLBP( LocBrakePress ); - if( MBPM < 2 ) - //(Hamulec as TKE).PLC(MaxBrakePress[LoadFlag]) - Hamulec->PLC( MaxBrakePress[ LoadFlag ] ); - else - //(Hamulec as TKE).PLC(TotalMass); - Hamulec->PLC( TotalMass-Mred ); - break; - } - default: - { - // unsupported brake valve type, we should never land here -// ErrorLog( "Unsupported brake valve type (" + std::to_string( BrakeValve ) + ") in " + TypeName ); -// ::PostQuitMessage( 0 ); - break; - } - } // switch + case TBrakeValve::EP2: + case TBrakeValve::EP1: + { + Hamulec->PLC(TotalMass - Mred); + break; + } + case TBrakeValve::ESt3AL2: + case TBrakeValve::NESt3: + case TBrakeValve::ESt4: + case TBrakeValve::ESt3: + { + if (MBPM < 2) + //(Hamulec as TNESt3).PLC(MaxBrakePress[LoadFlag]) + Hamulec->PLC(MaxBrakePress[LoadFlag]); + else + //(Hamulec as TNESt3).PLC(TotalMass); + Hamulec->PLC(TotalMass - Mred); + LocBrakePress = LocHandle->GetCP(); + //(Hamulec as TNESt3).SetLBP(LocBrakePress); + Hamulec->SetLBP(LocBrakePress); + break; + } + case TBrakeValve::KE: + { + LocBrakePress = LocHandle->GetCP(); + //(Hamulec as TKE).SetLBP(LocBrakePress); + Hamulec->SetLBP(LocBrakePress); + if (MBPM < 2) + //(Hamulec as TKE).PLC(MaxBrakePress[LoadFlag]) + Hamulec->PLC(MaxBrakePress[LoadFlag]); + else + //(Hamulec as TKE).PLC(TotalMass); + Hamulec->PLC(TotalMass - Mred); + break; + } + default: + { + // unsupported brake valve type, we should never land here + // ErrorLog( "Unsupported brake valve type (" + std::to_string( BrakeValve ) + ") in " + TypeName ); + // ::PostQuitMessage( 0 ); + break; + } + } // switch - if (((BrakeHandle == TBrakeHandle::FVel6)||(BrakeHandle == TBrakeHandle::FVE408)) && (CabOccupied != 0)) - { - if ((Power24vIsAvailable) - && (DirActive != 0) - && (EpFuse)) // tu powinien byc jeszcze bezpiecznik EP i baterie - - // temp = (Handle as TFVel6).GetCP + if (((BrakeHandle == TBrakeHandle::FVel6) || (BrakeHandle == TBrakeHandle::FVE408)) && (CabOccupied != 0)) + { + if ((Power24vIsAvailable) && (DirActive != 0) && (EpFuse)) // tu powinien byc jeszcze bezpiecznik EP i baterie - + // temp = (Handle as TFVel6).GetCP EpForce = Handle->GetEP(); - else + else EpForce = 0.0; - DynamicBrakeEMUStatus = ( - EpForce > 0.001 ? - Power110vIsAvailable : - true ); + DynamicBrakeEMUStatus = (EpForce > 0.001 ? Power110vIsAvailable : true); double temp1 = EpForce; if ((DCEMUED_EP_max_Vel > 0.001) && (Vel > DCEMUED_EP_max_Vel) && (DynamicBrakeEMUStatus)) temp1 = 0; if ((DCEMUED_EP_min_Im > 0.001) && (abs(Im) > DCEMUED_EP_min_Im) && (DynamicBrakeEMUStatus)) temp1 = 0; - Hamulec->SetEPS(temp1); + Hamulec->SetEPS(temp1); TUHEX_StageActual = EpForce; TUHEX_Active = TUHEX_StageActual > 0; - // Ra 2014-11: na tym się wysypuje, ale nie wiem, w jakich warunkach - SendCtrlToNext("Brake", EpForce, CabActive); - } + // Ra 2014-11: na tym się wysypuje, ale nie wiem, w jakich warunkach + SendCtrlToNext("Brake", EpForce, CabActive); + } - Pipe->Act(); - PipePress = Pipe->P(); - if( ( Hamulec->GetBrakeStatus() & b_dmg ) == b_dmg ) // jesli hamulec wyłączony - temp = 0.0; // odetnij - else - temp = 1.0; // połącz - Pipe->Flow( temp * Hamulec->GetPF( temp * PipePress, dt, Vel ) + GetDVc( dt ) ); + Pipe->Act(); + PipePress = Pipe->P(); + if ((Hamulec->GetBrakeStatus() & b_dmg) == b_dmg) // jesli hamulec wyłączony + temp = 0.0; // odetnij + else + temp = 1.0; // połącz + Pipe->Flow(temp * Hamulec->GetPF(temp * PipePress, dt, Vel) + GetDVc(dt)); - if (ASBType == 128) - Hamulec->ASB(int(SlippingWheels && (Vel>1))*(1+2*int(nrot_eps<-0.01))); + if (ASBType == 128) + Hamulec->ASB(int(SlippingWheels && (Vel > 1)) * (1 + 2 * int(nrot_eps < -0.01))); - dpPipe = 0; + dpPipe = 0; - // yB: jednokrokowe liczenie tego wszystkiego - Pipe->Act(); - PipePress = Pipe->P(); + // yB: jednokrokowe liczenie tego wszystkiego + Pipe->Act(); + PipePress = Pipe->P(); - dpMainValve = dpMainValve / (100.0 * dt); // normalizacja po czasie do syczenia; + dpMainValve = dpMainValve / (100.0 * dt); // normalizacja po czasie do syczenia; - if (PipePress < -1.0) - { - PipePress = -1.0; - Pipe->CreatePress(-1.0); - Pipe->Act(); - } + if (PipePress < -1.0) + { + PipePress = -1.0; + Pipe->CreatePress(-1.0); + Pipe->Act(); + } - if (CompressedVolume < 0.0) - CompressedVolume = 0.0; + if (CompressedVolume < 0.0) + CompressedVolume = 0.0; } // ************************************************************************************************* @@ -4710,70 +4685,69 @@ void TMoverParameters::UpdatePipePressure(double dt) // ************************************************************************************************* void TMoverParameters::UpdateScndPipePressure(double dt) { - if( ScndPipePress > 1.0 ) { - Pipe2->Flow( -(ScndPipePress)* AirLeakRate * dt ); - Pipe2->Act(); - } + if (ScndPipePress > 1.0) + { + Pipe2->Flow(-(ScndPipePress)*AirLeakRate * dt); + Pipe2->Act(); + } - const double Spz = 0.5067; - TMoverParameters *c; - double dv1, dv2, dV; + const double Spz = 0.5067; + TMoverParameters *c; + double dv1, dv2, dV; UpdateSpringBrake(dt); - dv1 = 0; - dv2 = 0; + dv1 = 0; + dv2 = 0; - // sprzeg 1 - if (Couplers[0].Connected != NULL) - if (TestFlag(Couplers[0].CouplingFlag, ctrain_scndpneumatic)) - { - c = Couplers[0].Connected; // skrot - dv1 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75); - if (dv1 * dv1 > 0.00000000000001) - c->switch_physics( true ); - c->Pipe2->Flow(-dv1); - } - // sprzeg 2 - if (Couplers[1].Connected != NULL) - if (TestFlag(Couplers[1].CouplingFlag, ctrain_scndpneumatic)) - { - c = Couplers[1].Connected; // skrot - dv2 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75); - if (dv2 * dv2 > 0.00000000000001) - c->switch_physics( true ); - c->Pipe2->Flow(-dv2); - } - if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL)) - if ((TestFlag(Couplers[0].CouplingFlag, ctrain_scndpneumatic)) && - (TestFlag(Couplers[1].CouplingFlag, ctrain_scndpneumatic))) - { - dV = 0.00025 * dt * PF(Couplers[0].Connected->ScndPipePress, - Couplers[1].Connected->ScndPipePress, Spz * 0.25); - Couplers[0].Connected->Pipe2->Flow(+dV); - Couplers[1].Connected->Pipe2->Flow(-dV); - } + // sprzeg 1 + if (Couplers[0].Connected != NULL) + if (TestFlag(Couplers[0].CouplingFlag, ctrain_scndpneumatic)) + { + c = Couplers[0].Connected; // skrot + dv1 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75); + if (dv1 * dv1 > 0.00000000000001) + c->switch_physics(true); + c->Pipe2->Flow(-dv1); + } + // sprzeg 2 + if (Couplers[1].Connected != NULL) + if (TestFlag(Couplers[1].CouplingFlag, ctrain_scndpneumatic)) + { + c = Couplers[1].Connected; // skrot + dv2 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75); + if (dv2 * dv2 > 0.00000000000001) + c->switch_physics(true); + c->Pipe2->Flow(-dv2); + } + if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL)) + if ((TestFlag(Couplers[0].CouplingFlag, ctrain_scndpneumatic)) && (TestFlag(Couplers[1].CouplingFlag, ctrain_scndpneumatic))) + { + dV = 0.00025 * dt * PF(Couplers[0].Connected->ScndPipePress, Couplers[1].Connected->ScndPipePress, Spz * 0.25); + Couplers[0].Connected->Pipe2->Flow(+dV); + Couplers[1].Connected->Pipe2->Flow(-dV); + } - Pipe2->Flow(Hamulec->GetHPFlow(ScndPipePress, dt)); - // NOTE: condition disabled to allow the air flow from the main hose to the main tank as well - if( /* ( ( Compressor > ScndPipePress ) && ( */ VeselVolume > 0.0 /* ) ) || ( TrainType == dt_EZT ) || ( TrainType == dt_DMU ) */ ) { - dV = PF(Compressor, ScndPipePress, Spz) * dt; - CompressedVolume += dV / 1000.0; - Pipe2->Flow(-dV); - } - Pipe2->Flow(dv1 + dv2); - Pipe2->Act(); - ScndPipePress = Pipe2->P(); + Pipe2->Flow(Hamulec->GetHPFlow(ScndPipePress, dt)); + // NOTE: condition disabled to allow the air flow from the main hose to the main tank as well + if (/* ( ( Compressor > ScndPipePress ) && ( */ VeselVolume > 0.0 /* ) ) || ( TrainType == dt_EZT ) || ( TrainType == dt_DMU ) */) + { + dV = PF(Compressor, ScndPipePress, Spz) * dt; + CompressedVolume += dV / 1000.0; + Pipe2->Flow(-dV); + } + Pipe2->Flow(dv1 + dv2); + Pipe2->Act(); + ScndPipePress = Pipe2->P(); - if (ScndPipePress < -1) - { - ScndPipePress = -1; - Pipe2->CreatePress(-1); - Pipe2->Act(); - } + if (ScndPipePress < -1) + { + ScndPipePress = -1; + Pipe2->CreatePress(-1); + Pipe2->Act(); + } } - // ************************************************************************************************* // yB: 20190906 // Aktualizacja ciśnienia w hamulcu sprezynowym @@ -4787,7 +4761,7 @@ void TMoverParameters::UpdateSpringBrake(double dt) double desired_press = std::min(std::max(MSP, BP), Pipe2->P()); double dv = PF(desired_press, SpringBrake.SBP, SpringBrake.ValveOffArea); SpringBrake.Cylinder->Flow(-dv); - Pipe2->Flow(std::max(dv,0.0)); + Pipe2->Flow(std::max(dv, 0.0)); } else { @@ -4796,7 +4770,7 @@ void TMoverParameters::UpdateSpringBrake(double dt) } if (SpringBrake.SBP > SpringBrake.ResetPressure) SpringBrake.IsReady = true; - + SpringBrake.IsActive = SpringBrake.SBP < (SpringBrake.IsActive ? SpringBrake.PressureOff : SpringBrake.PressureOn); SpringBrake.Release = false; @@ -4810,44 +4784,44 @@ void TMoverParameters::UpdateSpringBrake(double dt) // ************************************************************************************************* double TMoverParameters::GetDVc(double dt) { - // T_MoverParameters *c; - TMoverParameters *c; - double dv1, dv2;// , dV; + // T_MoverParameters *c; + TMoverParameters *c; + double dv1, dv2; // , dV; - dv1 = 0; - dv2 = 0; - // sprzeg 1 - if (Couplers[0].Connected != NULL) - if (TestFlag(Couplers[0].CouplingFlag, ctrain_pneumatic)) - { //*0.85 - c = Couplers[0].Connected; // skrot //0.08 //e/D * L/D = e/D^2 * L - dv1 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1.0 + 0.015 / Spg * Dim.L)); - if (dv1 * dv1 > 0.00000000000001) - c->switch_physics( true ); - c->Pipe->Flow(-dv1); - } - // sprzeg 2 - if (Couplers[1].Connected != NULL) - if (TestFlag(Couplers[1].CouplingFlag, ctrain_pneumatic)) - { - c = Couplers[1].Connected; // skrot - dv2 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1.0 + 0.015 / Spg * Dim.L)); - if (dv2 * dv2 > 0.00000000000001) - c->switch_physics( true ); - c->Pipe->Flow(-dv2); - } - //if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL)) - // if ((TestFlag(Couplers[0].CouplingFlag, ctrain_pneumatic)) && - // (TestFlag(Couplers[1].CouplingFlag, ctrain_pneumatic))) - // { - // dV = 0.05 * dt * PF(Couplers[0].Connected->PipePress, Couplers[1].Connected->PipePress, - // (Spg * 0.85) / (1 + 0.03 * Dim.L)) * - // 0; // ktoś mi powie jaki jest sens tego bloku jeśli przepływ mnożony przez zero? - // Couplers[0].Connected->Pipe->Flow(+dV); - // Couplers[1].Connected->Pipe->Flow(-dV); - // } - // suma - return dv2 + dv1; + dv1 = 0; + dv2 = 0; + // sprzeg 1 + if (Couplers[0].Connected != NULL) + if (TestFlag(Couplers[0].CouplingFlag, ctrain_pneumatic)) + { //*0.85 + c = Couplers[0].Connected; // skrot //0.08 //e/D * L/D = e/D^2 * L + dv1 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1.0 + 0.015 / Spg * Dim.L)); + if (dv1 * dv1 > 0.00000000000001) + c->switch_physics(true); + c->Pipe->Flow(-dv1); + } + // sprzeg 2 + if (Couplers[1].Connected != NULL) + if (TestFlag(Couplers[1].CouplingFlag, ctrain_pneumatic)) + { + c = Couplers[1].Connected; // skrot + dv2 = 0.5 * dt * PF(PipePress, c->PipePress, (Spg) / (1.0 + 0.015 / Spg * Dim.L)); + if (dv2 * dv2 > 0.00000000000001) + c->switch_physics(true); + c->Pipe->Flow(-dv2); + } + // if ((Couplers[1].Connected != NULL) && (Couplers[0].Connected != NULL)) + // if ((TestFlag(Couplers[0].CouplingFlag, ctrain_pneumatic)) && + // (TestFlag(Couplers[1].CouplingFlag, ctrain_pneumatic))) + // { + // dV = 0.05 * dt * PF(Couplers[0].Connected->PipePress, Couplers[1].Connected->PipePress, + // (Spg * 0.85) / (1 + 0.03 * Dim.L)) * + // 0; // ktoś mi powie jaki jest sens tego bloku jeśli przepływ mnożony przez zero? + // Couplers[0].Connected->Pipe->Flow(+dV); + // Couplers[1].Connected->Pipe->Flow(-dV); + // } + // suma + return dv2 + dv1; } // ************************************************************************************************* @@ -4856,60 +4830,58 @@ double TMoverParameters::GetDVc(double dt) // ************************************************************************************************* void TMoverParameters::ComputeConstans(void) { - double BearingF, RollF, HideModifier; - double Curvature; // Ra 2014-07: odwrotność promienia + double BearingF, RollF, HideModifier; + double Curvature; // Ra 2014-07: odwrotność promienia - TotalMassxg = TotalMass * g; // TotalMass*g - BearingF = DamageFlag & dtrain_bearing > 0 ? 2.0 : 0; + TotalMassxg = TotalMass * g; // TotalMass*g + BearingF = DamageFlag & dtrain_bearing > 0 ? 2.0 : 0; - HideModifier = 0; // int(Couplers[0].CouplingFlag>0)+int(Couplers[1].CouplingFlag>0); + HideModifier = 0; // int(Couplers[0].CouplingFlag>0)+int(Couplers[1].CouplingFlag>0); - if (BearingType == 0) - RollF = 0.05; // slizgowe - else - RollF = 0.015; // toczne - RollF += BearingF / 200.0; + if (BearingType == 0) + RollF = 0.05; // slizgowe + else + RollF = 0.015; // toczne + RollF += BearingF / 200.0; - // if (NPoweredAxles > 0) - // RollF = RollF * 1.5; //dodatkowe lozyska silnikow + // if (NPoweredAxles > 0) + // RollF = RollF * 1.5; //dodatkowe lozyska silnikow - if (NPoweredAxles > 0) // drobna optymalka - { - RollF += 0.025; - // if (Ft * Ft < 1) - // HideModifier = HideModifier - 3; - } - Ff = TotalMassxg * (BearingF + RollF * V * V / 10.0) / 1000.0; - // dorobic liczenie temperatury lozyska! - FrictConst1 = ( TotalMassxg * RollF ) / 10000.0; - // drag calculation - { - // NOTE: draft effect of previous vehicle is simplified and doesn't have much to do with reality - auto const *previousvehicle { Couplers[ ( V >= 0.0 ? end::front : end::rear ) ].Connected }; - auto dragarea { Dim.W * Dim.H }; - if( previousvehicle ) { - dragarea = std::max( 0.0, dragarea - ( 0.85 * previousvehicle->Dim.W * previousvehicle->Dim.H ) ); - } - FrictConst1 += Cx * dragarea; - } + if (NPoweredAxles > 0) // drobna optymalka + { + RollF += 0.025; + // if (Ft * Ft < 1) + // HideModifier = HideModifier - 3; + } + Ff = TotalMassxg * (BearingF + RollF * V * V / 10.0) / 1000.0; + // dorobic liczenie temperatury lozyska! + FrictConst1 = (TotalMassxg * RollF) / 10000.0; + // drag calculation + { + // NOTE: draft effect of previous vehicle is simplified and doesn't have much to do with reality + auto const *previousvehicle{Couplers[(V >= 0.0 ? end::front : end::rear)].Connected}; + auto dragarea{Dim.W * Dim.H}; + if (previousvehicle) + { + dragarea = std::max(0.0, dragarea - (0.85 * previousvehicle->Dim.W * previousvehicle->Dim.H)); + } + FrictConst1 += Cx * dragarea; + } - if( CategoryFlag & 1 ) { - Curvature = ( - RunningShape.R == 0.0 ? // zero oznacza nieskończony promień - 0.0 : - 1.0 / std::abs( RunningShape.R ) ); - } - else { - // vehicles other than trains don't experience friction against the rail on curves - Curvature = 0.0; - } - // opór składu na łuku (youBy): +(500*TrackW/R)*TotalMassxg*0.001 do FrictConst2s/d - FrictConst2s = (TotalMassxg * ((500.0 * TrackW * Curvature) + 2.5 - HideModifier + - 2 * BearingF / dtrain_bearing)) * - 0.001; - FrictConst2d = (TotalMassxg * ((500.0 * TrackW * Curvature) + 2.0 - HideModifier + - BearingF / dtrain_bearing)) * - 0.001; + if (CategoryFlag & 1) + { + Curvature = (RunningShape.R == 0.0 ? // zero oznacza nieskończony promień + 0.0 : + 1.0 / std::abs(RunningShape.R)); + } + else + { + // vehicles other than trains don't experience friction against the rail on curves + Curvature = 0.0; + } + // opór składu na łuku (youBy): +(500*TrackW/R)*TotalMassxg*0.001 do FrictConst2s/d + FrictConst2s = (TotalMassxg * ((500.0 * TrackW * Curvature) + 2.5 - HideModifier + 2 * BearingF / dtrain_bearing)) * 0.001; + FrictConst2d = (TotalMassxg * ((500.0 * TrackW * Curvature) + 2.0 - HideModifier + BearingF / dtrain_bearing)) * 0.001; } // ************************************************************************************************* @@ -4918,26 +4890,28 @@ void TMoverParameters::ComputeConstans(void) // ************************************************************************************************* void TMoverParameters::ComputeMass() { - // Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają - TotalMass = Mass + Mred; + // Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają + TotalMass = Mass + Mred; - if( LoadAmount == 0 ) { return; } + if (LoadAmount == 0) + { + return; + } - // include weight of carried load - auto loadtypeunitweight { 0.f }; + // include weight of carried load + auto loadtypeunitweight{0.f}; - if( ToLower( LoadQuantity ) == "tonns" ) { - loadtypeunitweight = 1000; - } - else { - auto const lookup { simulation::Weights.find( LoadType.name ) }; - loadtypeunitweight = ( - lookup != simulation::Weights.end() ? - lookup->second : - 1000.f ); // legacy default unit weight value - } + if (ToLower(LoadQuantity) == "tonns") + { + loadtypeunitweight = 1000; + } + else + { + auto const lookup{simulation::Weights.find(LoadType.name)}; + loadtypeunitweight = (lookup != simulation::Weights.end() ? lookup->second : 1000.f); // legacy default unit weight value + } - TotalMass += LoadAmount * loadtypeunitweight; + TotalMass += LoadAmount * loadtypeunitweight; } // ************************************************************************************************* @@ -4945,157 +4919,150 @@ void TMoverParameters::ComputeMass() // Obliczanie wypadkowej siły z wszystkich działających sił // ************************************************************************************************* // TBD, TODO: move some of the calculations out of the method, they're relevant to more than just force calculations -void TMoverParameters::ComputeTotalForce(double dt) { +void TMoverParameters::ComputeTotalForce(double dt) +{ - Vel = std::abs(V) * 3.6; // prędkość w km/h + Vel = std::abs(V) * 3.6; // prędkość w km/h - // McZapkie-031103: sprawdzanie czy warto liczyc fizyke i inne updaty - // ABu 300105: cos tu mieszalem , dziala teraz troche lepiej, wiec zostawiam - { - auto const vehicleisactive { - ( CabActive != 0 ) - || ( Vel > 0.0001 ) - || ( std::abs( AccS ) > 0.0001 ) - || ( LastSwitchingTime < 5 ) - || ( TrainType == dt_EZT ) - || ( TrainType == dt_DMU ) }; + // McZapkie-031103: sprawdzanie czy warto liczyc fizyke i inne updaty + // ABu 300105: cos tu mieszalem , dziala teraz troche lepiej, wiec zostawiam + { + auto const vehicleisactive{(CabActive != 0) || (Vel > 0.0001) || (std::abs(AccS) > 0.0001) || (LastSwitchingTime < 5) || (TrainType == dt_EZT) || (TrainType == dt_DMU)}; - auto const movingvehicleahead { - ( Neighbours[ end::front ].vehicle != nullptr ) - && ( ( Neighbours[ end::front ].vehicle->MoverParameters->Vel > 0.0001 ) - || ( std::abs( Neighbours[ end::front ].vehicle->MoverParameters->AccS ) > 0.0001 ) ) }; + auto const movingvehicleahead{(Neighbours[end::front].vehicle != nullptr) && + ((Neighbours[end::front].vehicle->MoverParameters->Vel > 0.0001) || (std::abs(Neighbours[end::front].vehicle->MoverParameters->AccS) > 0.0001))}; - auto const movingvehiclebehind { - ( Neighbours[ end::rear ].vehicle != nullptr ) - && ( ( Neighbours[ end::rear ].vehicle->MoverParameters->Vel > 0.0001 ) - || ( std::abs( Neighbours[ end::rear ].vehicle->MoverParameters->AccS ) > 0.0001 ) ) }; + auto const movingvehiclebehind{(Neighbours[end::rear].vehicle != nullptr) && + ((Neighbours[end::rear].vehicle->MoverParameters->Vel > 0.0001) || (std::abs(Neighbours[end::rear].vehicle->MoverParameters->AccS) > 0.0001))}; - auto const calculatephysics { vehicleisactive || movingvehicleahead || movingvehiclebehind }; + auto const calculatephysics{vehicleisactive || movingvehicleahead || movingvehiclebehind}; - switch_physics( calculatephysics ); - } + switch_physics(calculatephysics); + } - if( false == PhysicActivation ) { return; } + if (false == PhysicActivation) + { + return; + } - // juz zoptymalizowane: - FStand = FrictionForce(); // siła oporów ruchu - if( true == TestFlag( DamageFlag, dtrain_out ) ) { - // HACK: crude way to reduce speed after derailment - // TBD, TODO: more accurate approach? - FStand *= 1e20; - } + // juz zoptymalizowane: + FStand = FrictionForce(); // siła oporów ruchu + if (true == TestFlag(DamageFlag, dtrain_out)) + { + // HACK: crude way to reduce speed after derailment + // TBD, TODO: more accurate approach? + FStand *= 1e20; + } double old_nrot = abs(nrot); - nrot = v2n(); // przeliczenie prędkości liniowej na obrotową + nrot = v2n(); // przeliczenie prędkości liniowej na obrotową - if( ( true == TestFlag( BrakeMethod, bp_MHS ) ) - && ( PipePress < 3.0 ) // ustawione na sztywno na 3 bar - && ( Vel > 45 ) - && ( true == TestFlag( BrakeDelayFlag, bdelay_M ) ) ) { - // doliczenie hamowania hamulcem szynowym - FStand += TrackBrakeForce; - } - // w charakterystykach jest wartość siły hamowania zamiast nacisku + if ((true == TestFlag(BrakeMethod, bp_MHS)) && (PipePress < 3.0) // ustawione na sztywno na 3 bar + && (Vel > 45) && (true == TestFlag(BrakeDelayFlag, bdelay_M))) + { + // doliczenie hamowania hamulcem szynowym + FStand += TrackBrakeForce; + } + // w charakterystykach jest wartość siły hamowania zamiast nacisku - LastSwitchingTime += dt; - if( EngineType == TEngineType::ElectricSeriesMotor ) { - LastRelayTime += dt; - } + LastSwitchingTime += dt; + if (EngineType == TEngineType::ElectricSeriesMotor) + { + LastRelayTime += dt; + } - if( EngineType == TEngineType::ElectricSeriesMotor ) // potem ulepszyc! pantogtrafy! - { // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik - EngineVoltage = ( - Mains ? - EnginePowerSourceVoltage() : - 0.0 ); - if( CabActive == 0 ) { - EngineVoltage *= DirActive; - } - else { - EngineVoltage *= DirAbsolute; // DirActive*CabActive; - } - } // bo nie dzialalo - else { - EngineVoltage = ( - Power > 1.0 ? - std::max( - GetTrainsetHighVoltage(), - PantographVoltage ) : - 0.0 ); - } + if (EngineType == TEngineType::ElectricSeriesMotor) // potem ulepszyc! pantogtrafy! + { // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik + EngineVoltage = (Mains ? EnginePowerSourceVoltage() : 0.0); + if (CabActive == 0) + { + EngineVoltage *= DirActive; + } + else + { + EngineVoltage *= DirAbsolute; // DirActive*CabActive; + } + } // bo nie dzialalo + else + { + EngineVoltage = (Power > 1.0 ? std::max(GetTrainsetHighVoltage(), PantographVoltage) : 0.0); + } - FTrain = ( - Power > 0 ? - TractionForce( dt ) : - 0 ); + FTrain = (Power > 0 ? TractionForce(dt) : 0); double FT_factor = 1.0; - if (EngineType == TEngineType::ElectricInductionMotor && InvertersRatio > 0.0) { + if (EngineType == TEngineType::ElectricInductionMotor && InvertersRatio > 0.0) + { FT_factor = 1.0 / InvertersRatio; FTrain *= FT_factor; } - Fb = BrakeForce(RunningTrack); - // poslizg - auto Fwheels { FTrain - Fb * Sign( V ) }; - if( ( Vel > 0.1 ) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test - && ( std::abs(Fwheels) > TotalMassxg * Adhesive( RunningTrack.friction ) ) ) { - SlippingWheels = true; - } + Fb = BrakeForce(RunningTrack); + // poslizg + auto Fwheels{FTrain - Fb * Sign(V)}; + if ((Vel > 0.1) // crude trap, to prevent braked stationary vehicles from passing fb > mass * adhesive test + && (std::abs(Fwheels) > TotalMassxg * Adhesive(RunningTrack.friction))) + { + SlippingWheels = true; + } double temp_nrot = nrot; - if (true == SlippingWheels) { + if (true == SlippingWheels) + { temp_nrot = ComputeRotatingWheel(Fwheels - Sign(nrot * M_PI * WheelDiameter - V) * Adhesive(RunningTrack.friction) * TotalMassxg, dt, nrot); - if (Sign(nrot * M_PI * WheelDiameter - V)*Sign(temp_nrot * M_PI * WheelDiameter - V) < 0) + if (Sign(nrot * M_PI * WheelDiameter - V) * Sign(temp_nrot * M_PI * WheelDiameter - V) < 0) { SlippingWheels = false; temp_nrot = V / M_PI / WheelDiameter; } } - if (true == SlippingWheels) { - Fwheels = Sign(temp_nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction); - if (Fwheels*Sign(V)>0) + if (true == SlippingWheels) + { + Fwheels = Sign(temp_nrot * M_PI * WheelDiameter - V) * TotalMassxg * Adhesive(RunningTrack.friction); + if (Fwheels * Sign(V) > 0) { - FTrain = Fwheels + Fb*Sign(V); + FTrain = Fwheels + Fb * Sign(V); } - else if (FTrain*Sign(V)>0) + else if (FTrain * Sign(V) > 0) { - Fb = FTrain*Sign(V) - Fwheels*Sign(V); + Fb = FTrain * Sign(V) - Fwheels * Sign(V); } else { - double factor = (FTrain - Fb * Sign(V) != 0 ? Fwheels/(FTrain - Fb * Sign(V)) : 1.0); + double factor = (FTrain - Fb * Sign(V) != 0 ? Fwheels / (FTrain - Fb * Sign(V)) : 1.0); Fb *= factor; FTrain *= factor; } if (std::abs(nrot) < 0.1) { - WheelFlat = sqrt(square(WheelFlat) + abs(Fwheels) / NAxles*Vel*0.000002); + WheelFlat = sqrt(square(WheelFlat) + abs(Fwheels) / NAxles * Vel * 0.000002); } nrot = temp_nrot; - } - nrot_eps = (abs(nrot) - (old_nrot))/dt; - // doliczenie sił z innych pojazdów - for( int end = end::front; end <= end::rear; ++end ) { - if( Neighbours[ end ].vehicle != nullptr ) { - Couplers[ end ].CForce = CouplerForce( end, dt ); - FTrain += Couplers[ end ].CForce; - } - else - Couplers[ end ].CForce = 0; - } + } + nrot_eps = (abs(nrot) - (old_nrot)) / dt; + // doliczenie sił z innych pojazdów + for (int end = end::front; end <= end::rear; ++end) + { + if (Neighbours[end].vehicle != nullptr) + { + Couplers[end].CForce = CouplerForce(end, dt); + FTrain += Couplers[end].CForce; + } + else + Couplers[end].CForce = 0; + } - FStand += Fb; - // doliczenie składowej stycznej grawitacji + FStand += Fb; + // doliczenie składowej stycznej grawitacji FTrain /= FT_factor; - FTrain += TotalMassxg * RunningShape.dHtrack; - //!niejawne przypisanie zmiennej! - FTotal = FTrain - Sign(V) * FStand; + FTrain += TotalMassxg * RunningShape.dHtrack; + //! niejawne przypisanie zmiennej! + FTotal = FTrain - Sign(V) * FStand; } double TMoverParameters::BrakeForceR(double ratio, double velocity) { double press = 0; - if (MBPM>2) + if (MBPM > 2) { press = MaxBrakePress[1] + (MaxBrakePress[3] - MaxBrakePress[1]) * std::min(1.0, (TotalMass - Mass) / (MBPM - Mass)); } @@ -5109,16 +5076,16 @@ double TMoverParameters::BrakeForceR(double ratio, double velocity) { press = MaxBrakePress[3]; if (DynamicBrakeType == dbrake_automatic) - ratio = ratio + (1.5 - ratio)*std::min(1.0, Vel*0.02); - if ((BrakeDelayFlag&bdelay_R) && (BrakeMethod%128 != bp_Cosid) && (BrakeMethod % 128 != bp_D1) && (BrakeMethod % 128 != bp_D2) && (Power<1) && (velocity<40)) + ratio = ratio + (1.5 - ratio) * std::min(1.0, Vel * 0.02); + if ((BrakeDelayFlag & bdelay_R) && (BrakeMethod % 128 != bp_Cosid) && (BrakeMethod % 128 != bp_D1) && (BrakeMethod % 128 != bp_D2) && (Power < 1) && (velocity < 40)) ratio = ratio / 2; - if( ( TrainType == dt_DMU ) && ( velocity < 30.0 ) ) { - ratio -= 0.3; - } + if ((TrainType == dt_DMU) && (velocity < 30.0)) + { + ratio -= 0.3; + } } - } - return BrakeForceP(press*ratio, velocity); + return BrakeForceP(press * ratio, velocity); } double TMoverParameters::BrakeForceP(double press, double velocity) @@ -5126,7 +5093,7 @@ double TMoverParameters::BrakeForceP(double press, double velocity) double BFP = 0; double K = (((press * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj) * BrakeRigEff; K *= static_cast(BrakeCylNo) / (NAxles * std::max(1, NBpA)); - BFP = Hamulec->GetFC(velocity, K)*K*(NAxles * std::max(1, NBpA)) * 1000; + BFP = Hamulec->GetFC(velocity, K) * K * (NAxles * std::max(1, NBpA)) * 1000; return BFP; } @@ -5134,66 +5101,71 @@ double TMoverParameters::BrakeForceP(double press, double velocity) // Q: 20160713 // oblicza siłę na styku koła i szyny // ************************************************************************************************* -double TMoverParameters::BrakeForce( TTrackParam const &Track ) { +double TMoverParameters::BrakeForce(TTrackParam const &Track) +{ - double K{ 0 }, Fb{ 0 }, sm{ 0 }; + double K{0}, Fb{0}, sm{0}; - switch( LocalBrake ) { - case TLocalBrake::ManualBrake: { - K = MaxBrakeForce * ManualBrakeRatio(); - break; - } - case TLocalBrake::HydraulicBrake: { - K = MaxBrakeForce * LocalBrakeRatio(); - break; - } - default: { - break; - } - } + switch (LocalBrake) + { + case TLocalBrake::ManualBrake: + { + K = MaxBrakeForce * ManualBrakeRatio(); + break; + } + case TLocalBrake::HydraulicBrake: + { + K = MaxBrakeForce * LocalBrakeRatio(); + break; + } + default: + { + break; + } + } - if (MBrake == true) - { - K = MaxBrakeForce * ManualBrakeRatio(); - } + if (MBrake == true) + { + K = MaxBrakeForce * ManualBrakeRatio(); + } if (SpringBrake.IsReady) K += std::max(0.0, SpringBrake.MinForcePressure - SpringBrake.Cylinder->P()) * SpringBrake.MaxBrakeForce; - u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj; - if (u * BrakeRigEff > Ntotal) // histereza na nacisku klockow - Ntotal = u * BrakeRigEff; - else - { - u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj; - if (u * (2.0 - BrakeRigEff) < Ntotal) // histereza na nacisku klockow - Ntotal = u * (2.0 - BrakeRigEff); - } + u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj; + if (u * BrakeRigEff > Ntotal) // histereza na nacisku klockow + Ntotal = u * BrakeRigEff; + else + { + u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj; + if (u * (2.0 - BrakeRigEff) < Ntotal) // histereza na nacisku klockow + Ntotal = u * (2.0 - BrakeRigEff); + } - auto const NBrakeAxles { NAxles }; + auto const NBrakeAxles{NAxles}; - if (NBrakeAxles * NBpA > 0) - { - if (Ntotal > 0) // nie luz - K += Ntotal; // w kN - K *= static_cast(BrakeCylNo) / (NBrakeAxles * static_cast(NBpA)); // w kN na os - } - if ((BrakeSystem == TBrakeSystem::Pneumatic) || (BrakeSystem == TBrakeSystem::ElectroPneumatic)) - { - u = Hamulec->GetFC(Vel, K); - UnitBrakeForce = u * K * 1000.0; // sila na jeden klocek w N - } - else - UnitBrakeForce = K * 1000.0; - // if (LocalBrake=ManualBrake)or(MBrake=true)) and (BrakePress<0.3) then - // Fb:=UnitBrakeForce*NBpA {ham. reczny dziala na jedna os} - // else //yB: to nie do konca ma sens, ponieważ ręczny w wagonie działa na jeden cylinder - // hamulcowy/wózek, dlatego potrzebne są oddzielnie liczone osie - Fb = UnitBrakeForce * NBrakeAxles * std::max(1, NBpA); + if (NBrakeAxles * NBpA > 0) + { + if (Ntotal > 0) // nie luz + K += Ntotal; // w kN + K *= static_cast(BrakeCylNo) / (NBrakeAxles * static_cast(NBpA)); // w kN na os + } + if ((BrakeSystem == TBrakeSystem::Pneumatic) || (BrakeSystem == TBrakeSystem::ElectroPneumatic)) + { + u = Hamulec->GetFC(Vel, K); + UnitBrakeForce = u * K * 1000.0; // sila na jeden klocek w N + } + else + UnitBrakeForce = K * 1000.0; + // if (LocalBrake=ManualBrake)or(MBrake=true)) and (BrakePress<0.3) then + // Fb:=UnitBrakeForce*NBpA {ham. reczny dziala na jedna os} + // else //yB: to nie do konca ma sens, ponieważ ręczny w wagonie działa na jeden cylinder + // hamulcowy/wózek, dlatego potrzebne są oddzielnie liczone osie + Fb = UnitBrakeForce * NBrakeAxles * std::max(1, NBpA); - // u:=((BrakePress*P2FTrans)-BrakeCylSpring*BrakeCylMult[BCMFlag]/BrakeCylNo-0.83*BrakeSlckAdj/(BrakeCylNo))*BrakeCylNo; - // { end; } - return Fb; + // u:=((BrakePress*P2FTrans)-BrakeCylSpring*BrakeCylMult[BCMFlag]/BrakeCylNo-0.83*BrakeSlckAdj/(BrakeCylNo))*BrakeCylNo; + // { end; } + return Fb; } // ************************************************************************************************* @@ -5202,534 +5174,542 @@ double TMoverParameters::BrakeForce( TTrackParam const &Track ) { // ************************************************************************************************* double TMoverParameters::FrictionForce() const { - double FF = 0; - // ABu 240205: chyba juz ekstremalnie zoptymalizowana funkcja liczaca sily tarcia - if (abs(V) > 0.01) - FF = (FrictConst1 * V * V) + FrictConst2d; - else - FF = (FrictConst1 * V * V) + FrictConst2s; - return FF; + double FF = 0; + // ABu 240205: chyba juz ekstremalnie zoptymalizowana funkcja liczaca sily tarcia + if (abs(V) > 0.01) + FF = (FrictConst1 * V * V) + FrictConst2d; + else + FF = (FrictConst1 * V * V) + FrictConst2s; + return FF; } - - - // ************************************************************************************************* // Q: 20160713 // Oblicza przyczepność // ************************************************************************************************* -double TMoverParameters::Adhesive(double staticfriction) const +double TMoverParameters::Adhesive(double staticfriction) const { - double adhesion = 0.0; - const double adh_factor = 0.25; //współczynnik określający, jak bardzo spada tarcie przy poślizgu - const double slipfactor = 0.33; //współczynnik określający, jak szybko spada tarcie przy poślizgu - const double sandfactor = 1.25; //współczynnik określający, jak mocno pomaga piasek -/* - // ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS? - // w kazdym razie zaciemni kod na pewno :) - if (SlippingWheels == false) - { - if (SandDose) - adhesion = (Max0R(staticfriction * (100.0 + Vel) / ((50.0 + Vel) * 11.0), 0.048)) * - (11.0 - 2.0 * Random(0.0, 1.0)); - else - adhesion = (staticfriction * (100.0 + Vel) / ((50.0 + Vel) * 10.0)) * - (11.0 - 2.0 * Random(0.0, 1.0)); - } - else - { - if (SandDose) - adhesion = (0.048) * (11.0 - 2.0 * Random(0.0, 1.0)); - else - adhesion = (staticfriction * 0.02) * (11.0 - 2.0 * Random(0.0, 1.0)); - } - // WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3 - return adhesion; + double adhesion = 0.0; + const double adh_factor = 0.25; // współczynnik określający, jak bardzo spada tarcie przy poślizgu + const double slipfactor = 0.33; // współczynnik określający, jak szybko spada tarcie przy poślizgu + const double sandfactor = 1.25; // współczynnik określający, jak mocno pomaga piasek + /* + // ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS? + // w kazdym razie zaciemni kod na pewno :) + if (SlippingWheels == false) + { + if (SandDose) + adhesion = (Max0R(staticfriction * (100.0 + Vel) / ((50.0 + Vel) * 11.0), 0.048)) * + (11.0 - 2.0 * Random(0.0, 1.0)); + else + adhesion = (staticfriction * (100.0 + Vel) / ((50.0 + Vel) * 10.0)) * + (11.0 - 2.0 * Random(0.0, 1.0)); + } + else + { + if (SandDose) + adhesion = (0.048) * (11.0 - 2.0 * Random(0.0, 1.0)); + else + adhesion = (staticfriction * 0.02) * (11.0 - 2.0 * Random(0.0, 1.0)); + } + // WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3 + return adhesion; - //wersja druga - if( true == SlippingWheels ) { + //wersja druga + if( true == SlippingWheels ) { - if( true == SandDose ) { adhesion = 0.48; } - else { adhesion = staticfriction * 0.2; } - } - else { + if( true == SandDose ) { adhesion = 0.48; } + else { adhesion = staticfriction * 0.2; } + } + else { - if( true == SandDose ) { adhesion = std::max( staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ) * 1.1, 0.48 ); } - else { adhesion = staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ); } - } -// adhesion *= ( 0.9 + 0.2 * Random() ); -*/ - //wersja3 by youBy - uwzględnia naturalne mikropoślizgi i wpływ piasecznicy, usuwa losowość z pojazdu + if( true == SandDose ) { adhesion = std::max( staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ) * 1.1, 0.48 ); } + else { adhesion = staticfriction * ( 100.0 + Vel ) / ( 50.0 + Vel ); } + } + // adhesion *= ( 0.9 + 0.2 * Random() ); + */ + // wersja3 by youBy - uwzględnia naturalne mikropoślizgi i wpływ piasecznicy, usuwa losowość z pojazdu double Vwheels = nrot * M_PI * WheelDiameter; // predkosc liniowa koła wynikająca z obrotowej - double deltaV = V - Vwheels; //poślizg - różnica prędkości w punkcie styku koła i szyny - deltaV = std::max(0.0, std::abs(deltaV) - 0.25); //mikropoślizgi do ok. 0,25 m/s nie zrywają przyczepności - Vwheels = std::abs( Vwheels ); - adhesion = staticfriction * (28 + Vwheels) / (14 + Vwheels) * ((SandDose? sandfactor : 1) - (1 - adh_factor)*(deltaV / (deltaV + slipfactor))); + double deltaV = V - Vwheels; // poślizg - różnica prędkości w punkcie styku koła i szyny + deltaV = std::max(0.0, std::abs(deltaV) - 0.25); // mikropoślizgi do ok. 0,25 m/s nie zrywają przyczepności + Vwheels = std::abs(Vwheels); + adhesion = staticfriction * (28 + Vwheels) / (14 + Vwheels) * ((SandDose ? sandfactor : 1) - (1 - adh_factor) * (deltaV / (deltaV + slipfactor))); - return adhesion; + return adhesion; } // ************************************************************************************************* // Q: 20160713 // Obliczanie sił dzialających na sprzęgach // ************************************************************************************************* -double TMoverParameters::CouplerForce( int const End, double dt ) { +double TMoverParameters::CouplerForce(int const End, double dt) +{ - auto &coupler { Couplers[ End ] }; - auto *othervehicle { Neighbours[ End ].vehicle->MoverParameters }; - auto const otherend { Neighbours[ End ].vehicle_end }; - auto &othercoupler { othervehicle->Couplers[ otherend ] }; + auto &coupler{Couplers[End]}; + auto *othervehicle{Neighbours[End].vehicle->MoverParameters}; + auto const otherend{Neighbours[End].vehicle_end}; + auto &othercoupler{othervehicle->Couplers[otherend]}; - auto const othervehiclemove { ( othervehicle->dMoveLen * DirPatch( End, otherend ) ) }; - auto const initialdistance { Neighbours[ End ].distance }; // odległość od sprzęgu sąsiada - auto const distancedelta { ( - End == end::front ? - othervehiclemove - dMoveLen : - dMoveLen - othervehiclemove ) }; + auto const othervehiclemove{(othervehicle->dMoveLen * DirPatch(End, otherend))}; + auto const initialdistance{Neighbours[End].distance}; // odległość od sprzęgu sąsiada + auto const distancedelta{(End == end::front ? othervehiclemove - dMoveLen : dMoveLen - othervehiclemove)}; - auto const newdistance { initialdistance + 10.0 * distancedelta }; + auto const newdistance{initialdistance + 10.0 * distancedelta}; - auto const dV { V - ( othervehicle->V * DirPatch( End, otherend ) ) }; - auto const absdV { std::abs( dV ) }; + auto const dV{V - (othervehicle->V * DirPatch(End, otherend))}; + auto const absdV{std::abs(dV)}; - // potentially generate sounds on clash or stretch - if( ( newdistance < 0.0 ) - && ( coupler.Dist > newdistance ) - && ( dV < -0.1 ) - && ( false == coupler.has_adapter() ) ) { // HACK: with adapter present we presume buffers won't clash - // 090503: dzwieki pracy zderzakow - SetFlag( - coupler.sounds, - ( absdV > 5.0 ? - ( sound::bufferclash | sound::loud ) : - sound::bufferclash ) ); - } - else if( ( coupler.CouplingFlag != coupling::faux ) - && ( newdistance > 0.001 ) - && ( coupler.Dist <= 0.001 ) - && ( absdV > 0.005 ) - && ( Vel > 1.0 ) ) { - // 090503: dzwieki pracy sprzegu - SetFlag( - coupler.sounds, - ( absdV > 0.035 ? - ( sound::couplerstretch | sound::loud ) : - sound::couplerstretch ) ); - } + // potentially generate sounds on clash or stretch + if ((newdistance < 0.0) && (coupler.Dist > newdistance) && (dV < -0.1) && (false == coupler.has_adapter())) + { // HACK: with adapter present we presume buffers won't clash + // 090503: dzwieki pracy zderzakow + SetFlag(coupler.sounds, (absdV > 5.0 ? (sound::bufferclash | sound::loud) : sound::bufferclash)); + } + else if ((coupler.CouplingFlag != coupling::faux) && (newdistance > 0.001) && (coupler.Dist <= 0.001) && (absdV > 0.005) && (Vel > 1.0)) + { + // 090503: dzwieki pracy sprzegu + SetFlag(coupler.sounds, (absdV > 0.035 ? (sound::couplerstretch | sound::loud) : sound::couplerstretch)); + } - coupler.CheckCollision = false; - coupler.Dist = 0.0; + coupler.CheckCollision = false; + coupler.Dist = 0.0; - double CF { 0.0 }; + double CF{0.0}; - if( ( coupler.CouplingFlag == coupling::faux ) - && ( initialdistance > 0.05 ) ) { // arbitrary distance - // potentially reset auto coupling lock - coupler.AutomaticCouplingAllowed = true; - } + if ((coupler.CouplingFlag == coupling::faux) && (initialdistance > 0.05)) + { // arbitrary distance + // potentially reset auto coupling lock + coupler.AutomaticCouplingAllowed = true; + } - if( ( coupler.CouplingFlag != coupling::faux ) - || ( initialdistance < 0 ) ) { + if ((coupler.CouplingFlag != coupling::faux) || (initialdistance < 0)) + { - coupler.Dist = clamp( newdistance, ( coupler.has_adapter() ? 0 : -coupler.DmaxB ), coupler.DmaxC ); + coupler.Dist = clamp(newdistance, (coupler.has_adapter() ? 0 : -coupler.DmaxB), coupler.DmaxC); - double BetaAvg = 0; - double Fmax = 0; + double BetaAvg = 0; + double Fmax = 0; - if( coupler.CouplingFlag == coupling::faux ) { + if (coupler.CouplingFlag == coupling::faux) + { - BetaAvg = coupler.beta; - Fmax = (coupler.FmaxC + coupler.FmaxB) * CouplerTune; - } - else { - // usrednij bo wspolny sprzeg - BetaAvg = 0.5 * ( coupler.beta + othercoupler.beta ); - Fmax = 0.5 * ( coupler.FmaxC + coupler.FmaxB + othercoupler.FmaxC + othercoupler.FmaxB ) * CouplerTune; - } - auto const distDelta { std::abs( newdistance ) - std::abs( coupler.Dist ) }; // McZapkie-191103: poprawka na histereze + BetaAvg = coupler.beta; + Fmax = (coupler.FmaxC + coupler.FmaxB) * CouplerTune; + } + else + { + // usrednij bo wspolny sprzeg + BetaAvg = 0.5 * (coupler.beta + othercoupler.beta); + Fmax = 0.5 * (coupler.FmaxC + coupler.FmaxB + othercoupler.FmaxC + othercoupler.FmaxB) * CouplerTune; + } + auto const distDelta{std::abs(newdistance) - std::abs(coupler.Dist)}; // McZapkie-191103: poprawka na histereze - if (newdistance > 0) { + if (newdistance > 0) + { - if( distDelta > 0 ) { - CF = ( -( coupler.SpringKC + othercoupler.SpringKC ) * coupler.Dist / 2.0 ) * DirF( End ) - - Fmax * dV * BetaAvg; - } - else { - CF = ( -( coupler.SpringKC + othercoupler.SpringKC ) * coupler.Dist / 2.0 ) * DirF( End ) * BetaAvg - - Fmax * dV * BetaAvg; - } - // liczenie sily ze sprezystosci sprzegu - if( newdistance > ( coupler.DmaxC + othercoupler.DmaxC ) ) { - // zderzenie - coupler.CheckCollision = true; - } - if( std::abs( CF ) > coupler.FmaxC ) { - // coupler is stretched with excessive force, may break - coupler.stretch_duration += dt; - // give coupler 1 sec of leeway to account for simulation glitches, before checking whether it breaks - // (arbitrary) chance to break grows from 10-100% over 10 sec period - if( Global.crash_damage && ( coupler.stretch_duration > 1.f ) - && ( Random() < ( coupler.stretch_duration * 0.1f * dt ) ) ) { - damage_coupler( End ); - } - } - else { - coupler.stretch_duration = 0.f; - } - } - if( newdistance < 0 ) { + if (distDelta > 0) + { + CF = (-(coupler.SpringKC + othercoupler.SpringKC) * coupler.Dist / 2.0) * DirF(End) - Fmax * dV * BetaAvg; + } + else + { + CF = (-(coupler.SpringKC + othercoupler.SpringKC) * coupler.Dist / 2.0) * DirF(End) * BetaAvg - Fmax * dV * BetaAvg; + } + // liczenie sily ze sprezystosci sprzegu + if (newdistance > (coupler.DmaxC + othercoupler.DmaxC)) + { + // zderzenie + coupler.CheckCollision = true; + } + if (std::abs(CF) > coupler.FmaxC) + { + // coupler is stretched with excessive force, may break + coupler.stretch_duration += dt; + // give coupler 1 sec of leeway to account for simulation glitches, before checking whether it breaks + // (arbitrary) chance to break grows from 10-100% over 10 sec period + if (Global.crash_damage && (coupler.stretch_duration > 1.f) && (Random() < (coupler.stretch_duration * 0.1f * dt))) + { + damage_coupler(End); + } + } + else + { + coupler.stretch_duration = 0.f; + } + } + if (newdistance < 0) + { - if( distDelta > 0 ) { - CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End ) - - Fmax * dV * BetaAvg; - } - else { - CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End ) * BetaAvg - - Fmax * dV * BetaAvg; - } - // liczenie sily ze sprezystosci zderzaka - auto const collisiondistance { ( - ( coupler.has_adapter() || othercoupler.has_adapter() ) ? - std::min( coupler.DmaxB, othercoupler.DmaxB ) : // HACK: only take into account buffering ability of automatic coupler - coupler.DmaxB + othercoupler.DmaxB - ) }; - if( -newdistance > collisiondistance ) { - // zderzenie - coupler.CheckCollision = true; - } - if( -newdistance >= std::min( collisiondistance, dEpsilon ) ) { - if( ( coupler.type() == TCouplerType::Automatic ) - && ( coupler.type() == othercoupler.type() ) - && ( coupler.CouplingFlag == coupling::faux ) - && ( coupler.AutomaticCouplingAllowed && othercoupler.AutomaticCouplingAllowed ) ) { - // sprzeganie wagonow z samoczynnymi sprzegami - auto couplingtype { coupler.AutomaticCouplingFlag & othercoupler.AutomaticCouplingFlag }; - // potentially exclude incompatible control coupling - if( coupler.control_type != othercoupler.control_type ) { - couplingtype &= ~( coupling::control ); - } + if (distDelta > 0) + { + CF = (-(coupler.SpringKB + othercoupler.SpringKB) * coupler.Dist / 2.0) * DirF(End) - Fmax * dV * BetaAvg; + } + else + { + CF = (-(coupler.SpringKB + othercoupler.SpringKB) * coupler.Dist / 2.0) * DirF(End) * BetaAvg - Fmax * dV * BetaAvg; + } + // liczenie sily ze sprezystosci zderzaka + auto const collisiondistance{((coupler.has_adapter() || othercoupler.has_adapter()) ? + std::min(coupler.DmaxB, othercoupler.DmaxB) : // HACK: only take into account buffering ability of automatic coupler + coupler.DmaxB + othercoupler.DmaxB)}; + if (-newdistance > collisiondistance) + { + // zderzenie + coupler.CheckCollision = true; + } + if (-newdistance >= std::min(collisiondistance, dEpsilon)) + { + if ((coupler.type() == TCouplerType::Automatic) && (coupler.type() == othercoupler.type()) && (coupler.CouplingFlag == coupling::faux) && + (coupler.AutomaticCouplingAllowed && othercoupler.AutomaticCouplingAllowed)) + { + // sprzeganie wagonow z samoczynnymi sprzegami + auto couplingtype{coupler.AutomaticCouplingFlag & othercoupler.AutomaticCouplingFlag}; + // potentially exclude incompatible control coupling + if (coupler.control_type != othercoupler.control_type) + { + couplingtype &= ~(coupling::control); + } - if( Attach( End, otherend, othervehicle, couplingtype ) ) { - // HACK: we're reusing sound enum to mark whether vehicle was connected to another - SetFlag( AIFlag, sound::attachcoupler ); - coupler.AutomaticCouplingAllowed = false; - othercoupler.AutomaticCouplingAllowed = false; - } -/* - coupler.CouplingFlag = ( coupler.AutomaticCouplingFlag & othercoupler.AutomaticCouplingFlag ); - SetFlag( coupler.sounds, sound::attachcoupler ); -*/ - } - } - } - } + if (Attach(End, otherend, othervehicle, couplingtype)) + { + // HACK: we're reusing sound enum to mark whether vehicle was connected to another + SetFlag(AIFlag, sound::attachcoupler); + coupler.AutomaticCouplingAllowed = false; + othercoupler.AutomaticCouplingAllowed = false; + } + /* + coupler.CouplingFlag = ( coupler.AutomaticCouplingFlag & othercoupler.AutomaticCouplingFlag ); + SetFlag( coupler.sounds, sound::attachcoupler ); + */ + } + } + } + } - if( coupler.CouplingFlag != coupling::faux ) { - // uzgadnianie prawa Newtona - othervehicle->Couplers[ 1 - End ].CForce = -CF; - } + if (coupler.CouplingFlag != coupling::faux) + { + // uzgadnianie prawa Newtona + othervehicle->Couplers[1 - End].CForce = -CF; + } - return CF; + return CF; } // ************************************************************************************************* // Q: 20160714 // oblicza sile trakcyjna lokomotywy (dla elektrowozu tez calkowity prad) // ************************************************************************************************* -double TMoverParameters::TractionForce( double dt ) { - double PosRatio, dmoment, dtrans, tmp; +double TMoverParameters::TractionForce(double dt) +{ + double PosRatio, dmoment, dtrans, tmp; - Ft = 0; - dtrans = 0; - dmoment = 0; - // youBy - switch( EngineType ) { - case TEngineType::DieselElectric: { - if( ( true == Mains ) - && ( true == FuelPump.is_active ) ) { + Ft = 0; + dtrans = 0; + dmoment = 0; + // youBy + switch (EngineType) + { + case TEngineType::DieselElectric: + { + if ((true == Mains) && (true == FuelPump.is_active)) + { - if (EIMCtrlType > 0) //sterowanie cyfrowe - tmp = (DElist[0].RPM + ((DElist[MainCtrlPosNo].RPM - DElist[0].RPM) * std::max(0.0,eimic_real))) / 60.0; - else - tmp = DElist[ ( ControlPressureSwitch ? MainCtrlNoPowerPos() : MainCtrlPos ) ].RPM / 60.0; + if (EIMCtrlType > 0) // sterowanie cyfrowe + tmp = (DElist[0].RPM + ((DElist[MainCtrlPosNo].RPM - DElist[0].RPM) * std::max(0.0, eimic_real))) / 60.0; + else + tmp = DElist[(ControlPressureSwitch ? MainCtrlNoPowerPos() : MainCtrlPos)].RPM / 60.0; - if( ( true == HeatingAllow ) - && ( HeatingPower > 0 ) - && ( EngineHeatingRPM > 0 ) ) { - // bump engine revolutions up if needed, when heating is on - tmp = - std::max( - tmp, - std::min( - EngineMaxRPM(), - EngineHeatingRPM ) - / 60.0 ); - } - // NOTE: fake dizel_fill calculation for the sake of smoke emitter which uses this parameter to determine smoke opacity - dizel_fill = clamp( 0.2 + 0.35 * ( tmp - enrot ) + 0.5 * ( std::abs( Im ) / DElist[ MainCtrlPosNo ].Imax ), 0.05, 1.0 ); - } - else { - tmp = 0.0; - dizel_fill = 0.0; - } + if ((true == HeatingAllow) && (HeatingPower > 0) && (EngineHeatingRPM > 0)) + { + // bump engine revolutions up if needed, when heating is on + tmp = std::max(tmp, std::min(EngineMaxRPM(), EngineHeatingRPM) / 60.0); + } + // NOTE: fake dizel_fill calculation for the sake of smoke emitter which uses this parameter to determine smoke opacity + dizel_fill = clamp(0.2 + 0.35 * (tmp - enrot) + 0.5 * (std::abs(Im) / DElist[MainCtrlPosNo].Imax), 0.05, 1.0); + } + else + { + tmp = 0.0; + dizel_fill = 0.0; + } - if( enrot != tmp ) { - enrot = clamp( - enrot + ( dt / dizel_AIM ) * ( - enrot < tmp ? - 1.0 : - -1.0 * dizel_RevolutionsDecreaseRate ), // NOTE: revolutions typically drop faster than they rise - 0.0, std::max( tmp, enrot ) ); - if( std::abs( tmp - enrot ) < 0.001 ) { - enrot = tmp; - } - } - break; - } - case TEngineType::DieselEngine: { - if( ShuntMode ) // dodatkowa przekładnia np. dla 2Ls150 - dtrans = AnPos * Transmision.Ratio * MotorParam[ ScndCtrlActualPos ].mIsat; - else - dtrans = Transmision.Ratio * MotorParam[ ScndCtrlActualPos ].mIsat; + if (enrot != tmp) + { + enrot = clamp(enrot + (dt / dizel_AIM) * (enrot < tmp ? 1.0 : -1.0 * dizel_RevolutionsDecreaseRate), // NOTE: revolutions typically drop faster than they rise + 0.0, std::max(tmp, enrot)); + if (std::abs(tmp - enrot) < 0.001) + { + enrot = tmp; + } + } + break; + } + case TEngineType::DieselEngine: + { + if (ShuntMode) // dodatkowa przekładnia np. dla 2Ls150 + dtrans = AnPos * Transmision.Ratio * MotorParam[ScndCtrlActualPos].mIsat; + else + dtrans = Transmision.Ratio * MotorParam[ScndCtrlActualPos].mIsat; - dmoment = dizel_Momentum( dizel_fill, dtrans * nrot * DirActive, dt ); // oblicza tez enrot - break; - } - default: { - enrot = Transmision.Ratio * nrot; - break; - } - } + dmoment = dizel_Momentum(dizel_fill, dtrans * nrot * DirActive, dt); // oblicza tez enrot + break; + } + default: + { + enrot = Transmision.Ratio * nrot; + break; + } + } - eAngle += enrot * dt; - if( eAngle > M_PI * 2.0 ) - eAngle = std::fmod( eAngle, M_PI * 2.0 ); -/* - while (eAngle > M_PI * 2.0) - // eAngle = Pirazy2 - eAngle; <- ABu: a nie czasem tak, jak nizej? - eAngle -= M_PI * 2.0; -*/ - // hunter-091012: przeniesione z if DirActive<>0 (zeby po zejsciu z kierunku dalej spadala predkosc wentylatorow) - // wentylatory rozruchowe - // TBD, TODO: move this to update, it doesn't exactly have much to do with traction - switch( EngineType ) { + eAngle += enrot * dt; + if (eAngle > M_PI * 2.0) + eAngle = std::fmod(eAngle, M_PI * 2.0); + /* + while (eAngle > M_PI * 2.0) + // eAngle = Pirazy2 - eAngle; <- ABu: a nie czasem tak, jak nizej? + eAngle -= M_PI * 2.0; + */ + // hunter-091012: przeniesione z if DirActive<>0 (zeby po zejsciu z kierunku dalej spadala predkosc wentylatorow) + // wentylatory rozruchowe + // TBD, TODO: move this to update, it doesn't exactly have much to do with traction + switch (EngineType) + { - case TEngineType::ElectricSeriesMotor: { - if( true == Mains ) { - switch( RVentType ) { + case TEngineType::ElectricSeriesMotor: + { + if (true == Mains) + { + switch (RVentType) + { - case 1: { // manual - if( ( true == RVentForceOn ) - || ( ( DirActive != 0 ) - && ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) ) { - RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt; - } - else { - RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); - } - break; - } - - case 2: { // automatic - auto const motorcurrent{ std::min( ImaxHi, std::abs( Im ) ) }; - if( ( std::abs( Itot ) > RVentMinI ) - && ( RList[ MainCtrlActualPos ].R > RVentCutOff ) ) { - - RventRot += - ( RVentnmax - * std::min( 1.0, ( ( motorcurrent / NPoweredAxles ) / RVentMinI ) ) - * motorcurrent / ImaxLo - - RventRot ) - * RVentSpeed * dt; - } - else if( ( DynamicBrakeType == dbrake_automatic ) - && ( true == DynamicBrakeFlag ) ) { - RventRot += ( RVentnmax * motorcurrent / ImaxLo - RventRot ) * RVentSpeed * dt; - } - else if( RVentForceOn ) { - RventRot += ( RVentnmax - RventRot ) * RVentSpeed * dt; - } - else { - RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); - } - break; - } - - default: { - break; - } - } // rventtype - } // mains - else { - RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); - } - break; - } - - case TEngineType::DieselElectric: { - // NOTE: for this type RventRot is the speed of motor blowers; we also update radiator fans while at it - if( true == Mains ) { - // TBD, TODO: currently ignores RVentType, fix this? - RventRot += clamp( enrot - RventRot, -100.0, 50.0 ) * dt; - dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt; - dizel_heat.rpmw2 += clamp( dizel_heat.rpmwz2 - dizel_heat.rpmw2, -100.f, 50.f ) * dt; - } - else { - RventRot *= std::max( 0.0, 1.0 - RVentSpeed * dt ); - dizel_heat.rpmw *= std::max( 0.0, 1.0 - dizel_heat.rpmw * dt ); - dizel_heat.rpmw2 *= std::max( 0.0, 1.0 - dizel_heat.rpmw2 * dt ); - } - break; - } - - case TEngineType::DieselEngine: { - // NOTE: we update only radiator fans, as vehicles with diesel engine don't have other ventilators - if( true == Mains ) { - dizel_heat.rpmw += clamp( dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f ) * dt; - dizel_heat.rpmw2 += clamp( dizel_heat.rpmwz2 - dizel_heat.rpmw2, -100.f, 50.f ) * dt; - } - else { - dizel_heat.rpmw *= std::max( 0.0, 1.0 - dizel_heat.rpmw * dt ); - dizel_heat.rpmw2 *= std::max( 0.0, 1.0 - dizel_heat.rpmw2 * dt ); - } - break; - } - - default: { - break; - } - } - - switch( EngineType ) { - case TEngineType::Dumb: { - PosRatio = ( MainCtrlPos + ScndCtrlPos ) / ( MainCtrlPosNo + ScndCtrlPosNo + 0.01 ); - EnginePower = /*1000.0 **/ Power * PosRatio; - break; - } - case TEngineType::DieselEngine: { - dizel_Power = Mm * enrot * (2.0 * M_PI / 1000.0); - EnginePower = ( dizel_Mstand + Mm ) * enrot * ( 2.0 * M_PI / 1000.0 ); - if( MainCtrlPowerPos() > 1 ) { - // dodatkowe opory z powodu sprezarki} -// dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); //yB: skąd to w ogóle się bierze?! - } - break; - } - case TEngineType::DieselElectric: { - EnginePower = 0; // the actual calculation is done in two steps later in the method - break; - } - default: { - break; - } - } - - switch( EngineType ) { - - case TEngineType::ElectricSeriesMotor: { - // update the state of voltage relays - auto const voltage { std::max( GetTrainsetHighVoltage(), PantographVoltage ) }; - NoVoltRelay = - ( EnginePowerSource.SourceType != TPowerSource::CurrentCollector ) - || ( voltage >= EnginePowerSource.CollectorParameters.MinV ); - OvervoltageRelay = - ( EnginePowerSource.SourceType != TPowerSource::CurrentCollector ) - || ( voltage <= EnginePowerSource.CollectorParameters.MaxV ) - || ( false == EnginePowerSource.CollectorParameters.OVP ); - // wywalanie szybkiego z powodu niewłaściwego napięcia - EventFlag |= ( ( true == Mains ) - && ( ( false == NoVoltRelay ) || ( false == OvervoltageRelay ) ) - && ( MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ) ) ); // TODO: check whether we need to send this EMU-wide - break; - } - - case TEngineType::ElectricInductionMotor: { - // TODO: check if we can use instead the code for electricseriesmotor - if( ( Mains ) ) { - // nie wchodzić w funkcję bez potrzeby - if( ( std::max( GetTrainsetHighVoltage(), PantographVoltage ) < EnginePowerSource.CollectorParameters.MinV ) - || ( std::max( GetTrainsetHighVoltage(), PantographVoltage ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) { - MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ); // TODO: check whether we need to send this EMU-wide - } - } - break; - } - - case TEngineType::DieselElectric: { - // TODO: move this to the auto relay check when the electric engine code paths are unified - StLinFlag |= ( - ( Mains ) - && ( false == StLinFlag ) - && ( MainCtrlPowerPos() == 1 ) ); - StLinFlag &= MotorConnectorsCheck(); - StLinFlag &= ( MainCtrlPowerPos() > 0 ); - - break; - } - - default: { - break; - } - } - - if (DirActive != 0) - switch (EngineType) - { - case TEngineType::Dumb: - { - if (Mains && (CabActive != 0)) - { - if (Vel > 0.1) - { - Ft = std::min(1000.0 * Power / std::abs(V), Ftmax) * PosRatio; - } - else { - Ft = Ftmax * PosRatio; - } - Ft = Ft * DirAbsolute; // DirActive*CabActive; - } - else { - Ft = 0; - } - break; - } // Dumb - - case TEngineType::WheelsDriven: - { - if (EnginePowerSource.SourceType == TPowerSource::InternalSource) - if (EnginePowerSource.PowerType == TPowerType::BioPower) - Ft = Sign(sin(eAngle)) * PulseForce * Transmision.Ratio; - PulseForceTimer = PulseForceTimer + dt; - if (PulseForceTimer > CtrlDelay) - { - PulseForce = 0; - if (PulseForceCount > 0) - PulseForceCount--; - } - EnginePower = Ft * (1.0 + Vel); - break; - } // WheelsDriven - - case TEngineType::ElectricSeriesMotor: - { - // enrot:=Transmision.Ratio*nrot; - // yB: szereg dwoch sekcji w ET42 - if ((TrainType == dt_ET42) && (Imax == ImaxHi)) - EngineVoltage = EngineVoltage / 2.0; - Mm = Momentum(Current(enrot, EngineVoltage)); // oblicza tez prad p/slinik - - if (TrainType == dt_ET42) - { - if (Imax == ImaxHi) - EngineVoltage = EngineVoltage * 2; - if ((DynamicBrakeFlag) && (abs(Im) > 300)) // przeiesione do mover.cpp - FuseOff(); - } - if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) - { - if (TUHEX_Stages > 0) //hamowanie wielostopniowe, nadpisuje wartości domyślne + case 1: + { // manual + if ((true == RVentForceOn) || ((DirActive != 0) && (RList[MainCtrlActualPos].R > RVentCutOff))) { - if (Vel > 100) TUHEX_StageActual = std::min(TUHEX_StageActual, 1); + RventRot += (RVentnmax - RventRot) * RVentSpeed * dt; + } + else + { + RventRot *= std::max(0.0, 1.0 - RVentSpeed * dt); + } + break; + } + + case 2: + { // automatic + auto const motorcurrent{std::min(ImaxHi, std::abs(Im))}; + if ((std::abs(Itot) > RVentMinI) && (RList[MainCtrlActualPos].R > RVentCutOff)) + { + + RventRot += (RVentnmax * std::min(1.0, ((motorcurrent / NPoweredAxles) / RVentMinI)) * motorcurrent / ImaxLo - RventRot) * RVentSpeed * dt; + } + else if ((DynamicBrakeType == dbrake_automatic) && (true == DynamicBrakeFlag)) + { + RventRot += (RVentnmax * motorcurrent / ImaxLo - RventRot) * RVentSpeed * dt; + } + else if (RVentForceOn) + { + RventRot += (RVentnmax - RventRot) * RVentSpeed * dt; + } + else + { + RventRot *= std::max(0.0, 1.0 - RVentSpeed * dt); + } + break; + } + + default: + { + break; + } + } // rventtype + } // mains + else + { + RventRot *= std::max(0.0, 1.0 - RVentSpeed * dt); + } + break; + } + + case TEngineType::DieselElectric: + { + // NOTE: for this type RventRot is the speed of motor blowers; we also update radiator fans while at it + if (true == Mains) + { + // TBD, TODO: currently ignores RVentType, fix this? + RventRot += clamp(enrot - RventRot, -100.0, 50.0) * dt; + dizel_heat.rpmw += clamp(dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f) * dt; + dizel_heat.rpmw2 += clamp(dizel_heat.rpmwz2 - dizel_heat.rpmw2, -100.f, 50.f) * dt; + } + else + { + RventRot *= std::max(0.0, 1.0 - RVentSpeed * dt); + dizel_heat.rpmw *= std::max(0.0, 1.0 - dizel_heat.rpmw * dt); + dizel_heat.rpmw2 *= std::max(0.0, 1.0 - dizel_heat.rpmw2 * dt); + } + break; + } + + case TEngineType::DieselEngine: + { + // NOTE: we update only radiator fans, as vehicles with diesel engine don't have other ventilators + if (true == Mains) + { + dizel_heat.rpmw += clamp(dizel_heat.rpmwz - dizel_heat.rpmw, -100.f, 50.f) * dt; + dizel_heat.rpmw2 += clamp(dizel_heat.rpmwz2 - dizel_heat.rpmw2, -100.f, 50.f) * dt; + } + else + { + dizel_heat.rpmw *= std::max(0.0, 1.0 - dizel_heat.rpmw * dt); + dizel_heat.rpmw2 *= std::max(0.0, 1.0 - dizel_heat.rpmw2 * dt); + } + break; + } + + default: + { + break; + } + } + + switch (EngineType) + { + case TEngineType::Dumb: + { + PosRatio = (MainCtrlPos + ScndCtrlPos) / (MainCtrlPosNo + ScndCtrlPosNo + 0.01); + EnginePower = /*1000.0 **/ Power * PosRatio; + break; + } + case TEngineType::DieselEngine: + { + dizel_Power = Mm * enrot * (2.0 * M_PI / 1000.0); + EnginePower = (dizel_Mstand + Mm) * enrot * (2.0 * M_PI / 1000.0); + if (MainCtrlPowerPos() > 1) + { + // dodatkowe opory z powodu sprezarki} + // dmoment -= dizel_Mstand * ( 0.2 * enrot / dizel_nmax ); //yB: skąd to w ogóle się bierze?! + } + break; + } + case TEngineType::DieselElectric: + { + EnginePower = 0; // the actual calculation is done in two steps later in the method + break; + } + default: + { + break; + } + } + + switch (EngineType) + { + + case TEngineType::ElectricSeriesMotor: + { + // update the state of voltage relays + auto const voltage{std::max(GetTrainsetHighVoltage(), PantographVoltage)}; + NoVoltRelay = (EnginePowerSource.SourceType != TPowerSource::CurrentCollector) || (voltage >= EnginePowerSource.CollectorParameters.MinV); + OvervoltageRelay = + (EnginePowerSource.SourceType != TPowerSource::CurrentCollector) || (voltage <= EnginePowerSource.CollectorParameters.MaxV) || (false == EnginePowerSource.CollectorParameters.OVP); + // wywalanie szybkiego z powodu niewłaściwego napięcia + EventFlag |= ((true == Mains) && ((false == NoVoltRelay) || (false == OvervoltageRelay)) && + (MainSwitch(false, (TrainType == dt_EZT ? range_t::unit : range_t::local)))); // TODO: check whether we need to send this EMU-wide + break; + } + + case TEngineType::ElectricInductionMotor: + { + // TODO: check if we can use instead the code for electricseriesmotor + if ((Mains)) + { + // nie wchodzić w funkcję bez potrzeby + if ((std::max(GetTrainsetHighVoltage(), PantographVoltage) < EnginePowerSource.CollectorParameters.MinV) || + (std::max(GetTrainsetHighVoltage(), PantographVoltage) > EnginePowerSource.CollectorParameters.MaxV + 200)) + { + MainSwitch(false, (TrainType == dt_EZT ? range_t::unit : range_t::local)); // TODO: check whether we need to send this EMU-wide + } + } + break; + } + + case TEngineType::DieselElectric: + { + // TODO: move this to the auto relay check when the electric engine code paths are unified + StLinFlag |= ((Mains) && (false == StLinFlag) && (MainCtrlPowerPos() == 1)); + StLinFlag &= MotorConnectorsCheck(); + StLinFlag &= (MainCtrlPowerPos() > 0); + + break; + } + + default: + { + break; + } + } + + if (DirActive != 0) + switch (EngineType) + { + case TEngineType::Dumb: + { + if (Mains && (CabActive != 0)) + { + if (Vel > 0.1) + { + Ft = std::min(1000.0 * Power / std::abs(V), Ftmax) * PosRatio; + } + else + { + Ft = Ftmax * PosRatio; + } + Ft = Ft * DirAbsolute; // DirActive*CabActive; + } + else + { + Ft = 0; + } + break; + } // Dumb + + case TEngineType::WheelsDriven: + { + if (EnginePowerSource.SourceType == TPowerSource::InternalSource) + if (EnginePowerSource.PowerType == TPowerType::BioPower) + Ft = Sign(sin(eAngle)) * PulseForce * Transmision.Ratio; + PulseForceTimer = PulseForceTimer + dt; + if (PulseForceTimer > CtrlDelay) + { + PulseForce = 0; + if (PulseForceCount > 0) + PulseForceCount--; + } + EnginePower = Ft * (1.0 + Vel); + break; + } // WheelsDriven + + case TEngineType::ElectricSeriesMotor: + { + // enrot:=Transmision.Ratio*nrot; + // yB: szereg dwoch sekcji w ET42 + if ((TrainType == dt_ET42) && (Imax == ImaxHi)) + EngineVoltage = EngineVoltage / 2.0; + Mm = Momentum(Current(enrot, EngineVoltage)); // oblicza tez prad p/slinik + + if (TrainType == dt_ET42) + { + if (Imax == ImaxHi) + EngineVoltage = EngineVoltage * 2; + if ((DynamicBrakeFlag) && (abs(Im) > 300)) // przeiesione do mover.cpp + FuseOff(); + } + if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) + { + if (TUHEX_Stages > 0) // hamowanie wielostopniowe, nadpisuje wartości domyślne + { + if (Vel > 100) + TUHEX_StageActual = std::min(TUHEX_StageActual, 1); switch (TUHEX_StageActual) { case 1: @@ -5742,9 +5722,9 @@ double TMoverParameters::TractionForce( double dt ) { break; case 3: TUHEX_Sum = TUHEX_Sum3; - if ((Vadd > 0.99*TUHEX_MaxIw) && (DynamicBrakeRes == DynamicBrakeRes1)) + if ((Vadd > 0.99 * TUHEX_MaxIw) && (DynamicBrakeRes == DynamicBrakeRes1)) TUHEX_ResChange = true; - if (TUHEX_ResChange && Vadd < 0.5*TUHEX_MaxIw) + if (TUHEX_ResChange && Vadd < 0.5 * TUHEX_MaxIw) { TUHEX_ResChange = false; DynamicBrakeRes = DynamicBrakeRes2; @@ -5756,404 +5736,426 @@ double TMoverParameters::TractionForce( double dt ) { break; } } - if (((Vadd + abs(Im)) > TUHEX_Sum + TUHEX_Diff) || (Hamulec->GetEDBCP() < 0.25) || (TUHEX_ResChange) || (TUHEX_StageActual==0 && TUHEX_Stages>0)) - { - Vadd -= 500.0 * dt; + if (((Vadd + abs(Im)) > TUHEX_Sum + TUHEX_Diff) || (Hamulec->GetEDBCP() < 0.25) || (TUHEX_ResChange) || (TUHEX_StageActual == 0 && TUHEX_Stages > 0)) + { + Vadd -= 500.0 * dt; if (Vadd < TUHEX_MinIw) { Vadd = 0; DynamicBrakeFlag = false; } - } - else if ((DynamicBrakeFlag) && ((Vadd + abs(Im)) < TUHEX_Sum - TUHEX_Diff)) - { - Vadd += 70.0 * dt; - Vadd = Min0R(Max0R(Vadd, TUHEX_MinIw), TUHEX_MaxIw); - } - if (Vadd > 0) - Mm = MomentumF(Im, Vadd, 0); - } + } + else if ((DynamicBrakeFlag) && ((Vadd + abs(Im)) < TUHEX_Sum - TUHEX_Diff)) + { + Vadd += 70.0 * dt; + Vadd = Min0R(Max0R(Vadd, TUHEX_MinIw), TUHEX_MaxIw); + } + if (Vadd > 0) + Mm = MomentumF(Im, Vadd, 0); + } - if ((TrainType == dt_ET22) && (DelayCtrlFlag)) // szarpanie przy zmianie układu w byku - Mm = Mm * RList[MainCtrlActualPos].Bn / - (RList[MainCtrlActualPos].Bn + - 1); // zrobione w momencie, żeby nie dawac elektryki w przeliczaniu sił + if ((TrainType == dt_ET22) && (DelayCtrlFlag)) // szarpanie przy zmianie układu w byku + Mm = Mm * RList[MainCtrlActualPos].Bn / (RList[MainCtrlActualPos].Bn + 1); // zrobione w momencie, żeby nie dawac elektryki w przeliczaniu sił if (abs(Im) > Imax) Vhyp += dt; //*(abs(Im) / Imax - 0.9) * 10; // zwieksz czas oddzialywania na PN - else - Vhyp = 0; - if (Vhyp > CtrlDelay / 2) // jesli czas oddzialywania przekroczony - FuseOff(); // wywalanie bezpiecznika z powodu przetezenia silnikow + else + Vhyp = 0; + if (Vhyp > CtrlDelay / 2) // jesli czas oddzialywania przekroczony + FuseOff(); // wywalanie bezpiecznika z powodu przetezenia silnikow - if (((DynamicBrakeType == dbrake_automatic) || (DynamicBrakeType == dbrake_switch)) && (DynamicBrakeFlag)) - Itot = Im * 2; // 2x2 silniki w EP09 - else if ((TrainType == dt_EZT) && (Imin == IminLo) && (ScndS)) // yBARC - boczniki na szeregu poprawnie - Itot = Im; - else - Itot = Im * RList[MainCtrlActualPos].Bn; // prad silnika * ilosc galezi - Mw = Mm * Transmision.Ratio * Transmision.Efficiency; - Fw = Mw * 2.0 / WheelDiameter; - Ft = Fw * NPoweredAxles; // sila trakcyjna - break; - } + if (((DynamicBrakeType == dbrake_automatic) || (DynamicBrakeType == dbrake_switch)) && (DynamicBrakeFlag)) + Itot = Im * 2; // 2x2 silniki w EP09 + else if ((TrainType == dt_EZT) && (Imin == IminLo) && (ScndS)) // yBARC - boczniki na szeregu poprawnie + Itot = Im; + else + Itot = Im * RList[MainCtrlActualPos].Bn; // prad silnika * ilosc galezi + Mw = Mm * Transmision.Ratio * Transmision.Efficiency; + Fw = Mw * 2.0 / WheelDiameter; + Ft = Fw * NPoweredAxles; // sila trakcyjna + break; + } - case TEngineType::DieselEngine: - { - Mw = dmoment * dtrans * Transmision.Efficiency; // dmoment i dtrans policzone przy okazji enginerotation + case TEngineType::DieselEngine: + { + Mw = dmoment * dtrans * Transmision.Efficiency; // dmoment i dtrans policzone przy okazji enginerotation if ((hydro_R) && (hydro_R_Placement == 0)) Mw -= dizel_MomentumRetarder(nrot * Transmision.Ratio, dt) * Transmision.Ratio * Transmision.Efficiency; - Fw = Mw * 2.0 / WheelDiameter / NPoweredAxles; - Ft = Fw * NPoweredAxles; // sila trakcyjna - Ft = Ft * DirAbsolute; // DirActive*CabActive; - break; - } - - case TEngineType::DieselElectric: // youBy - { - // tmpV:=V*CabActive*DirActive; - auto const tmpV { nrot * Pirazy2 * 0.5 * WheelDiameter * DirAbsolute }; //*CabActive*DirActive; - auto tempUmax = 0.0; - auto tempImax = 0.0; - auto tempPmax = 0.0; - // jazda manewrowa - if (EIMCtrlType > 0) //sterowanie cyfrowe - { - auto eimic_positive = std::max(0.0, eimic_real); - auto const rpmratio { EngineRPMRatio() }; - tempImax = DElist[MainCtrlPosNo].Imax * eimic_positive; - tempUmax = DElist[MainCtrlPosNo].Umax * std::min(eimic_positive, rpmratio); - tempPmax = DElist[MainCtrlPosNo].GenPower * std::min(eimic_positive, rpmratio); - tmp = tempPmax; - if (true == StLinFlag) - { - - if (tmpV < (Vhyp * tempPmax / DElist[MainCtrlPosNo].GenPower)) - { - // czy na czesci prostej, czy na hiperboli - Ft = (Ftmax - - ((Ftmax - 1000.0 * DElist[MainCtrlPosNo].GenPower / (Vhyp + Vadd)) * - (tmpV / Vhyp) / PowerCorRatio)) * - eimic_positive; // posratio - bo sila jakos tam sie rozklada - } - else - { - // na hiperboli - // 1.107 - wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka - Ft = 1000.0 * tempPmax / (tmpV + Vadd) / - PowerCorRatio; // tu jest zawarty stosunek mocy - } - } - else - Ft = 0; // jak nastawnik na zero, to sila tez zero - - PosRatio = tempPmax / DElist[MainCtrlPosNo].GenPower; - } - else - if( true == ShuntMode ) { - if( true == StLinFlag ) { - EngineVoltage = ( SST[ MainCtrlPos ].Umax * AnPos ) + ( SST[ MainCtrlPos ].Umin * ( 1.0 - AnPos ) ); - // NOTE: very crude way to approximate power generated at current rpm instead of instant top output - // NOTE, TODO: doesn't take into account potentially increased revolutions if heating is on, fix it - tmp = EngineRPMRatio() * ( SST[ MainCtrlPos ].Pmax * AnPos ) + ( SST[ MainCtrlPos ].Pmin * ( 1.0 - AnPos ) ); - Ft = tmp * 1000.0 / ( abs( tmpV ) + 1.6 ); - } - else { - EngineVoltage = 0; - Ft = 0; - } - PosRatio = 1; - } - else // jazda ciapongowa - { - auto power = Power; - tempImax = DElist[MainCtrlPos].Imax; - tempUmax = DElist[MainCtrlPos].Umax; - tempPmax = DElist[MainCtrlPos].GenPower; - if( true == Heating ) { power -= HeatingPower; } - if( power < 0.0 ) { power = 0.0; } - // NOTE: very crude way to approximate power generated at current rpm instead of instant top output - // NOTE, TODO: doesn't take into account potentially increased revolutions if heating is on, fix it - auto const currentgenpower { ( - DElist[ MainCtrlPos ].RPM > 0 ? - DElist[ MainCtrlPos ].GenPower * ( 60.0 * enrot / DElist[ MainCtrlPos ].RPM ) : - 0.0 ) }; - - tmp = std::min( power, currentgenpower ); - - PosRatio = currentgenpower / DElist[MainCtrlPosNo].GenPower; - // stosunek mocy teraz do mocy max - // NOTE: Mains in this context is working diesel engine - if( true == StLinFlag ) { - - if( tmpV < ( Vhyp * power / DElist[ MainCtrlPosNo ].GenPower ) ) { - // czy na czesci prostej, czy na hiperboli - Ft = ( Ftmax - - ( ( Ftmax - 1000.0 * DElist[ MainCtrlPosNo ].GenPower / ( Vhyp + Vadd ) ) - * ( tmpV / Vhyp ) - / PowerCorRatio ) ) - * PosRatio; // posratio - bo sila jakos tam sie rozklada - } - else { - // na hiperboli - // 1.107 - wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka - Ft = 1000.0 * tmp / ( tmpV + Vadd ) / - PowerCorRatio; // tu jest zawarty stosunek mocy - } - } - else - Ft = 0; // jak nastawnik na zero, to sila tez zero - - PosRatio = tmp / DElist[MainCtrlPosNo].GenPower; - } - - if (FuseFlag) - Ft = 0; - else - Ft = Ft * DirAbsolute; // DirActive * CabActive; //zwrot sily i jej wartosc - Fw = Ft / NPoweredAxles; // sila na obwodzie kola - Mw = Fw * WheelDiameter / 2.0; // moment na osi kola - Mm = Mw / Transmision.Ratio; // moment silnika trakcyjnego - - // with MotorParam[ScndCtrlPos] do - if (abs(Mm) > MotorParam[ScndCtrlPos].fi) - Im = NPoweredAxles * - abs(abs(Mm) / MotorParam[ScndCtrlPos].mfi + MotorParam[ScndCtrlPos].mIsat); - else - Im = NPoweredAxles * sqrt(abs(Mm * MotorParam[ScndCtrlPos].Isat)); - - if( ShuntMode ) { - EnginePower = EngineVoltage * Im / 1000.0; - if( EnginePower > tmp ) { - EnginePower = tmp; - EngineVoltage = EnginePower * 1000.0 / Im; - } - if( EnginePower < tmp ) { - Ft *= EnginePower / tmp; - } - } - else - { - if (abs(Im) > tempImax) - { // nie ma nadmiarowego, tylko Imax i zwarcie na pradnicy - Ft = Ft / Im * tempImax; - Im = tempImax; - } - - if( Im > 0 ) { - // jak pod obciazeniem - if( true == Flat ) { - // ograniczenie napiecia w pradnicy - plaszczak u gory - EngineVoltage = 1000.0 * tmp / std::abs( Im ); - } - else { - auto tempMCP = EIMCtrlType > 0 ? 1 + 99 * std::max(1.0, eimic_real) : MainCtrlPos; - auto tempMCPN = EIMCtrlType > 0 ? 100 : MainCtrlPosNo; - // charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie Pitagorasa - EngineVoltage = - std::sqrt( - std::abs( - square(tempUmax) - square(tempUmax * Im / tempImax))) * - (tempMCP - 1) + - (1.0 - Im / tempImax) * tempUmax * (tempMCPN - tempMCP); - EngineVoltage /= (tempMCPN - 1); - EngineVoltage = clamp( - EngineVoltage, - Im * 0.05, ( 1000.0 * tmp / std::abs( Im ) ) ); - } - } - - if ((EngineVoltage > tempUmax) - || ( Im == 0 ) ) { - // gdy wychodzi za duze napiecie albo przy biegu jalowym (jest cos takiego?) - EngineVoltage = tempUmax * (ConverterFlag ? 1 : 0); - } - - EnginePower = EngineVoltage * Im / 1000.0; -/* - // power curve drop - // NOTE: disabled for the time being due to side-effects - if( ( tmpV > 1 ) && ( EnginePower < tmp ) ) { - Ft = interpolate( - Ft, EnginePower / tmp, - clamp( tmpV - 1.0, 0.0, 1.0 ) ); - } -*/ - } - - if ((Imax > 1) && (Im > Imax)) - FuseOff(); - if (FuseFlag) - EngineVoltage = 0; - - // przekazniki bocznikowania, kazdy inny dla kazdej pozycji - if( ( false == StLinFlag ) || ( ShuntMode ) ) { - ScndCtrlPos = 0; - } - else { - if( AutoRelayFlag ) { - - auto const shuntfieldstate { ScndCtrlPos }; - - switch( RelayType ) { - - case 0: { - - if( ( ScndCtrlPos < ScndCtrlPosNo ) - && ( Im <= ( MPTRelay[ ScndCtrlPos ].Iup * PosRatio ) ) ) { - ++ScndCtrlPos; - } - if( ( ScndCtrlPos > 0 ) - && ( Im >= ( MPTRelay[ScndCtrlPos].Idown * PosRatio ) ) ) { - --ScndCtrlPos; - } - break; - } - case 1: { - - if( ( ScndCtrlPos < ScndCtrlPosNo ) - && ( MPTRelay[ ScndCtrlPos ].Iup < Vel ) ) { - ++ScndCtrlPos; - } - if( ( ScndCtrlPos > 0 ) - && ( MPTRelay[ ScndCtrlPos ].Idown > Vel ) ) { - --ScndCtrlPos; - } - break; - } - case 2: { - - if( ( ScndCtrlPos < ScndCtrlPosNo ) - && ( MPTRelay[ ScndCtrlPos ].Iup < Vel ) - && ( EnginePower < ( tmp * 0.99 ) ) ) { - ++ScndCtrlPos; - } - if( ( ScndCtrlPos > 0 ) - && ( MPTRelay[ ScndCtrlPos ].Idown < Im ) ) { - --ScndCtrlPos; - } - break; - } - case 41: - { - if( ( ScndCtrlPos < ScndCtrlPosNo ) - && ( MainCtrlPos == MainCtrlPosNo ) - && ( tmpV * 3.6 > MPTRelay[ ScndCtrlPos ].Iup ) ) { - ++ScndCtrlPos; - enrot = enrot * 0.73; - } - if( ( ScndCtrlPos > 0 ) - && ( Im > MPTRelay[ ScndCtrlPos ].Idown ) ) { - --ScndCtrlPos; - } - break; - } - case 45: - { - if( ( ScndCtrlPos < ScndCtrlPosNo ) - && ( MainCtrlPos >= 11 ) ) { - - if( Im < MPTRelay[ ScndCtrlPos ].Iup ) { - ++ScndCtrlPos; - } - // check for cases where the speed drops below threshold for level 2 or 3 - if( ( ScndCtrlPos > 1 ) - && ( Vel < MPTRelay[ ScndCtrlPos - 1 ].Idown ) ) { - --ScndCtrlPos; - } - } - // malenie - if( ( ScndCtrlPos > 0 ) && ( MainCtrlPos < 11 ) ) { - - if( ScndCtrlPos == 1 ) { - if( Im > MPTRelay[ ScndCtrlPos - 1 ].Idown ) { - --ScndCtrlPos; - } - } - else { - if( Vel < MPTRelay[ ScndCtrlPos ].Idown ) { - --ScndCtrlPos; - } - } - } - // 3rd level drops with master controller at position lower than 10... - if( MainCtrlPos < 11 ) { - ScndCtrlPos = std::min( 2, ScndCtrlPos ); - } - // ...and below position 7 field shunt drops altogether - if( MainCtrlPos < 8 ) { - ScndCtrlPos = 0; - } -/* - // crude woodward approximation; difference between rpm for consecutive positions is ~5% - // so we get full throttle until ~half way between desired and previous position, or zero on rpm reduction - auto const woodward { clamp( - ( DElist[ MainCtrlPos ].RPM / ( enrot * 60.0 ) - 1.0 ) * 50.0, - 0.0, 1.0 ) }; -*/ - break; - } - case 46: - { - // wzrastanie - if( ( MainCtrlPos >= 12 ) - && ( ScndCtrlPos < ScndCtrlPosNo ) ) { - if( ( ScndCtrlPos ) % 2 == 0 ) { - if( ( MPTRelay[ ScndCtrlPos ].Iup > Im ) ) { - ++ScndCtrlPos; - } - } - else { - if( ( MPTRelay[ ScndCtrlPos - 1 ].Iup > Im ) - && ( MPTRelay[ ScndCtrlPos ].Iup < Vel ) ) { - ++ScndCtrlPos; - } - } - } - // malenie - if( ( MainCtrlPos < 12 ) - && ( ScndCtrlPos > 0 ) ) { - if( Vel < 50.0 ) { - // above 50 km/h already active shunt field can be maintained until lower controller setting - if( ( ScndCtrlPos ) % 2 == 0 ) { - if( ( MPTRelay[ ScndCtrlPos ].Idown < Im ) ) { - --ScndCtrlPos; - } - } - else { - if( ( MPTRelay[ ScndCtrlPos + 1 ].Idown < Im ) - && ( MPTRelay[ ScndCtrlPos ].Idown > Vel ) ) { - --ScndCtrlPos; - } - } - } - } - if( MainCtrlPos < 11 ) { - ScndCtrlPos = std::min( 2, ScndCtrlPos ); - } - if( MainCtrlPos < 8 ) { - ScndCtrlPos = 0; - } - break; - } - default: { - break; - } - } // switch RelayType - - if( ScndCtrlPos != shuntfieldstate ) { - SetFlag( SoundFlag, ( sound::relay | sound::shuntfield ) ); - } - } - } + Fw = Mw * 2.0 / WheelDiameter / NPoweredAxles; + Ft = Fw * NPoweredAxles; // sila trakcyjna + Ft = Ft * DirAbsolute; // DirActive*CabActive; break; - } // DieselElectric + } - case TEngineType::ElectricInductionMotor: - { - if( true == Mains && !SecuritySystem.is_engine_blocked() ) { + case TEngineType::DieselElectric: // youBy + { + // tmpV:=V*CabActive*DirActive; + auto const tmpV{nrot * Pirazy2 * 0.5 * WheelDiameter * DirAbsolute}; //*CabActive*DirActive; + auto tempUmax = 0.0; + auto tempImax = 0.0; + auto tempPmax = 0.0; + // jazda manewrowa + if (EIMCtrlType > 0) // sterowanie cyfrowe + { + auto eimic_positive = std::max(0.0, eimic_real); + auto const rpmratio{EngineRPMRatio()}; + tempImax = DElist[MainCtrlPosNo].Imax * eimic_positive; + tempUmax = DElist[MainCtrlPosNo].Umax * std::min(eimic_positive, rpmratio); + tempPmax = DElist[MainCtrlPosNo].GenPower * std::min(eimic_positive, rpmratio); + tmp = tempPmax; + if (true == StLinFlag) + { + + if (tmpV < (Vhyp * tempPmax / DElist[MainCtrlPosNo].GenPower)) + { + // czy na czesci prostej, czy na hiperboli + Ft = + (Ftmax - ((Ftmax - 1000.0 * DElist[MainCtrlPosNo].GenPower / (Vhyp + Vadd)) * (tmpV / Vhyp) / PowerCorRatio)) * eimic_positive; // posratio - bo sila jakos tam sie rozklada + } + else + { + // na hiperboli + // 1.107 - wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka + Ft = 1000.0 * tempPmax / (tmpV + Vadd) / PowerCorRatio; // tu jest zawarty stosunek mocy + } + } + else + Ft = 0; // jak nastawnik na zero, to sila tez zero + + PosRatio = tempPmax / DElist[MainCtrlPosNo].GenPower; + } + else if (true == ShuntMode) + { + if (true == StLinFlag) + { + EngineVoltage = (SST[MainCtrlPos].Umax * AnPos) + (SST[MainCtrlPos].Umin * (1.0 - AnPos)); + // NOTE: very crude way to approximate power generated at current rpm instead of instant top output + // NOTE, TODO: doesn't take into account potentially increased revolutions if heating is on, fix it + tmp = EngineRPMRatio() * (SST[MainCtrlPos].Pmax * AnPos) + (SST[MainCtrlPos].Pmin * (1.0 - AnPos)); + Ft = tmp * 1000.0 / (abs(tmpV) + 1.6); + } + else + { + EngineVoltage = 0; + Ft = 0; + } + PosRatio = 1; + } + else // jazda ciapongowa + { + auto power = Power; + tempImax = DElist[MainCtrlPos].Imax; + tempUmax = DElist[MainCtrlPos].Umax; + tempPmax = DElist[MainCtrlPos].GenPower; + if (true == Heating) + { + power -= HeatingPower; + } + if (power < 0.0) + { + power = 0.0; + } + // NOTE: very crude way to approximate power generated at current rpm instead of instant top output + // NOTE, TODO: doesn't take into account potentially increased revolutions if heating is on, fix it + auto const currentgenpower{(DElist[MainCtrlPos].RPM > 0 ? DElist[MainCtrlPos].GenPower * (60.0 * enrot / DElist[MainCtrlPos].RPM) : 0.0)}; + + tmp = std::min(power, currentgenpower); + + PosRatio = currentgenpower / DElist[MainCtrlPosNo].GenPower; + // stosunek mocy teraz do mocy max + // NOTE: Mains in this context is working diesel engine + if (true == StLinFlag) + { + + if (tmpV < (Vhyp * power / DElist[MainCtrlPosNo].GenPower)) + { + // czy na czesci prostej, czy na hiperboli + Ft = (Ftmax - ((Ftmax - 1000.0 * DElist[MainCtrlPosNo].GenPower / (Vhyp + Vadd)) * (tmpV / Vhyp) / PowerCorRatio)) * PosRatio; // posratio - bo sila jakos tam sie rozklada + } + else + { + // na hiperboli + // 1.107 - wspolczynnik sredniej nadwyzki Ft w symku nad charakterystyka + Ft = 1000.0 * tmp / (tmpV + Vadd) / PowerCorRatio; // tu jest zawarty stosunek mocy + } + } + else + Ft = 0; // jak nastawnik na zero, to sila tez zero + + PosRatio = tmp / DElist[MainCtrlPosNo].GenPower; + } + + if (FuseFlag) + Ft = 0; + else + Ft = Ft * DirAbsolute; // DirActive * CabActive; //zwrot sily i jej wartosc + Fw = Ft / NPoweredAxles; // sila na obwodzie kola + Mw = Fw * WheelDiameter / 2.0; // moment na osi kola + Mm = Mw / Transmision.Ratio; // moment silnika trakcyjnego + + // with MotorParam[ScndCtrlPos] do + if (abs(Mm) > MotorParam[ScndCtrlPos].fi) + Im = NPoweredAxles * abs(abs(Mm) / MotorParam[ScndCtrlPos].mfi + MotorParam[ScndCtrlPos].mIsat); + else + Im = NPoweredAxles * sqrt(abs(Mm * MotorParam[ScndCtrlPos].Isat)); + + if (ShuntMode) + { + EnginePower = EngineVoltage * Im / 1000.0; + if (EnginePower > tmp) + { + EnginePower = tmp; + EngineVoltage = EnginePower * 1000.0 / Im; + } + if (EnginePower < tmp) + { + Ft *= EnginePower / tmp; + } + } + else + { + if (abs(Im) > tempImax) + { // nie ma nadmiarowego, tylko Imax i zwarcie na pradnicy + Ft = Ft / Im * tempImax; + Im = tempImax; + } + + if (Im > 0) + { + // jak pod obciazeniem + if (true == Flat) + { + // ograniczenie napiecia w pradnicy - plaszczak u gory + EngineVoltage = 1000.0 * tmp / std::abs(Im); + } + else + { + auto tempMCP = EIMCtrlType > 0 ? 1 + 99 * std::max(1.0, eimic_real) : MainCtrlPos; + auto tempMCPN = EIMCtrlType > 0 ? 100 : MainCtrlPosNo; + // charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie Pitagorasa + EngineVoltage = std::sqrt(std::abs(square(tempUmax) - square(tempUmax * Im / tempImax))) * (tempMCP - 1) + (1.0 - Im / tempImax) * tempUmax * (tempMCPN - tempMCP); + EngineVoltage /= (tempMCPN - 1); + EngineVoltage = clamp(EngineVoltage, Im * 0.05, (1000.0 * tmp / std::abs(Im))); + } + } + + if ((EngineVoltage > tempUmax) || (Im == 0)) + { + // gdy wychodzi za duze napiecie albo przy biegu jalowym (jest cos takiego?) + EngineVoltage = tempUmax * (ConverterFlag ? 1 : 0); + } + + EnginePower = EngineVoltage * Im / 1000.0; + /* + // power curve drop + // NOTE: disabled for the time being due to side-effects + if( ( tmpV > 1 ) && ( EnginePower < tmp ) ) { + Ft = interpolate( + Ft, EnginePower / tmp, + clamp( tmpV - 1.0, 0.0, 1.0 ) ); + } + */ + } + + if ((Imax > 1) && (Im > Imax)) + FuseOff(); + if (FuseFlag) + EngineVoltage = 0; + + // przekazniki bocznikowania, kazdy inny dla kazdej pozycji + if ((false == StLinFlag) || (ShuntMode)) + { + ScndCtrlPos = 0; + } + else + { + if (AutoRelayFlag) + { + + auto const shuntfieldstate{ScndCtrlPos}; + + switch (RelayType) + { + + case 0: + { + + if ((ScndCtrlPos < ScndCtrlPosNo) && (Im <= (MPTRelay[ScndCtrlPos].Iup * PosRatio))) + { + ++ScndCtrlPos; + } + if ((ScndCtrlPos > 0) && (Im >= (MPTRelay[ScndCtrlPos].Idown * PosRatio))) + { + --ScndCtrlPos; + } + break; + } + case 1: + { + + if ((ScndCtrlPos < ScndCtrlPosNo) && (MPTRelay[ScndCtrlPos].Iup < Vel)) + { + ++ScndCtrlPos; + } + if ((ScndCtrlPos > 0) && (MPTRelay[ScndCtrlPos].Idown > Vel)) + { + --ScndCtrlPos; + } + break; + } + case 2: + { + + if ((ScndCtrlPos < ScndCtrlPosNo) && (MPTRelay[ScndCtrlPos].Iup < Vel) && (EnginePower < (tmp * 0.99))) + { + ++ScndCtrlPos; + } + if ((ScndCtrlPos > 0) && (MPTRelay[ScndCtrlPos].Idown < Im)) + { + --ScndCtrlPos; + } + break; + } + case 41: + { + if ((ScndCtrlPos < ScndCtrlPosNo) && (MainCtrlPos == MainCtrlPosNo) && (tmpV * 3.6 > MPTRelay[ScndCtrlPos].Iup)) + { + ++ScndCtrlPos; + enrot = enrot * 0.73; + } + if ((ScndCtrlPos > 0) && (Im > MPTRelay[ScndCtrlPos].Idown)) + { + --ScndCtrlPos; + } + break; + } + case 45: + { + if ((ScndCtrlPos < ScndCtrlPosNo) && (MainCtrlPos >= 11)) + { + + if (Im < MPTRelay[ScndCtrlPos].Iup) + { + ++ScndCtrlPos; + } + // check for cases where the speed drops below threshold for level 2 or 3 + if ((ScndCtrlPos > 1) && (Vel < MPTRelay[ScndCtrlPos - 1].Idown)) + { + --ScndCtrlPos; + } + } + // malenie + if ((ScndCtrlPos > 0) && (MainCtrlPos < 11)) + { + + if (ScndCtrlPos == 1) + { + if (Im > MPTRelay[ScndCtrlPos - 1].Idown) + { + --ScndCtrlPos; + } + } + else + { + if (Vel < MPTRelay[ScndCtrlPos].Idown) + { + --ScndCtrlPos; + } + } + } + // 3rd level drops with master controller at position lower than 10... + if (MainCtrlPos < 11) + { + ScndCtrlPos = std::min(2, ScndCtrlPos); + } + // ...and below position 7 field shunt drops altogether + if (MainCtrlPos < 8) + { + ScndCtrlPos = 0; + } + /* + // crude woodward approximation; difference between rpm for consecutive positions is ~5% + // so we get full throttle until ~half way between desired and previous position, or zero on rpm reduction + auto const woodward { clamp( + ( DElist[ MainCtrlPos ].RPM / ( enrot * 60.0 ) - 1.0 ) * 50.0, + 0.0, 1.0 ) }; + */ + break; + } + case 46: + { + // wzrastanie + if ((MainCtrlPos >= 12) && (ScndCtrlPos < ScndCtrlPosNo)) + { + if ((ScndCtrlPos) % 2 == 0) + { + if ((MPTRelay[ScndCtrlPos].Iup > Im)) + { + ++ScndCtrlPos; + } + } + else + { + if ((MPTRelay[ScndCtrlPos - 1].Iup > Im) && (MPTRelay[ScndCtrlPos].Iup < Vel)) + { + ++ScndCtrlPos; + } + } + } + // malenie + if ((MainCtrlPos < 12) && (ScndCtrlPos > 0)) + { + if (Vel < 50.0) + { + // above 50 km/h already active shunt field can be maintained until lower controller setting + if ((ScndCtrlPos) % 2 == 0) + { + if ((MPTRelay[ScndCtrlPos].Idown < Im)) + { + --ScndCtrlPos; + } + } + else + { + if ((MPTRelay[ScndCtrlPos + 1].Idown < Im) && (MPTRelay[ScndCtrlPos].Idown > Vel)) + { + --ScndCtrlPos; + } + } + } + } + if (MainCtrlPos < 11) + { + ScndCtrlPos = std::min(2, ScndCtrlPos); + } + if (MainCtrlPos < 8) + { + ScndCtrlPos = 0; + } + break; + } + default: + { + break; + } + } // switch RelayType + + if (ScndCtrlPos != shuntfieldstate) + { + SetFlag(SoundFlag, (sound::relay | sound::shuntfield)); + } + } + } + break; + } // DieselElectric + + case TEngineType::ElectricInductionMotor: + { + if (true == Mains && !SecuritySystem.is_engine_blocked()) + { double ActiveInverters = 0.0; - for (auto &inv : Inverters) { + for (auto &inv : Inverters) + { if (inv.IsActive) ActiveInverters += 1.0; } @@ -6162,34 +6164,39 @@ double TMoverParameters::TractionForce( double dt ) { { eimc[eimc_p_Pmax] = TableInterpolation(EIM_Pmax_Table, Vel); } - //tempomat + // tempomat if (ScndCtrlPosNo == 4 && SpeedCtrlTypeTime) { - SpeedCtrlUnit.IsActive = ( SpeedCtrlValue > 0 ); - switch (ScndCtrlPos) { + SpeedCtrlUnit.IsActive = (SpeedCtrlValue > 0); + switch (ScndCtrlPos) + { case 0: NewSpeed = 0; SpeedCtrlValue = 0; SpeedCtrlTimer = 10; break; case 1: - if (SpeedCtrlTimer > SpeedCtrlDelay) { + if (SpeedCtrlTimer > SpeedCtrlDelay) + { SpeedCtrlTimer = 0; NewSpeed -= 10; - if (NewSpeed < 0) NewSpeed = 0; + if (NewSpeed < 0) + NewSpeed = 0; } else SpeedCtrlTimer += dt; - break; + break; case 2: SpeedCtrlTimer = 10; SpeedCtrlValue = NewSpeed; break; case 3: - if (SpeedCtrlTimer > SpeedCtrlDelay) { + if (SpeedCtrlTimer > SpeedCtrlDelay) + { SpeedCtrlTimer = 0; NewSpeed += 10; - if (NewSpeed > Vmax) NewSpeed = Vmax; + if (NewSpeed > Vmax) + NewSpeed = Vmax; } else SpeedCtrlTimer += dt; @@ -6214,297 +6221,270 @@ double TMoverParameters::TractionForce( double dt ) { SpeedCtrlTimer += dt; if (SpeedCtrlTimer > SpeedCtrlDelay) { - int NewSCAP = (float)ScndCtrlPos / (float)ScndCtrlPosNo * Vmax; + int NewSCAP = (float)ScndCtrlPos / (float)ScndCtrlPosNo * Vmax; if (NewSCAP != SpeedCtrlValue) { SpeedCtrlValue = NewSCAP; -// SendCtrlToNext("SpeedCntrl", SpeedCtrlValue, CabActive); + // SendCtrlToNext("SpeedCntrl", SpeedCtrlValue, CabActive); } } } - SpeedCtrlUnit.IsActive = ( SpeedCtrlValue > 0 ); + SpeedCtrlUnit.IsActive = (SpeedCtrlValue > 0); } double edBCP = Hamulec->GetEDBCP(); - auto const localbrakeactive { ( CabOccupied != 0 ) && ( LocHandle->GetCP() > 0.25 ) }; - if( ( false == Doors.instances[ side::left ].is_closed ) - || ( false == Doors.instances[ side::right ].is_closed ) - || ( Doors.permit_needed && ( Doors.instances[ side::left ].open_permit || Doors.instances[ side::right ].open_permit ) ) ) { - DynamicBrakeFlag = true; - } - else if (((edBCP < 0.25) && (false == localbrakeactive) && (AnPos < 0.01)) - || ((edBCP < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01))) - DynamicBrakeFlag = false; - else if ((((BrakePress > 0.25) && (edBCP > 0.25) || localbrakeactive)) - || (AnPos > 0.02)) - DynamicBrakeFlag = true; + auto const localbrakeactive{(CabOccupied != 0) && (LocHandle->GetCP() > 0.25)}; + if ((false == Doors.instances[side::left].is_closed) || (false == Doors.instances[side::right].is_closed) || + (Doors.permit_needed && (Doors.instances[side::left].open_permit || Doors.instances[side::right].open_permit))) + { + DynamicBrakeFlag = true; + } + else if (((edBCP < 0.25) && (false == localbrakeactive) && (AnPos < 0.01)) || ((edBCP < 0.25) && (ShuntModeAllow) && (LocalBrakePosA < 0.01))) + DynamicBrakeFlag = false; + else if ((((BrakePress > 0.25) && (edBCP > 0.25) || localbrakeactive)) || (AnPos > 0.02)) + DynamicBrakeFlag = true; edBCP = Hamulec->GetEDBCP() * eimc[eimc_p_abed]; // stala napedu - if ((DynamicBrakeFlag)) - { + if ((DynamicBrakeFlag)) + { // ustalanie współczynnika blendingu do luzowania hamulca PN - if (eimv[eimv_Fmax] * Sign(V) * DirAbsolute < -1) - { - PosRatio = -Sign(V) * DirAbsolute * eimv[eimv_Fr] / - (eimc[eimc_p_Fh] * - Max0R(edBCP,Max0R(0.01,Hamulec->GetEDBCP())) / MaxBrakePress[0]); + if (eimv[eimv_Fmax] * Sign(V) * DirAbsolute < -1) + { + PosRatio = -Sign(V) * DirAbsolute * eimv[eimv_Fr] / (eimc[eimc_p_Fh] * Max0R(edBCP, Max0R(0.01, Hamulec->GetEDBCP())) / MaxBrakePress[0]); PosRatio = clamp(PosRatio, 0.0, 1.0); - } + } else { PosRatio = 0; } - PosRatio = Round(20.0 * PosRatio) / 20.0; //stopniowanie PN/ED - if (PosRatio < 19.5 / 20.0) - PosRatio *= 0.9; - Hamulec->SetED(Max0R(0.0, std::min(PosRatio, 1.0))); //ustalenie stopnia zmniejszenia ciśnienia + PosRatio = Round(20.0 * PosRatio) / 20.0; // stopniowanie PN/ED + if (PosRatio < 19.5 / 20.0) + PosRatio *= 0.9; + Hamulec->SetED(Max0R(0.0, std::min(PosRatio, 1.0))); // ustalenie stopnia zmniejszenia ciśnienia // ustalanie siły hamowania ED - if ((Hamulec->GetEDBCP() > 0.25) && (eimc[eimc_p_abed] < 0.001) || (ActiveInverters < InvertersNo)) //jeśli PN wyłącza ED + if ((Hamulec->GetEDBCP() > 0.25) && (eimc[eimc_p_abed] < 0.001) || (ActiveInverters < InvertersNo)) // jeśli PN wyłącza ED { PosRatio = 0; eimv[eimv_Fzad] = 0; } else { - PosRatio = -std::max(std::min(edBCP * 1.0 / MaxBrakePress[0], 1.0), AnPos) * - std::max(0.0, std::min(1.0, (Vel - eimc[eimc_p_Vh0]) / - (eimc[eimc_p_Vh1] - eimc[eimc_p_Vh0]))); - eimv[eimv_Fzad] = -std::min(1.0,std::max(LocalBrakeRatio(), edBCP / MaxBrakePress[0])); + PosRatio = -std::max(std::min(edBCP * 1.0 / MaxBrakePress[0], 1.0), AnPos) * std::max(0.0, std::min(1.0, (Vel - eimc[eimc_p_Vh0]) / (eimc[eimc_p_Vh1] - eimc[eimc_p_Vh0]))); + eimv[eimv_Fzad] = -std::min(1.0, std::max(LocalBrakeRatio(), edBCP / MaxBrakePress[0])); } - tmp = 5; - } - else - { + tmp = 5; + } + else + { PosRatio = Max0R(eimic_real, 0); - eimv[eimv_Fzad] = PosRatio; - if ((Flat) && (eimc[eimc_p_F0] * eimv[eimv_Fful] > 0)) - PosRatio = Min0R(PosRatio * eimc[eimc_p_F0] / eimv[eimv_Fful], 1); -/* if (ScndCtrlActualPos > 0) //speed control - if (Vmax < 250) - PosRatio = Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos - Vel))); - else - PosRatio = - Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos * 2 - Vel))); */ - // PosRatio = 1.0 * (PosRatio * 0 + 1) * PosRatio; // 1 * 1 * PosRatio = PosRatio - Hamulec->SetED(0); - // (Hamulec as TLSt).SetLBP(LocBrakePress); - if ((PosRatio > eimv_pr)) - tmp = 4; - else - tmp = 4; // szybkie malenie, powolne wzrastanie - } - dmoment = eimv[eimv_Fful]; - // NOTE: the commands to operate the sandbox are likely to conflict with other similar ai decisions - // TODO: gather these in single place so they can be resolved together - if( ( SlippingWheels ) ) { - PosRatio = 0; - tmp = 10; - SandboxAuto( true, range_t::unit ); - } // przeciwposlizg - else { - // switch sandbox off - SandboxAuto( false, range_t::unit ); - } + eimv[eimv_Fzad] = PosRatio; + if ((Flat) && (eimc[eimc_p_F0] * eimv[eimv_Fful] > 0)) + PosRatio = Min0R(PosRatio * eimc[eimc_p_F0] / eimv[eimv_Fful], 1); + /* if (ScndCtrlActualPos > 0) //speed control + if (Vmax < 250) + PosRatio = Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos - Vel))); + else + PosRatio = + Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos * 2 - Vel))); */ + // PosRatio = 1.0 * (PosRatio * 0 + 1) * PosRatio; // 1 * 1 * PosRatio = PosRatio + Hamulec->SetED(0); + // (Hamulec as TLSt).SetLBP(LocBrakePress); + if ((PosRatio > eimv_pr)) + tmp = 4; + else + tmp = 4; // szybkie malenie, powolne wzrastanie + } + dmoment = eimv[eimv_Fful]; + // NOTE: the commands to operate the sandbox are likely to conflict with other similar ai decisions + // TODO: gather these in single place so they can be resolved together + if ((SlippingWheels)) + { + PosRatio = 0; + tmp = 10; + SandboxAuto(true, range_t::unit); + } // przeciwposlizg + else + { + // switch sandbox off + SandboxAuto(false, range_t::unit); + } if (ActiveInverters == 0.0) { PosRatio = 0; eimv_pr = 0; } - eimv_pr += Max0R(Min0R(PosRatio - eimv_pr, 0.02), -0.02) * 12 * - (tmp /*2{+4*byte(PosRatio= 0)) - Vadd *= (1.0 - 2.0 * dt); - else if ((std::abs(EngineVoltage) < EnginePowerSource.CollectorParameters.MaxV)) - Vadd *= (1.0 - dt); - else - Vadd = std::max( - Vadd * (1.0 - 0.2 * dt), - 0.007 * (std::abs(EngineVoltage) - (EnginePowerSource.CollectorParameters.MaxV - 100))); - Itot = eimv[eimv_Ipoj] * (0.01 + std::min(0.99, 0.99 - Vadd)); + Im = eimv[eimv_If]; + if ((eimv[eimv_Ipoj] >= 0)) + Vadd *= (1.0 - 2.0 * dt); + else if ((std::abs(EngineVoltage) < EnginePowerSource.CollectorParameters.MaxV)) + Vadd *= (1.0 - dt); + else + Vadd = std::max(Vadd * (1.0 - 0.2 * dt), 0.007 * (std::abs(EngineVoltage) - (EnginePowerSource.CollectorParameters.MaxV - 100))); + Itot = eimv[eimv_Ipoj] * (0.01 + std::min(0.99, 0.99 - Vadd)); + EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000; + // power inverters + auto const tmpV{std::abs(eimv[eimv_fp])}; + auto const useFFEDList = FFEDListSize > 0 && DynamicBrakeFlag; + auto const list = useFFEDList ? FFEDlist : FFlist; + auto const listSize = useFFEDList ? FFEDListSize : FFListSize; - EnginePower = abs(eimv[eimv_Ic] * eimv[eimv_U] * NPoweredAxles) / 1000; - // power inverters - auto const tmpV { std::abs( eimv[ eimv_fp ] ) }; - auto const useFFEDList = FFEDListSize > 0 && DynamicBrakeFlag; - auto const list = useFFEDList ? FFEDlist : FFlist; - auto const listSize = useFFEDList ? FFEDListSize : FFListSize; + if ((listSize > 0) && ((std::abs(eimv[eimv_If]) > 1.0) && (tmpV > 0.0001))) + { - if( ( listSize > 0 ) - && ( ( std::abs( eimv[ eimv_If ] ) > 1.0 ) - && ( tmpV > 0.0001 ) ) ) { + int i = 0; + while ((i < listSize - 1) && (list[i + 1].v < tmpV)) + { + ++i; + } + InverterFrequency = (tmpV - list[i].v) / std::max(1.0, (list[i + 1].v - list[i].v)) * (list[i + 1].freq - list[i].freq) + list[i].freq; + } + else + { + InverterFrequency = 0.0; + } - int i = 0; - while( ( i < listSize - 1 ) - && ( list[ i + 1 ].v < tmpV ) ) { - ++i; - } - InverterFrequency = - ( tmpV - list[ i ].v ) - / std::max( 1.0, ( list[ i + 1 ].v - list[ i ].v ) ) - * ( list[ i + 1 ].freq - list[ i ].freq ) - + list[ i ].freq; - } - else { - InverterFrequency = 0.0; - } - - Mm = eimv[eimv_M] * DirAbsolute; - Mw = Mm * Transmision.Ratio * Transmision.Efficiency; - Fw = Mw * 2.0 / WheelDiameter; - Ft = Fw * NPoweredAxles * InvertersRatio; - eimv[eimv_Fr] = DirAbsolute * Ft / 1000; - } // mains - else - { - for (auto &inv : Inverters) { + Mm = eimv[eimv_M] * DirAbsolute; + Mw = Mm * Transmision.Ratio * Transmision.Efficiency; + Fw = Mw * 2.0 / WheelDiameter; + Ft = Fw * NPoweredAxles * InvertersRatio; + eimv[eimv_Fr] = DirAbsolute * Ft / 1000; + } // mains + else + { + for (auto &inv : Inverters) + { inv.Freal = 0.0; inv.IsActive = false; } - Im = 0.0; - Mm = 0.0; - Mw = 0.0; - Fw = 0.0; - Ft = 0.0; - Itot = 0.0; + Im = 0.0; + Mm = 0.0; + Mw = 0.0; + Fw = 0.0; + Ft = 0.0; + Itot = 0.0; eimv_pr = 0.0; - EnginePower = 0.0; - { - for (int i = 0; i < 21; ++i) - eimv[i] = 0.0; - } - Hamulec->SetED(0.0); - InverterFrequency = 0.0; //(Hamulec as TLSt).SetLBP(LocBrakePress); - } + EnginePower = 0.0; + { + for (int i = 0; i < 21; ++i) + eimv[i] = 0.0; + } + Hamulec->SetED(0.0); + InverterFrequency = 0.0; //(Hamulec as TLSt).SetLBP(LocBrakePress); + } break; - } // ElectricInductionMotor + } // ElectricInductionMotor - case TEngineType::None: - default: { - break; - } - } // case EngineType + case TEngineType::None: + default: + { + break; + } + } // case EngineType - switch( EngineType ) { - case TEngineType::DieselElectric: { - // rough approximation of extra effort to overcome friction etc - EnginePower += EngineRPMRatio() * 0.15 * DElist[ MainCtrlPosNo ].GenPower; - break; - } - default: { - break; - } - } + switch (EngineType) + { + case TEngineType::DieselElectric: + { + // rough approximation of extra effort to overcome friction etc + EnginePower += EngineRPMRatio() * 0.15 * DElist[MainCtrlPosNo].GenPower; + break; + } + default: + { + break; + } + } - - return Ft; + return Ft; } // ************************************************************************************************* // Q: 20160713 -//Obliczenie predkości obrotowej kół??? +// Obliczenie predkości obrotowej kół??? // ************************************************************************************************* double TMoverParameters::ComputeRotatingWheel(double WForce, double dt, double n) const { - double newn = 0, eps = 0; - if ((n == 0) && (WForce * Sign(V) < 0)) - newn = 0; - else - { - eps = WForce * WheelDiameter / (2.0 * AxleInertialMoment); - newn = n + eps * dt; - if ((newn * n <= 0) && (eps * n < 0)) - newn = 0; - } - return newn; + double newn = 0, eps = 0; + if ((n == 0) && (WForce * Sign(V) < 0)) + newn = 0; + else + { + eps = WForce * WheelDiameter / (2.0 * AxleInertialMoment); + newn = n + eps * dt; + if ((newn * n <= 0) && (eps * n < 0)) + newn = 0; + } + return newn; } // ************************************************************************************************* @@ -6513,29 +6493,29 @@ double TMoverParameters::ComputeRotatingWheel(double WForce, double dt, double n // ************************************************************************************************* bool TMoverParameters::FuseFlagCheck(void) const { - bool FFC; + bool FFC; - FFC = false; - if (Power > 0.01) - FFC = FuseFlag; - else // pobor pradu jezeli niema mocy - for (int b = 0; b < 2; b++) - if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) - if (Couplers[b].Connected->Power > 0.01) - FFC = Couplers[b].Connected->FuseFlagCheck(); + FFC = false; + if (Power > 0.01) + FFC = FuseFlag; + else // pobor pradu jezeli niema mocy + for (int b = 0; b < 2; b++) + if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) + if (Couplers[b].Connected->Power > 0.01) + FFC = Couplers[b].Connected->FuseFlagCheck(); - return FFC; + return FFC; } // ************************************************************************************************* // Q: 20160713 // Załączenie bezpiecznika nadmiarowego // ************************************************************************************************* -bool TMoverParameters::FuseOn( range_t const Notify ) +bool TMoverParameters::FuseOn(range_t const Notify) { - auto const result { RelayReset( ( relay_t::maincircuitground | relay_t::tractionnmotoroverload ), Notify ) }; + auto const result{RelayReset((relay_t::maincircuitground | relay_t::tractionnmotoroverload), Notify)}; - return result; + return result; } // ************************************************************************************************* @@ -6544,88 +6524,92 @@ bool TMoverParameters::FuseOn( range_t const Notify ) // ************************************************************************************************* void TMoverParameters::FuseOff(void) { - if (!FuseFlag) - { - FuseFlag = true; - EventFlag = true; - SetFlag(SoundFlag, sound::relay | sound::loud); - } + if (!FuseFlag) + { + FuseFlag = true; + EventFlag = true; + SetFlag(SoundFlag, sound::relay | sound::loud); + } } // resets relays assigned to specified customizable reset button -bool TMoverParameters::UniversalResetButton( int const Button, range_t const Notify ) { +bool TMoverParameters::UniversalResetButton(int const Button, range_t const Notify) +{ - auto const lowvoltagepower { Power24vIsAvailable || Power110vIsAvailable }; - if( false == lowvoltagepower ) { return false; } + auto const lowvoltagepower{Power24vIsAvailable || Power110vIsAvailable}; + if (false == lowvoltagepower) + { + return false; + } - auto const relays { UniversalResetButtonFlag[ Button ] }; - if( relays == 0 ) { return false; } + auto const relays{UniversalResetButtonFlag[Button]}; + if (relays == 0) + { + return false; + } - auto const result { RelayReset( relays, Notify ) }; + auto const result{RelayReset(relays, Notify)}; - return result; + return result; } // resets state of specified relays -bool TMoverParameters::RelayReset( int const Relays, range_t const Notify ) { +bool TMoverParameters::RelayReset(int const Relays, range_t const Notify) +{ - auto const lowvoltagepower { Power24vIsAvailable || Power110vIsAvailable }; - bool reset { false }; + auto const lowvoltagepower{Power24vIsAvailable || Power110vIsAvailable}; + bool reset{false}; - if( TestFlag( Relays, relay_t::maincircuitground ) ) { - if( ( ( EngineType == TEngineType::ElectricSeriesMotor ) || ( EngineType == TEngineType::DieselElectric ) ) - && ( ( GroundRelayStart == start_t::manual ) || ( GroundRelayStart == start_t::manualwithautofallback ) ) - && ( IsMainCtrlNoPowerPos() ) - && ( ScndCtrlPos == 0 ) - && ( DirActive != 0 ) - && ( !TestFlag( EngDmgFlag, 1 ) ) ) { - // NOTE: true means the relay is operational - reset |= ( !GroundRelay && lowvoltagepower ); - GroundRelay |= lowvoltagepower; - } - } + if (TestFlag(Relays, relay_t::maincircuitground)) + { + if (((EngineType == TEngineType::ElectricSeriesMotor) || (EngineType == TEngineType::DieselElectric)) && + ((GroundRelayStart == start_t::manual) || (GroundRelayStart == start_t::manualwithautofallback)) && (IsMainCtrlNoPowerPos()) && (ScndCtrlPos == 0) && (DirActive != 0) && + (!TestFlag(EngDmgFlag, 1))) + { + // NOTE: true means the relay is operational + reset |= (!GroundRelay && lowvoltagepower); + GroundRelay |= lowvoltagepower; + } + } - if( TestFlag( Relays, relay_t::tractionnmotoroverload ) ) { - if( ( ( EngineType == TEngineType::ElectricSeriesMotor ) || ( EngineType == TEngineType::DieselElectric ) ) - && ( IsMainCtrlNoPowerPos() ) - && ( ScndCtrlPos == 0 ) - && ( DirActive != 0 ) - && ( !TestFlag( EngDmgFlag, 1 ) ) ) { - // NOTE: false means the relay is operational - // TODO: cleanup, flip the FuseFlag code to match other relays - // TODO: check whether the power is required, TBD, TODO: make it configurable? - reset |= ( FuseFlag && lowvoltagepower ); - FuseFlag &= !lowvoltagepower; - } - } + if (TestFlag(Relays, relay_t::tractionnmotoroverload)) + { + if (((EngineType == TEngineType::ElectricSeriesMotor) || (EngineType == TEngineType::DieselElectric)) && (IsMainCtrlNoPowerPos()) && (ScndCtrlPos == 0) && (DirActive != 0) && + (!TestFlag(EngDmgFlag, 1))) + { + // NOTE: false means the relay is operational + // TODO: cleanup, flip the FuseFlag code to match other relays + // TODO: check whether the power is required, TBD, TODO: make it configurable? + reset |= (FuseFlag && lowvoltagepower); + FuseFlag &= !lowvoltagepower; + } + } - if( TestFlag( Relays, relay_t::primaryconverteroverload ) ) { - if( ( ConverterOverloadRelayStart == start_t::manual ) -// && ( false == Mains ) - && ( false == ConverterAllow ) ) { - // NOTE: false means the relay is operational - // TODO: cleanup, flip the FuseFlag code to match other relays - // TODO: check whether the power is required, TBD, TODO: make it configurable? - reset |= ( ConvOvldFlag && lowvoltagepower ); - ConvOvldFlag &= !lowvoltagepower; - } - } + if (TestFlag(Relays, relay_t::primaryconverteroverload)) + { + if ((ConverterOverloadRelayStart == start_t::manual) + // && ( false == Mains ) + && (false == ConverterAllow)) + { + // NOTE: false means the relay is operational + // TODO: cleanup, flip the FuseFlag code to match other relays + // TODO: check whether the power is required, TBD, TODO: make it configurable? + reset |= (ConvOvldFlag && lowvoltagepower); + ConvOvldFlag &= !lowvoltagepower; + } + } - if( reset ) { - SetFlag( SoundFlag, sound::relay | sound::loud ); - } + if (reset) + { + SetFlag(SoundFlag, sound::relay | sound::loud); + } - if( Notify != range_t::local ) { - SendCtrlToNext( - "RelayReset", - Relays, - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("RelayReset", Relays, CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return reset; + return reset; } // ************************************************************************************************* @@ -6634,28 +6618,28 @@ bool TMoverParameters::RelayReset( int const Relays, range_t const Notify ) { // ************************************************************************************************* double TMoverParameters::v2n(void) { - // przelicza predkosc liniowa na obrotowa - const double dmgn = 0.5; - double n, deltan = 0; + // przelicza predkosc liniowa na obrotowa + const double dmgn = 0.5; + double n, deltan = 0; - n = V / (M_PI * WheelDiameter); // predkosc obrotowa wynikajaca z liniowej [obr/s] - deltan = n - nrot; //"pochodna" prędkości obrotowej - /* if (SlippingWheels) - if (std::abs(deltan) < 0.001) - SlippingWheels = false; // wygaszenie poslizgu */ //poslizg jest w innym miejscu wygaszany też - if (SlippingWheels) // nie ma zwiazku z predkoscia liniowa V - { // McZapkie-221103: uszkodzenia kol podczas poslizgu - if (deltan > dmgn) - if (FuzzyLogic(deltan, dmgn, p_slippdmg)) - if (SetFlag(DamageFlag, dtrain_wheelwear)) // podkucie - EventFlag = true; - if (deltan < -dmgn) - if (FuzzyLogic(-deltan, dmgn, p_slippdmg)) - if (SetFlag(DamageFlag, dtrain_thinwheel)) // wycieranie sie obreczy - EventFlag = true; - n = nrot; // predkosc obrotowa nie zalezy od predkosci liniowej - } - return n; + n = V / (M_PI * WheelDiameter); // predkosc obrotowa wynikajaca z liniowej [obr/s] + deltan = n - nrot; //"pochodna" prędkości obrotowej + /* if (SlippingWheels) + if (std::abs(deltan) < 0.001) + SlippingWheels = false; // wygaszenie poslizgu */ //poslizg jest w innym miejscu wygaszany też + if (SlippingWheels) // nie ma zwiazku z predkoscia liniowa V + { // McZapkie-221103: uszkodzenia kol podczas poslizgu + if (deltan > dmgn) + if (FuzzyLogic(deltan, dmgn, p_slippdmg)) + if (SetFlag(DamageFlag, dtrain_wheelwear)) // podkucie + EventFlag = true; + if (deltan < -dmgn) + if (FuzzyLogic(-deltan, dmgn, p_slippdmg)) + if (SetFlag(DamageFlag, dtrain_thinwheel)) // wycieranie sie obreczy + EventFlag = true; + n = nrot; // predkosc obrotowa nie zalezy od predkosci liniowej + } + return n; } // ************************************************************************************************* @@ -6664,17 +6648,16 @@ double TMoverParameters::v2n(void) // ************************************************************************************************* double TMoverParameters::Momentum(double I) { - // liczy moment sily wytwarzany przez silnik elektryczny} - int SP; + // liczy moment sily wytwarzany przez silnik elektryczny} + int SP; - SP = ScndCtrlActualPos; - if (ScndInMain) - if (!(RList[MainCtrlActualPos].ScndAct == 255)) - SP = RList[MainCtrlActualPos].ScndAct; + SP = ScndCtrlActualPos; + if (ScndInMain) + if (!(RList[MainCtrlActualPos].ScndAct == 255)) + SP = RList[MainCtrlActualPos].ScndAct; - // Momentum:=mfi*I*(1-1.0/(Abs(I)/mIsat+1)); - return (MotorParam[SP].mfi * I * - (abs(I) / (abs(I) + MotorParam[SP].mIsat) - MotorParam[SP].mfi0)); + // Momentum:=mfi*I*(1-1.0/(Abs(I)/mIsat+1)); + return (MotorParam[SP].mfi * I * (abs(I) / (abs(I) + MotorParam[SP].mIsat) - MotorParam[SP].mfi0)); } // ************************************************************************************************* @@ -6683,10 +6666,9 @@ double TMoverParameters::Momentum(double I) // ************************************************************************************************* double TMoverParameters::MomentumF(double I, double Iw, int SCP) { - // umozliwia dokladne sterowanie wzbudzeniem + // umozliwia dokladne sterowanie wzbudzeniem - return (MotorParam[SCP].mfi * I * - Max0R(abs(Iw) / (abs(Iw) + MotorParam[SCP].mIsat) - MotorParam[SCP].mfi0, 0)); + return (MotorParam[SCP].mfi * I * Max0R(abs(Iw) / (abs(Iw) + MotorParam[SCP].mIsat) - MotorParam[SCP].mfi0, 0)); } // ************************************************************************************************* @@ -6695,39 +6677,34 @@ double TMoverParameters::MomentumF(double I, double Iw, int SCP) // ************************************************************************************************* bool TMoverParameters::CutOffEngine(void) { - bool COE = false; // Ra: wartość domyślna, sprawdzić to trzeba - if ((NPoweredAxles > 0) && (CabActive == 0) && (EngineType == TEngineType::ElectricSeriesMotor)) - { - if (SetFlag(DamageFlag, -dtrain_engine)) - { - NPoweredAxles = NPoweredAxles / 2; // bylo div czyli mod? - COE = true; - } - } - return COE; + bool COE = false; // Ra: wartość domyślna, sprawdzić to trzeba + if ((NPoweredAxles > 0) && (CabActive == 0) && (EngineType == TEngineType::ElectricSeriesMotor)) + { + if (SetFlag(DamageFlag, -dtrain_engine)) + { + NPoweredAxles = NPoweredAxles / 2; // bylo div czyli mod? + COE = true; + } + } + return COE; } // ************************************************************************************************* // Q: 20160713 // Przełączenie wysoki / niski prąd rozruchu // ************************************************************************************************* -bool TMoverParameters::MaxCurrentSwitch(bool State, range_t const Notify ) +bool TMoverParameters::MaxCurrentSwitch(bool State, range_t const Notify) { - auto const initialstate { MotorOverloadRelayHighThreshold }; + auto const initialstate{MotorOverloadRelayHighThreshold}; - MotorOverloadRelayHighThreshold = State; + MotorOverloadRelayHighThreshold = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "MaxCurrentSwitch", - ( State ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("MaxCurrentSwitch", (State ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return State != initialstate; + return State != initialstate; } // ************************************************************************************************* @@ -6736,26 +6713,26 @@ bool TMoverParameters::MaxCurrentSwitch(bool State, range_t const Notify ) // ************************************************************************************************* bool TMoverParameters::MinCurrentSwitch(bool State) { - bool MCS = false; - if( ( ( EngineType == TEngineType::ElectricSeriesMotor ) && ( IminHi > IminLo ) ) - || ( ( TrainType == dt_EZT ) && ( EngineType != TEngineType::ElectricInductionMotor ) ) ) { + bool MCS = false; + if (((EngineType == TEngineType::ElectricSeriesMotor) && (IminHi > IminLo)) || ((TrainType == dt_EZT) && (EngineType != TEngineType::ElectricInductionMotor))) + { - if (State && (Imin == IminLo)) - { - Imin = IminHi; - MCS = true; - if (CabActive != 0) - SendCtrlToNext("MinCurrentSwitch", 1, CabActive); - } - if ((!State) && (Imin == IminHi)) - { - Imin = IminLo; - MCS = true; - if (CabActive != 0) - SendCtrlToNext("MinCurrentSwitch", 0, CabActive); - } - } - return MCS; + if (State && (Imin == IminLo)) + { + Imin = IminHi; + MCS = true; + if (CabActive != 0) + SendCtrlToNext("MinCurrentSwitch", 1, CabActive); + } + if ((!State) && (Imin == IminHi)) + { + Imin = IminLo; + MCS = true; + if (CabActive != 0) + SendCtrlToNext("MinCurrentSwitch", 0, CabActive); + } + } + return MCS; } // ************************************************************************************************* @@ -6764,10 +6741,10 @@ bool TMoverParameters::MinCurrentSwitch(bool State) // ************************************************************************************************* bool TMoverParameters::ResistorsFlagCheck(void) const { - bool RFC = false; + bool RFC = false; - if (Power > 0.01) - RFC = ResistorsFlag; + if (Power > 0.01) + RFC = ResistorsFlag; else // pobor pradu jezeli niema mocy { for (int b = 0; b < 2; b++) @@ -6775,7 +6752,7 @@ bool TMoverParameters::ResistorsFlagCheck(void) const if (Couplers[b].Connected->Power > 0.01) RFC = Couplers[b].Connected->ResistorsFlagCheck(); } - return RFC; + return RFC; } // ************************************************************************************************* @@ -6784,17 +6761,17 @@ bool TMoverParameters::ResistorsFlagCheck(void) const // ************************************************************************************************* bool TMoverParameters::AutoRelaySwitch(bool State) { - bool ARS; - if ((AutoRelayType == 2) && (AutoRelayFlag != State)) - { - AutoRelayFlag = State; - ARS = true; - SendCtrlToNext("AutoRelaySwitch", int(State), CabActive); - } - else - ARS = false; + bool ARS; + if ((AutoRelayType == 2) && (AutoRelayFlag != State)) + { + AutoRelayFlag = State; + ARS = true; + SendCtrlToNext("AutoRelaySwitch", int(State), CabActive); + } + else + ARS = false; - return ARS; + return ARS; } // ************************************************************************************************* @@ -6804,463 +6781,522 @@ bool TMoverParameters::AutoRelaySwitch(bool State) bool TMoverParameters::AutoRelayCheck(void) { - bool OK = false; // b:int; - bool ARC = false; + bool OK = false; // b:int; + bool ARC = false; - auto const motorconnectorsoff { false == MotorConnectorsCheck() }; + auto const motorconnectorsoff{false == MotorConnectorsCheck()}; - // Ra 2014-06: dla SN61 nie działa prawidłowo - // yBARC - rozlaczenie stycznikow liniowych - if( ( motorconnectorsoff ) - || ( HasCamshaft ? - IsMainCtrlActualNoPowerPos() : - IsMainCtrlNoPowerPos() ) ) { - StLinFlag = false; - OK = false; - if( false == DynamicBrakeFlag ) { - Im = 0; - Itot = 0; - ResistorsFlag = false; - } - } + // Ra 2014-06: dla SN61 nie działa prawidłowo + // yBARC - rozlaczenie stycznikow liniowych + if ((motorconnectorsoff) || (HasCamshaft ? IsMainCtrlActualNoPowerPos() : IsMainCtrlNoPowerPos())) + { + StLinFlag = false; + OK = false; + if (false == DynamicBrakeFlag) + { + Im = 0; + Itot = 0; + ResistorsFlag = false; + } + } - // sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im 0) || (ScndCtrlPos > 0)) && - (!(CoupledCtrl) || (RList[MainCtrlActualPos].Relay == MainCtrlPos))) - { // zmieniaj scndctrlactualpos - // scnd bez samoczynnego rozruchu - if (ScndCtrlActualPos < ScndCtrlPos) - { - if ((LastRelayTime > CtrlDelay) && (ARFASI2)) - { - ++ScndCtrlActualPos; - SetFlag( SoundFlag, sound::shuntfield ); - OK = true; - } - } - else if (ScndCtrlActualPos > ScndCtrlPos) - { - if ((LastRelayTime > CtrlDownDelay) && (TrainType != dt_EZT)) - { - --ScndCtrlActualPos; - SetFlag( SoundFlag, sound::shuntfield ); - OK = true; - } - } - else - OK = false; - } - else - { // zmieniaj mainctrlactualpos - if( ( DirActive < 0 ) && ( TrainType != dt_PseudoDiesel ) ) { - if( RList[ MainCtrlActualPos + 1 ].Bn > BackwardsBranchesAllowed) { - return false; // nie poprawiamy przy konwersji - // return ARC;// bbylo exit; //Ra: to powoduje, że EN57 nie wyłącza się przy IminLo - } - } - // main bez samoczynnego rozruchu - if( ( MainCtrlActualPos < ( sizeof( RList ) / sizeof( TScheme ) - 1 ) ) // crude guard against running out of current fixed table - && ( ( RList[ MainCtrlActualPos ].Relay < MainCtrlPos ) - || ( ( RList[ MainCtrlActualPos + 1 ].Relay == MainCtrlPos ) && ( MainCtrlActualPos < RlistSize ) ) - || ( ( TrainType == dt_ET22 ) && ( DelayCtrlFlag ) ) ) ) { + // sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im 0) || (ScndCtrlPos > 0)) && (!(CoupledCtrl) || (RList[MainCtrlActualPos].Relay == MainCtrlPos))) + { // zmieniaj scndctrlactualpos + // scnd bez samoczynnego rozruchu + if (ScndCtrlActualPos < ScndCtrlPos) + { + if ((LastRelayTime > CtrlDelay) && (ARFASI2)) + { + ++ScndCtrlActualPos; + SetFlag(SoundFlag, sound::shuntfield); + OK = true; + } + } + else if (ScndCtrlActualPos > ScndCtrlPos) + { + if ((LastRelayTime > CtrlDownDelay) && (TrainType != dt_EZT)) + { + --ScndCtrlActualPos; + SetFlag(SoundFlag, sound::shuntfield); + OK = true; + } + } + else + OK = false; + } + else + { // zmieniaj mainctrlactualpos + if ((DirActive < 0) && (TrainType != dt_PseudoDiesel)) + { + if (RList[MainCtrlActualPos + 1].Bn > BackwardsBranchesAllowed) + { + return false; // nie poprawiamy przy konwersji + // return ARC;// bbylo exit; //Ra: to powoduje, że EN57 nie wyłącza się przy IminLo + } + } + // main bez samoczynnego rozruchu + if ((MainCtrlActualPos < (sizeof(RList) / sizeof(TScheme) - 1)) // crude guard against running out of current fixed table + && ((RList[MainCtrlActualPos].Relay < MainCtrlPos) || ((RList[MainCtrlActualPos + 1].Relay == MainCtrlPos) && (MainCtrlActualPos < RlistSize)) || + ((TrainType == dt_ET22) && (DelayCtrlFlag)))) + { - // prevent switch to parallel mode if motor overload relay is set to high threshold mode - if( ( IsMotorOverloadRelayHighThresholdOn() ) - && ( RList[ MainCtrlActualPos + 1 ].Bn > 1 ) ) { - return false; - } + // prevent switch to parallel mode if motor overload relay is set to high threshold mode + if ((IsMotorOverloadRelayHighThresholdOn()) && (RList[MainCtrlActualPos + 1].Bn > 1)) + { + return false; + } - if( ( RList[MainCtrlPos].R == 0 ) - && ( MainCtrlPos > 0 ) - && ( MainCtrlPos != MainCtrlPosNo ) - && ( FastSerialCircuit == 1 ) ) { - // szybkie wchodzenie na bezoporowa (303E) - // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: - ++MainCtrlActualPos; - if( MainCtrlPos - MainCtrlActualPos == 1 ) { - // HACK: ensure we play only single sound of basic relays for entire trasition; return false - // for all but last step despite configuration change, to prevent playback of the basic relay sound - // TBD, TODO: move the basic sound event here and enable it with call parameter - OK = true; - } - if( RList[ MainCtrlActualPos ].R == 0 ) { - SetFlag( SoundFlag, sound::parallel | sound::loud ); - OK = true; - } - } - else if ((LastRelayTime > CtrlDelay) && (ARFASI)) - { - // WriteLog("LRT = " + FloatToStr(LastRelayTime) + ", " + - // FloatToStr(CtrlDelay)); - if( ( TrainType == dt_ET22 ) - && ( MainCtrlPos > 1 ) - && ( ( RList[ MainCtrlActualPos ].Bn < RList[ MainCtrlActualPos + 1 ].Bn ) - || ( DelayCtrlFlag ) ) ) { - // et22 z walem grupowym - if( !DelayCtrlFlag ) // najpierw przejscie - { - ++MainCtrlActualPos; - DelayCtrlFlag = true; // tryb przejscia - OK = true; - } - else if( LastRelayTime > 4 * CtrlDelay ) // przejscie - { + if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) && (MainCtrlPos != MainCtrlPosNo) && (FastSerialCircuit == 1)) + { + // szybkie wchodzenie na bezoporowa (303E) + // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: + ++MainCtrlActualPos; + if (MainCtrlPos - MainCtrlActualPos == 1) + { + // HACK: ensure we play only single sound of basic relays for entire trasition; return false + // for all but last step despite configuration change, to prevent playback of the basic relay sound + // TBD, TODO: move the basic sound event here and enable it with call parameter + OK = true; + } + if (RList[MainCtrlActualPos].R == 0) + { + SetFlag(SoundFlag, sound::parallel | sound::loud); + OK = true; + } + } + else if ((LastRelayTime > CtrlDelay) && (ARFASI)) + { + // WriteLog("LRT = " + FloatToStr(LastRelayTime) + ", " + + // FloatToStr(CtrlDelay)); + if ((TrainType == dt_ET22) && (MainCtrlPos > 1) && ((RList[MainCtrlActualPos].Bn < RList[MainCtrlActualPos + 1].Bn) || (DelayCtrlFlag))) + { + // et22 z walem grupowym + if (!DelayCtrlFlag) // najpierw przejscie + { + ++MainCtrlActualPos; + DelayCtrlFlag = true; // tryb przejscia + OK = true; + } + else if (LastRelayTime > 4 * CtrlDelay) // przejscie + { - DelayCtrlFlag = false; - OK = true; - } -/* - else - ; -*/ - } - else // nie ET22 z wałem grupowym - { - ++MainCtrlActualPos; - OK = true; - } - //--------- - // hunter-111211: poprawki - if( MainCtrlActualPos > 0 ) { - if( ( RList[ MainCtrlActualPos ].R == 0 ) - && ( MainCtrlActualPos != MainCtrlPosNo ) ) { - // wejscie na bezoporowa - SetFlag( SoundFlag, sound::parallel | sound::loud ); - } - else if( ( RList[ MainCtrlActualPos ].R > 0 ) - && ( RList[ MainCtrlActualPos - 1 ].R == 0 ) ) { - // wejscie na drugi uklad - SetFlag( SoundFlag, sound::parallel ); - } - } - } - } - else if (RList[MainCtrlActualPos].Relay > MainCtrlPos) - { - if( ( RList[ MainCtrlPos ].R == 0 ) - && ( MainCtrlPos > 0 ) - && ( !( MainCtrlPos == MainCtrlPosNo ) ) - && ( FastSerialCircuit == 1 ) ) { - // szybkie wchodzenie na bezoporowa (303E) - // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: - --MainCtrlActualPos; - OK = true; - if( RList[ MainCtrlActualPos ].R == 0 ) { - SetFlag( SoundFlag, sound::parallel ); - } - } - else if (LastRelayTime > CtrlDownDelay) - { - if (TrainType != dt_EZT) // tutaj powinien być tryb sterowania wałem - { - --MainCtrlActualPos; - OK = true; - } - if (MainCtrlActualPos > 0) // hunter-111211: poprawki - if (RList[MainCtrlActualPos].R == 0) { - // dzwieki schodzenia z bezoporowej} - SetFlag(SoundFlag, sound::parallel); - } - } - } - else if ((RList[MainCtrlActualPos].R > 0) && (ScndCtrlActualPos > 0)) - { - if (LastRelayTime > CtrlDownDelay) - { - --ScndCtrlActualPos; // boczniki nie dzialaja na poz. oporowych - SetFlag( SoundFlag, sound::shuntfield ); - OK = true; - } - } - else - OK = false; - } - } - else // not StLinFlag - { - OK = false; - // ybARC - zalaczenie stycznikow liniowych - if( ( false == motorconnectorsoff ) - && ( MainCtrlActualPos == 0 ) - && ( ( TrainType == dt_EZT || HasCamshaft ) ? - MainCtrlPowerPos() > 0 : - MainCtrlPowerPos() == 1 ) ) { + DelayCtrlFlag = false; + OK = true; + } + /* + else + ; + */ + } + else // nie ET22 z wałem grupowym + { + ++MainCtrlActualPos; + OK = true; + } + //--------- + // hunter-111211: poprawki + if (MainCtrlActualPos > 0) + { + if ((RList[MainCtrlActualPos].R == 0) && (MainCtrlActualPos != MainCtrlPosNo)) + { + // wejscie na bezoporowa + SetFlag(SoundFlag, sound::parallel | sound::loud); + } + else if ((RList[MainCtrlActualPos].R > 0) && (RList[MainCtrlActualPos - 1].R == 0)) + { + // wejscie na drugi uklad + SetFlag(SoundFlag, sound::parallel); + } + } + } + } + else if (RList[MainCtrlActualPos].Relay > MainCtrlPos) + { + if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) && (!(MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1)) + { + // szybkie wchodzenie na bezoporowa (303E) + // MainCtrlActualPos:=MainCtrlPos; //hunter-111012: + --MainCtrlActualPos; + OK = true; + if (RList[MainCtrlActualPos].R == 0) + { + SetFlag(SoundFlag, sound::parallel); + } + } + else if (LastRelayTime > CtrlDownDelay) + { + if (TrainType != dt_EZT) // tutaj powinien być tryb sterowania wałem + { + --MainCtrlActualPos; + OK = true; + } + if (MainCtrlActualPos > 0) // hunter-111211: poprawki + if (RList[MainCtrlActualPos].R == 0) + { + // dzwieki schodzenia z bezoporowej} + SetFlag(SoundFlag, sound::parallel); + } + } + } + else if ((RList[MainCtrlActualPos].R > 0) && (ScndCtrlActualPos > 0)) + { + if (LastRelayTime > CtrlDownDelay) + { + --ScndCtrlActualPos; // boczniki nie dzialaja na poz. oporowych + SetFlag(SoundFlag, sound::shuntfield); + OK = true; + } + } + else + OK = false; + } + } + else // not StLinFlag + { + OK = false; + // ybARC - zalaczenie stycznikow liniowych + if ((false == motorconnectorsoff) && (MainCtrlActualPos == 0) && ((TrainType == dt_EZT || HasCamshaft) ? MainCtrlPowerPos() > 0 : MainCtrlPowerPos() == 1)) + { - DelayCtrlFlag = true; - if( LastRelayTime >= InitialCtrlDelay ) { - StLinFlag = true; - MainCtrlActualPos = 1; - DelayCtrlFlag = false; - SetFlag(SoundFlag, sound::relay | sound::loud); - OK = true; - } - } - else { - DelayCtrlFlag = false; - } + DelayCtrlFlag = true; + if (LastRelayTime >= InitialCtrlDelay) + { + StLinFlag = true; + MainCtrlActualPos = 1; + DelayCtrlFlag = false; + SetFlag(SoundFlag, sound::relay | sound::loud); + OK = true; + } + } + else + { + DelayCtrlFlag = false; + } - if( ( false == StLinFlag ) - && ( ( MainCtrlActualPos > 0 ) - || ( ScndCtrlActualPos > 0 ) ) ) { + if ((false == StLinFlag) && ((MainCtrlActualPos > 0) || (ScndCtrlActualPos > 0))) + { - if( CoupledCtrl ) { + if (CoupledCtrl) + { - if( TrainType == dt_EZT ) { - // EN57 wal jednokierunkowy calosciowy - if( MainCtrlActualPos == 1 ) { + if (TrainType == dt_EZT) + { + // EN57 wal jednokierunkowy calosciowy + if (MainCtrlActualPos == 1) + { - MainCtrlActualPos = 0; - OK = true; - } - else { + MainCtrlActualPos = 0; + OK = true; + } + else + { - if( LastRelayTime > CtrlDownDelay ) { + if (LastRelayTime > CtrlDownDelay) + { - if( MainCtrlActualPos < RlistSize ) { - // dojdz do konca - ++MainCtrlActualPos; - } - else if( ScndCtrlActualPos < ScndCtrlPosNo ) { - // potem boki - ++ScndCtrlActualPos; - SetFlag( SoundFlag, sound::shuntfield ); - } - else { - // i sie przewroc na koniec - MainCtrlActualPos = 0; - ScndCtrlActualPos = 0; - } - OK = true; - } - } - } - else { - // wal kulakowy dwukierunkowy - if( LastRelayTime > CtrlDownDelay ) { - if( ScndCtrlActualPos > 0 ) { - --ScndCtrlActualPos; - SetFlag( SoundFlag, sound::shuntfield ); - } - else { - --MainCtrlActualPos; - } - OK = true; - } - } - } - else if( HasCamshaft ) { - // wal kulakowy dwukierunkowy - if( LastRelayTime > CtrlDownDelay ) { - if( MainCtrlActualPos > 0 ) { - --MainCtrlActualPos; - } - ScndCtrlActualPos = 0; - OK = true; - } - } - else { - MainCtrlActualPos = 0; - ScndCtrlActualPos = 0; - OK = true; - } - } - } - if (OK) - LastRelayTime = 0; + if (MainCtrlActualPos < RlistSize) + { + // dojdz do konca + ++MainCtrlActualPos; + } + else if (ScndCtrlActualPos < ScndCtrlPosNo) + { + // potem boki + ++ScndCtrlActualPos; + SetFlag(SoundFlag, sound::shuntfield); + } + else + { + // i sie przewroc na koniec + MainCtrlActualPos = 0; + ScndCtrlActualPos = 0; + } + OK = true; + } + } + } + else + { + // wal kulakowy dwukierunkowy + if (LastRelayTime > CtrlDownDelay) + { + if (ScndCtrlActualPos > 0) + { + --ScndCtrlActualPos; + SetFlag(SoundFlag, sound::shuntfield); + } + else + { + --MainCtrlActualPos; + } + OK = true; + } + } + } + else if (HasCamshaft) + { + // wal kulakowy dwukierunkowy + if (LastRelayTime > CtrlDownDelay) + { + if (MainCtrlActualPos > 0) + { + --MainCtrlActualPos; + } + ScndCtrlActualPos = 0; + OK = true; + } + } + else + { + MainCtrlActualPos = 0; + ScndCtrlActualPos = 0; + OK = true; + } + } + } + if (OK) + LastRelayTime = 0; - return OK; - } + return OK; + } } -bool TMoverParameters::MotorConnectorsCheck() { +bool TMoverParameters::MotorConnectorsCheck() +{ - // hunter-111211: wylacznik cisnieniowy - ControlPressureSwitch = ( - ( HasControlPressureSwitch ) - && ( ( BrakePress > 2.0 ) - || ( PipePress < 3.6 ) ) ); + // hunter-111211: wylacznik cisnieniowy + ControlPressureSwitch = ((HasControlPressureSwitch) && ((BrakePress > 2.0) || (PipePress < 3.6))); - if( true == ControlPressureSwitch ) { return false; } + if (true == ControlPressureSwitch) + { + return false; + } - auto const connectorsoff { - ( false == Mains ) - || ( true == FuseFlag ) - || ( true == StLinSwitchOff ) - || ( DirActive == 0 ) }; + auto const connectorsoff{(false == Mains) || (true == FuseFlag) || (true == StLinSwitchOff) || (DirActive == 0)}; - return ( false == connectorsoff ); + return (false == connectorsoff); } -bool TMoverParameters::OperatePantographsValve( operation_t const State, range_t const Notify ) { +bool TMoverParameters::OperatePantographsValve(operation_t const State, range_t const Notify) +{ - if( ( EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) - && ( EnginePowerSource.CollectorParameters.CollectorsNo > 0 ) ) { + if ((EnginePowerSource.SourceType == TPowerSource::CurrentCollector) && (EnginePowerSource.CollectorParameters.CollectorsNo > 0)) + { - auto &valve { PantsValve }; + auto &valve{PantsValve}; - switch( State ) { - case operation_t::none: { valve.is_enabled = false; valve.is_disabled = false; break; } - case operation_t::enable: { valve.is_enabled = true; valve.is_disabled = false; break; } - case operation_t::disable: { valve.is_enabled = false; valve.is_disabled = true; break; } - case operation_t::enable_on: { valve.is_enabled = true; break; } - case operation_t::enable_off: { valve.is_enabled = false; break; } - case operation_t::disable_on: { valve.is_disabled = true; break; } - case operation_t::disable_off: { valve.is_disabled = false; break; } - } - } + switch (State) + { + case operation_t::none: + { + valve.is_enabled = false; + valve.is_disabled = false; + break; + } + case operation_t::enable: + { + valve.is_enabled = true; + valve.is_disabled = false; + break; + } + case operation_t::disable: + { + valve.is_enabled = false; + valve.is_disabled = true; + break; + } + case operation_t::enable_on: + { + valve.is_enabled = true; + break; + } + case operation_t::enable_off: + { + valve.is_enabled = false; + break; + } + case operation_t::disable_on: + { + valve.is_disabled = true; + break; + } + case operation_t::disable_off: + { + valve.is_disabled = false; + break; + } + } + } - if( Notify != range_t::local ) { - SendCtrlToNext( - "PantsValve", - static_cast( State ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("PantsValve", static_cast(State), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return true; + return true; } -bool TMoverParameters::OperatePantographValve( end const End, operation_t const State, range_t const Notify ) { +bool TMoverParameters::OperatePantographValve(end const End, operation_t const State, range_t const Notify) +{ - if( ( EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) - && ( EnginePowerSource.CollectorParameters.CollectorsNo > 0 ) ) { + if ((EnginePowerSource.SourceType == TPowerSource::CurrentCollector) && (EnginePowerSource.CollectorParameters.CollectorsNo > 0)) + { - auto &valve { Pantographs[ End ].valve }; + auto &valve{Pantographs[End].valve}; - switch( State ) { - case operation_t::none: { valve.is_enabled = false; valve.is_disabled = false; break; } - case operation_t::enable: { valve.is_enabled = true; valve.is_disabled = false; break; } - case operation_t::disable: { valve.is_enabled = false; valve.is_disabled = true; break; } - case operation_t::enable_on: { valve.is_enabled = true; break; } - case operation_t::enable_off: { valve.is_enabled = false; break; } - case operation_t::disable_on: { valve.is_disabled = true; break; } - case operation_t::disable_off: { valve.is_disabled = false; break; } - } - } + switch (State) + { + case operation_t::none: + { + valve.is_enabled = false; + valve.is_disabled = false; + break; + } + case operation_t::enable: + { + valve.is_enabled = true; + valve.is_disabled = false; + break; + } + case operation_t::disable: + { + valve.is_enabled = false; + valve.is_disabled = true; + break; + } + case operation_t::enable_on: + { + valve.is_enabled = true; + break; + } + case operation_t::enable_off: + { + valve.is_enabled = false; + break; + } + case operation_t::disable_on: + { + valve.is_disabled = true; + break; + } + case operation_t::disable_off: + { + valve.is_disabled = false; + break; + } + } + } - if( Notify != range_t::local ) { - SendCtrlToNext( - "PantValve", - // HACK: pack the state, pantograph index and sender cab into 8-bit value - // with high bit storing front/rear pantograph, and 7th bit storing sender cab - static_cast( - 0x80 * ( End == end::front ? 0 : 1 ) - + 0x40 * ( CabActive != -1 ? 1 : 0 ) - + static_cast( State ) ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("PantValve", + // HACK: pack the state, pantograph index and sender cab into 8-bit value + // with high bit storing front/rear pantograph, and 7th bit storing sender cab + static_cast(0x80 * (End == end::front ? 0 : 1) + 0x40 * (CabActive != -1 ? 1 : 0) + static_cast(State)), CabActive, + (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return true; + return true; } -bool TMoverParameters::DropAllPantographs( bool const State, range_t const Notify ) { +bool TMoverParameters::DropAllPantographs(bool const State, range_t const Notify) +{ - auto const initialstate{ PantAllDown }; + auto const initialstate{PantAllDown}; - PantAllDown = State; + PantAllDown = State; - if( Notify != range_t::local ) { - SendCtrlToNext( - "PantAllDown", - ( State ? 1 : 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + if (Notify != range_t::local) + { + SendCtrlToNext("PantAllDown", (State ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return State != initialstate; + return State != initialstate; } void TMoverParameters::CheckEIMIC(double dt) { - double offset = EIMCtrlAdditionalZeros ? 1.0 : 0.0; - double multiplier = (EIMCtrlEmergency ? 1.0 : 0.0) + offset; + double offset = EIMCtrlAdditionalZeros ? 1.0 : 0.0; + double multiplier = (EIMCtrlEmergency ? 1.0 : 0.0) + offset; switch (EIMCtrlType) { case 0: - eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : - eimic_analog > 0.01 ? eimic_analog : (double)MainCtrlPos / (double)MainCtrlPosNo); - if (EIMCtrlAdditionalZeros || EIMCtrlEmergency) + eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : eimic_analog > 0.01 ? eimic_analog : (double)MainCtrlPos / (double)MainCtrlPosNo); + if (EIMCtrlAdditionalZeros || EIMCtrlEmergency) { if (eimic > 0.001) eimic = std::max(0.002, eimic * (double)MainCtrlPosNo / ((double)MainCtrlPosNo - offset) - offset / ((double)MainCtrlPosNo - offset)); if ((eimic < -0.001) && (BrakeHandle != TBrakeHandle::MHZ_EN57)) eimic = std::min(-0.002, eimic * (double)LocalBrakePosNo / ((double)LocalBrakePosNo - multiplier) + offset / ((double)LocalBrakePosNo - multiplier)); } - if ((eimic > 0.001) && (SpeedCtrlUnit.IsActive)) - eimic = std::max(eimic, SpeedCtrlUnit.MinPower); + if ((eimic > 0.001) && (SpeedCtrlUnit.IsActive)) + eimic = std::max(eimic, SpeedCtrlUnit.MinPower); break; case 1: switch (MainCtrlPos) { - case 0: //B+ - eimic -= clamp(1.0 + eimic, 0.0, dt*0.14); //odejmuj do -1 + case 0: // B+ + eimic -= clamp(1.0 + eimic, 0.0, dt * 0.14); // odejmuj do -1 break; - case 1: //B - eimic -= clamp(0.0 + eimic, 0.0, dt*0.14); //odejmuj do 0 + case 1: // B + eimic -= clamp(0.0 + eimic, 0.0, dt * 0.14); // odejmuj do 0 break; - case 2: //B- - case 3: //0 - case 4: //T- - eimic -= clamp(0.0 + eimic, 0.0, dt*0.14); //odejmuj do 0 - eimic += clamp(0.0 - eimic, 0.0, dt*0.14); //dodawaj do 0 + case 2: // B- + case 3: // 0 + case 4: // T- + eimic -= clamp(0.0 + eimic, 0.0, dt * 0.14); // odejmuj do 0 + eimic += clamp(0.0 - eimic, 0.0, dt * 0.14); // dodawaj do 0 break; - case 5: //T - eimic += clamp(0.0 - eimic, 0.0, dt*0.14); //dodawaj do 0 + case 5: // T + eimic += clamp(0.0 - eimic, 0.0, dt * 0.14); // dodawaj do 0 break; - case 6: //T+ - eimic += clamp(1.0 - eimic, 0.0, dt*0.14); //dodawaj do 1 + case 6: // T+ + eimic += clamp(1.0 - eimic, 0.0, dt * 0.14); // dodawaj do 1 break; - case 7: //TMax - eimic += clamp(1.0 - eimic, 0.0, dt*0.14); //dodawaj do 1, max + case 7: // TMax + eimic += clamp(1.0 - eimic, 0.0, dt * 0.14); // dodawaj do 1, max break; } - if (MainCtrlPos >= 3 && eimic < 0) eimic = 0; - if (MainCtrlPos <= 3 && eimic > 0) eimic = 0; + if (MainCtrlPos >= 3 && eimic < 0) + eimic = 0; + if (MainCtrlPos <= 3 && eimic > 0) + eimic = 0; break; case 2: - if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay)) + if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime > InitialCtrlDelay)) { - double delta = (MainCtrlActualPos == MainCtrlPos ? dt*CtrlDelay : 0.01); + double delta = (MainCtrlActualPos == MainCtrlPos ? dt * CtrlDelay : 0.01); switch (MainCtrlPos) { case 0: case 1: - eimic -= clamp(1.0 + eimic, 0.0, delta); //odejmuj do -1 - if (eimic > 0) eimic = 0; + eimic -= clamp(1.0 + eimic, 0.0, delta); // odejmuj do -1 + if (eimic > 0) + eimic = 0; break; case 2: - eimic -= clamp(0.0 + eimic, 0.0, delta); //odejmuj do 0 + eimic -= clamp(0.0 + eimic, 0.0, delta); // odejmuj do 0 break; case 3: - eimic += clamp(0.0 - eimic, 0.0, delta); //dodawaj do 0 + eimic += clamp(0.0 - eimic, 0.0, delta); // dodawaj do 0 break; case 4: - eimic += clamp(1.0 - eimic, 0.0, delta); //dodawaj do 1 - if (eimic < 0) eimic = 0; + eimic += clamp(1.0 - eimic, 0.0, delta); // dodawaj do 1 + if (eimic < 0) + eimic = 0; break; } } @@ -7275,26 +7311,30 @@ void TMoverParameters::CheckEIMIC(double dt) case 3: if (UniCtrlIntegratedBrakePNCtrl) { - if ((UniCtrlList[MainCtrlPos].mode != BrakeCtrlPos) && (MainCtrlActualPos == MainCtrlPos)) //there was no move of controller, but brake only + if ((UniCtrlList[MainCtrlPos].mode != BrakeCtrlPos) && (MainCtrlActualPos == MainCtrlPos)) // there was no move of controller, but brake only { if (BrakeCtrlPos < UniCtrlList[MainCtrlPosNo].mode) - BrakeLevelSet(UniCtrlList[MainCtrlPosNo].mode); //bottom clamping + BrakeLevelSet(UniCtrlList[MainCtrlPosNo].mode); // bottom clamping if (BrakeCtrlPos > UniCtrlList[0].mode) - BrakeLevelSet(UniCtrlList[0].mode); //top clamping + BrakeLevelSet(UniCtrlList[0].mode); // top clamping if (IsCabMaster()) { - while (BrakeCtrlPos > UniCtrlList[MainCtrlPos].mode) DecMainCtrl(1); //find nearest position - while (BrakeCtrlPos < UniCtrlList[MainCtrlPos].mode) IncMainCtrl(1); //find nearest position + while (BrakeCtrlPos > UniCtrlList[MainCtrlPos].mode) + DecMainCtrl(1); // find nearest position + while (BrakeCtrlPos < UniCtrlList[MainCtrlPos].mode) + IncMainCtrl(1); // find nearest position } } - else //controller was moved + else // controller was moved BrakeLevelSet(UniCtrlList[MainCtrlPos].mode); } - if ((MainCtrlActualPos != MainCtrlPos) || (LastRelayTime>InitialCtrlDelay)) + 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(-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) @@ -7304,24 +7344,23 @@ void TMoverParameters::CheckEIMIC(double dt) LastRelayTime = 0; MainCtrlActualPos = MainCtrlPos; } - if (Hamulec->GetEDBCP() > 0.3 && eimic < 0 && !UniCtrlIntegratedLocalBrakeCtrl) //when braking with pneumatic brake - eimic = 0; //shut off retarder - if ((UniCtrlIntegratedBrakeCtrl == false)&&(UniCtrlIntegratedLocalBrakeCtrl == false)) + if (Hamulec->GetEDBCP() > 0.3 && eimic < 0 && !UniCtrlIntegratedLocalBrakeCtrl) // when braking with pneumatic brake + eimic = 0; // shut off retarder + if ((UniCtrlIntegratedBrakeCtrl == false) && (UniCtrlIntegratedLocalBrakeCtrl == false)) { eimic = (LocalBrakeRatio() > 0.01 ? -LocalBrakeRatio() : eimic); } - } - if (LocHandleTimeTraxx) + if (LocHandleTimeTraxx) { - if (LocalBrakeRatio() < 0.05) //pozycja 0 + if (LocalBrakeRatio() < 0.05) // pozycja 0 { - eim_localbrake -= dt*0.17; //zmniejszanie + eim_localbrake -= dt * 0.17; // zmniejszanie } - if (LocalBrakeRatio() > 0.15) //pozycja 2 + if (LocalBrakeRatio() > 0.15) // pozycja 2 { - eim_localbrake += dt*0.17; //wzrastanie + eim_localbrake += dt * 0.17; // wzrastanie eim_localbrake = std::max(eim_localbrake, BrakePress / MaxBrakePress[0]); } else @@ -7330,29 +7369,28 @@ void TMoverParameters::CheckEIMIC(double dt) eim_localbrake = 0; } eim_localbrake = clamp(eim_localbrake, 0.0, 1.0); - if (eim_localbrake > 0.04 && eimic > 0) eimic = 0; + if (eim_localbrake > 0.04 && eimic > 0) + eimic = 0; } - auto const eimicpowerenabled { - ( ( true == Mains ) || ( Power == 0.0 ) ) - && ( !SpringBrake.IsActive || !SpringBrakeCutsOffDrive ) - && ( !LockPipe ) - && ( DirAbsolute != 0 ) }; - auto const eimicdoorenabled { - (SpringBrake.IsActive && ReleaseParkingBySpringBrakeWhenDoorIsOpen) - }; + auto const eimicpowerenabled{((true == Mains) || (Power == 0.0)) && (!SpringBrake.IsActive || !SpringBrakeCutsOffDrive) && (!LockPipe) && (DirAbsolute != 0)}; + auto const eimicdoorenabled{(SpringBrake.IsActive && ReleaseParkingBySpringBrakeWhenDoorIsOpen)}; double eimic_max = 0.0; - if ((Doors.instances[side::left].open_permit == false) - && (Doors.instances[side::right].open_permit == false)) { - if (eimicpowerenabled) { + if ((Doors.instances[side::left].open_permit == false) && (Doors.instances[side::right].open_permit == false)) + { + if (eimicpowerenabled) + { eimic_max = 1.0; } - else { + else + { eimic_max = 0.001; } } - else { - if (eimicdoorenabled) { + else + { + if (eimicdoorenabled) + { eimic_max = 0.001; } } @@ -7361,74 +7399,86 @@ void TMoverParameters::CheckEIMIC(double dt) void TMoverParameters::CheckSpeedCtrl(double dt) { - if (EIMCtrlType == 0) - { - SpeedCtrlUnit.DesiredPower = std::max(eimic, 0.0); - } + if (EIMCtrlType == 0) + { + SpeedCtrlUnit.DesiredPower = std::max(eimic, 0.0); + } double accfactor = SpeedCtrlUnit.DesiredPower; - if (EIMCtrlType >= 2) { - if (MainCtrlPos < MainCtrlPosNo - 2) { + if (EIMCtrlType >= 2) + { + if (MainCtrlPos < MainCtrlPosNo - 2) + { SpeedCtrlUnit.Standby = true; } - if (MainCtrlPos > MainCtrlPosNo - 1) { + if (MainCtrlPos > MainCtrlPosNo - 1) + { SpeedCtrlUnit.Standby = false; } - if (!SpeedCtrlUnit.BrakeIntervention) { - if ((Hamulec->GetEDBCP()>0.4) || (PipePress < (HighPipePress - 0.2))) + if (!SpeedCtrlUnit.BrakeIntervention) + { + if ((Hamulec->GetEDBCP() > 0.4) || (PipePress < (HighPipePress - 0.2))) SpeedCtrlUnit.Standby = true; } - if ((EIMCtrlType >= 3)&&(UniCtrlList[MainCtrlPos].SpeedUp <= 0)) { + if ((EIMCtrlType >= 3) && (UniCtrlList[MainCtrlPos].SpeedUp <= 0)) + { accfactor = 0.0; - eimicSpeedCtrl = 0; + eimicSpeedCtrl = 0; } } - if (SpeedCtrlUnit.IsActive) {//speed control - if (true) { - if ((!SpeedCtrlUnit.Standby)) { - if (SpeedCtrlUnit.ManualStateOverride) { - if (eimic > 0.0009) eimic = 1.0; + if (SpeedCtrlUnit.IsActive) + { // speed control + if (true) + { + if ((!SpeedCtrlUnit.Standby)) + { + if (SpeedCtrlUnit.ManualStateOverride) + { + if (eimic > 0.0009) + eimic = 1.0; } double error = (std::max(SpeedCtrlValue + SpeedCtrlUnit.Offset, 0.0) - Vel); double factorP = error > 0 ? SpeedCtrlUnit.FactorPpos : SpeedCtrlUnit.FactorPneg; - double eSCP = clamp(factorP * error, -1.2, 1.0); //P module + double eSCP = clamp(factorP * error, -1.2, 1.0); // P module bool retarder_not_work = (EngineType != TEngineType::DieselEngine) || (Vel < SpeedCtrlUnit.BrakeInterventionVel); if (eSCP < -1.0) { - SpeedCtrlUnit.BrakeInterventionBraking = (eSCP < -1.1) && retarder_not_work && (eimicSpeedCtrl < -0.99 * SpeedCtrlUnit.DesiredPower); + SpeedCtrlUnit.BrakeInterventionBraking = (eSCP < -1.1) && retarder_not_work && (eimicSpeedCtrl < -0.99 * SpeedCtrlUnit.DesiredPower); eSCP = -1.0; } SpeedCtrlUnit.BrakeInterventionUnbraking = (eSCP > 0.0) || (Vel == 0.0); - if (abs(eSCP) < 0.999) { - //TODO: check how to disable integral part when braking in smart way - //double factorI = eimicSpeedCtrlIntegral >= 0 ? SpeedCtrlUnit.FactorIpos : SpeedCtrlUnit.FactorIneg; + if (abs(eSCP) < 0.999) + { + // TODO: check how to disable integral part when braking in smart way + // double factorI = eimicSpeedCtrlIntegral >= 0 ? SpeedCtrlUnit.FactorIpos : SpeedCtrlUnit.FactorIneg; double factorI = eimicSpeedCtrlIntegral >= 0 ? SpeedCtrlUnit.FactorIpos : SpeedCtrlUnit.FactorIneg; eimicSpeedCtrlIntegral = clamp(eimicSpeedCtrlIntegral + factorI * eSCP * dt, -1.0 + eSCP, 1.0 - eSCP); } - else { + else + { eimicSpeedCtrlIntegral = 0; } - auto const DesiredeimicSpeedCtrl { clamp( eimicSpeedCtrlIntegral + eSCP, -SpeedCtrlUnit.DesiredPower, accfactor ) }; - eimicSpeedCtrl = clamp( - DesiredeimicSpeedCtrl, - eimicSpeedCtrl - SpeedCtrlUnit.PowerDownSpeed * dt, - eimicSpeedCtrl + SpeedCtrlUnit.PowerUpSpeed * dt ); - if (Vel < SpeedCtrlUnit.FullPowerVelocity) { + auto const DesiredeimicSpeedCtrl{clamp(eimicSpeedCtrlIntegral + eSCP, -SpeedCtrlUnit.DesiredPower, accfactor)}; + eimicSpeedCtrl = clamp(DesiredeimicSpeedCtrl, eimicSpeedCtrl - SpeedCtrlUnit.PowerDownSpeed * dt, eimicSpeedCtrl + SpeedCtrlUnit.PowerUpSpeed * dt); + if (Vel < SpeedCtrlUnit.FullPowerVelocity) + { eimicSpeedCtrl = std::min(eimicSpeedCtrl, SpeedCtrlUnit.InitialPower); } - if ((Vel < SpeedCtrlUnit.StartVelocity) && (MainCtrlPos < MainCtrlPosNo)) { + if ((Vel < SpeedCtrlUnit.StartVelocity) && (MainCtrlPos < MainCtrlPosNo)) + { eimicSpeedCtrl = 0; eimic = 0; } } - else { + else + { eimicSpeedCtrl = 0; eimicSpeedCtrlIntegral = 0; } SpeedCtrlUnit.Parking = (Vel == 0.0) && (eimic <= 0) && (EngineType != TEngineType::ElectricInductionMotor); SendCtrlToNext("SpeedCtrlUnit.Parking", SpeedCtrlUnit.Parking, CabActive); - } - else { + else + { if (Vmax < 250) eimicSpeedCtrl = clamp(0.5 * (SpeedCtrlValue - Vel), -1.0, 1.0); else @@ -7440,24 +7490,27 @@ void TMoverParameters::CheckSpeedCtrl(double dt) SpeedCtrlUnit.IsActive = false; } } - else { + else + { eimicSpeedCtrl = 1; eimicSpeedCtrlIntegral = 0; SpeedCtrlUnit.Parking = false; - SendCtrlToNext( "SpeedCtrlUnit.Parking", SpeedCtrlUnit.Parking, CabActive ); + SendCtrlToNext("SpeedCtrlUnit.Parking", SpeedCtrlUnit.Parking, CabActive); } } void TMoverParameters::SpeedCtrlButton(int button) { - if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + if ((SpeedCtrl) && (ScndCtrlPos > 0)) + { SpeedCtrlValue = SpeedCtrlButtons[button]; } } void TMoverParameters::SpeedCtrlInc() { - if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + if ((SpeedCtrl) && (ScndCtrlPos > 0)) + { double x = floor(SpeedCtrlValue / SpeedCtrlUnit.VelocityStep) + 1.0; SpeedCtrlValue = std::min(x * SpeedCtrlUnit.VelocityStep, SpeedCtrlUnit.MaxVelocity); } @@ -7465,7 +7518,8 @@ void TMoverParameters::SpeedCtrlInc() void TMoverParameters::SpeedCtrlDec() { - if ((SpeedCtrl) && (ScndCtrlPos > 0)) { + if ((SpeedCtrl) && (ScndCtrlPos > 0)) + { double x = ceil(SpeedCtrlValue / SpeedCtrlUnit.VelocityStep) - 1.0; SpeedCtrlValue = std::max(x * SpeedCtrlUnit.VelocityStep, SpeedCtrlUnit.MinVelocity); } @@ -7473,26 +7527,26 @@ void TMoverParameters::SpeedCtrlDec() bool TMoverParameters::SpeedCtrlPowerInc() { - if (!(SpeedCtrl && ScndCtrlPos > 0)) - return false; + if (!(SpeedCtrl && ScndCtrlPos > 0)) + return false; - if (SpeedCtrlUnit.DesiredPower == SpeedCtrlUnit.MaxPower) - return false; + if (SpeedCtrlUnit.DesiredPower == SpeedCtrlUnit.MaxPower) + return false; - SpeedCtrlUnit.DesiredPower = std::min(SpeedCtrlUnit.DesiredPower + SpeedCtrlUnit.PowerStep, SpeedCtrlUnit.MaxPower); - return true; + SpeedCtrlUnit.DesiredPower = std::min(SpeedCtrlUnit.DesiredPower + SpeedCtrlUnit.PowerStep, SpeedCtrlUnit.MaxPower); + return true; } bool TMoverParameters::SpeedCtrlPowerDec() { - if (!(SpeedCtrl && ScndCtrlPos > 0)) - return false; + if (!(SpeedCtrl && ScndCtrlPos > 0)) + return false; - if (SpeedCtrlUnit.DesiredPower == SpeedCtrlUnit.MinPower) - return false; + if (SpeedCtrlUnit.DesiredPower == SpeedCtrlUnit.MinPower) + return false; - SpeedCtrlUnit.DesiredPower = std::max(SpeedCtrlUnit.DesiredPower - SpeedCtrlUnit.PowerStep, SpeedCtrlUnit.MinPower); - return true; + SpeedCtrlUnit.DesiredPower = std::max(SpeedCtrlUnit.DesiredPower - SpeedCtrlUnit.PowerStep, SpeedCtrlUnit.MinPower); + return true; } // ************************************************************************************************* @@ -7501,14 +7555,13 @@ bool TMoverParameters::SpeedCtrlPowerDec() // ************************************************************************************************* bool TMoverParameters::dizel_EngageSwitch(double state) { - if ((EngineType == TEngineType::DieselEngine) && (state <= 1) && (state >= 0) && - (state != dizel_engagestate)) - { - dizel_engagestate = state; - return true; - } - else - return false; + if ((EngineType == TEngineType::DieselEngine) && (state <= 1) && (state >= 0) && (state != dizel_engagestate)) + { + dizel_engagestate = state; + return true; + } + else + return false; } // ************************************************************************************************* @@ -7517,32 +7570,32 @@ bool TMoverParameters::dizel_EngageSwitch(double state) // ************************************************************************************************* bool TMoverParameters::dizel_EngageChange(double dt) { - double engagespeed = 0; // OK:boolean; - bool DEC; + double engagespeed = 0; // OK:boolean; + bool DEC; - DEC = false; - if (dizel_engage - dizel_engagestate > 0) - engagespeed = engagedownspeed; - else - engagespeed = engageupspeed; - if (dt > 0.2) - dt = 0.1; - if (abs(dizel_engage - dizel_engagestate) < 0.11) - { - if (dizel_engage != dizel_engagestate) - { - DEC = true; - dizel_engage = dizel_engagestate; - } - // else OK:=false; //już jest false - } - else - { - dizel_engage = dizel_engage + engagespeed * dt * (dizel_engagestate - dizel_engage); - // OK:=false; - } - // dizel_EngageChange:=OK; - return DEC; + DEC = false; + if (dizel_engage - dizel_engagestate > 0) + engagespeed = engagedownspeed; + else + engagespeed = engageupspeed; + if (dt > 0.2) + dt = 0.1; + if (abs(dizel_engage - dizel_engagestate) < 0.11) + { + if (dizel_engage != dizel_engagestate) + { + DEC = true; + dizel_engage = dizel_engagestate; + } + // else OK:=false; //już jest false + } + else + { + dizel_engage = dizel_engage + engagespeed * dt * (dizel_engagestate - dizel_engage); + // OK:=false; + } + // dizel_EngageChange:=OK; + return DEC; } // ************************************************************************************************* @@ -7551,213 +7604,207 @@ bool TMoverParameters::dizel_EngageChange(double dt) // ************************************************************************************************* bool TMoverParameters::dizel_AutoGearCheck(void) { - auto OK { false }; + auto OK{false}; - auto const VelUp { ( MotorParam[ ScndCtrlActualPos ].mfi0 != 0.0 ? - MotorParam[ ScndCtrlActualPos ].mfi0 + ( MotorParam[ ScndCtrlActualPos ].mfi - MotorParam[ ScndCtrlActualPos ].mfi0 ) * std::max( 0.0, eimic_real ) : - MotorParam[ ScndCtrlActualPos ].mfi ) }; + auto const VelUp{(MotorParam[ScndCtrlActualPos].mfi0 != 0.0 ? + MotorParam[ScndCtrlActualPos].mfi0 + (MotorParam[ScndCtrlActualPos].mfi - MotorParam[ScndCtrlActualPos].mfi0) * std::max(0.0, eimic_real) : + MotorParam[ScndCtrlActualPos].mfi)}; - auto const VelDown { ( ( MotorParam[ ScndCtrlActualPos ].fi0 != 0.0 ) && ( eimic_real <= 0.0 ) ? - MotorParam[ ScndCtrlActualPos ].fi0 : - MotorParam[ ScndCtrlActualPos ].fi ) }; + auto const VelDown{((MotorParam[ScndCtrlActualPos].fi0 != 0.0) && (eimic_real <= 0.0) ? MotorParam[ScndCtrlActualPos].fi0 : MotorParam[ScndCtrlActualPos].fi)}; - if (MotorParam[ScndCtrlActualPos].AutoSwitch && Mains) - { - if ((RList[MainCtrlPos].Mn == 0)&&(!hydro_TC)) - { - if (dizel_engagestate > 0) - dizel_EngageSwitch(0); - if ((IsMainCtrlNoPowerPos()) && (ScndCtrlActualPos > 0)) - dizel_automaticgearstatus = -1; - } - else - { - if (MotorParam[ScndCtrlActualPos].AutoSwitch && - (dizel_automaticgearstatus == 0)) // sprawdz czy zmienic biegi - { - if( Vel > VelUp ) { - // shift up - if( ScndCtrlActualPos < ScndCtrlPosNo ) { - dizel_automaticgearstatus = 1; - OK = true; - } - } - else if( Vel < VelDown ) { - // shift down - if( ScndCtrlActualPos > 0 ) { - dizel_automaticgearstatus = -1; - OK = true; - } - } - } - } - if ((dizel_engage < 0.1) && (dizel_automaticgearstatus != 0)) - { - if (dizel_automaticgearstatus == 1) - ScndCtrlActualPos++; - else - ScndCtrlActualPos--; - dizel_automaticgearstatus = 0; - dizel_EngageSwitch(1.0); - OK = true; - } - } + if (MotorParam[ScndCtrlActualPos].AutoSwitch && Mains) + { + if ((RList[MainCtrlPos].Mn == 0) && (!hydro_TC)) + { + if (dizel_engagestate > 0) + dizel_EngageSwitch(0); + if ((IsMainCtrlNoPowerPos()) && (ScndCtrlActualPos > 0)) + dizel_automaticgearstatus = -1; + } + else + { + if (MotorParam[ScndCtrlActualPos].AutoSwitch && (dizel_automaticgearstatus == 0)) // sprawdz czy zmienic biegi + { + if (Vel > VelUp) + { + // shift up + if (ScndCtrlActualPos < ScndCtrlPosNo) + { + dizel_automaticgearstatus = 1; + OK = true; + } + } + else if (Vel < VelDown) + { + // shift down + if (ScndCtrlActualPos > 0) + { + dizel_automaticgearstatus = -1; + OK = true; + } + } + } + } + if ((dizel_engage < 0.1) && (dizel_automaticgearstatus != 0)) + { + if (dizel_automaticgearstatus == 1) + ScndCtrlActualPos++; + else + ScndCtrlActualPos--; + dizel_automaticgearstatus = 0; + dizel_EngageSwitch(1.0); + OK = true; + } + } - if (Mains) - { - if (EIMCtrlType > 0) //sterowanie komputerowe + if (Mains) + { + if (EIMCtrlType > 0) // sterowanie komputerowe { if (dizel_automaticgearstatus == 0) { if ((hydro_TC && hydro_TC_Fill > 0.01) || (eimic_real > 0.005)) dizel_EngageSwitch(1.0); + else if (Vel > hydro_R_EngageVel && hydro_R && hydro_R_Fill > 0.01) + dizel_EngageSwitch(0.5); else - if (Vel > hydro_R_EngageVel && hydro_R && hydro_R_Fill > 0.01) - dizel_EngageSwitch(0.5); - else - dizel_EngageSwitch(0.0); + dizel_EngageSwitch(0.0); } else dizel_EngageSwitch(0.0); } - else - if (dizel_automaticgearstatus == 0) // ustaw cisnienie w silowniku sprzegla} - switch (RList[MainCtrlPos].Mn) - { - case 1: - dizel_EngageSwitch(0.5); + else if (dizel_automaticgearstatus == 0) // ustaw cisnienie w silowniku sprzegla} + switch (RList[MainCtrlPos].Mn) + { + case 1: + dizel_EngageSwitch(0.5); break; - case 2: - dizel_EngageSwitch(1.0); + case 2: + dizel_EngageSwitch(1.0); break; case 3: - if (Vel>dizel_minVelfullengage) + if (Vel > dizel_minVelfullengage) dizel_EngageSwitch(1.0); else dizel_EngageSwitch(0.5); break; case 4: - if (Vel>dizel_minVelfullengage) + if (Vel > dizel_minVelfullengage) dizel_EngageSwitch(1.0); else dizel_EngageSwitch(0.66); break; case 5: - if (Vel>dizel_minVelfullengage) + if (Vel > dizel_minVelfullengage) dizel_EngageSwitch(1.0); else - dizel_EngageSwitch(0.35*(1+RList[MainCtrlPos].R)*RList[MainCtrlPos].R); + dizel_EngageSwitch(0.35 * (1 + RList[MainCtrlPos].R) * RList[MainCtrlPos].R); break; - default: - if (hydro_TC && hydro_TC_Fill>0.01) + default: + if (hydro_TC && hydro_TC_Fill > 0.01) dizel_EngageSwitch(1.0); else dizel_EngageSwitch(0.0); - } - else - dizel_EngageSwitch(0.0); - if (!(MotorParam[ScndCtrlActualPos].mIsat > 0)) - dizel_EngageSwitch(0.0); // wylacz sprzeglo na pozycjach neutralnych - if (!AutoRelayFlag) - ScndCtrlActualPos = ScndCtrlPos; - } - return OK; + } + else + dizel_EngageSwitch(0.0); + if (!(MotorParam[ScndCtrlActualPos].mIsat > 0)) + dizel_EngageSwitch(0.0); // wylacz sprzeglo na pozycjach neutralnych + if (!AutoRelayFlag) + ScndCtrlActualPos = ScndCtrlPos; + } + return OK; } // performs diesel engine startup procedure; potentially clears startup switch; returns: true if the engine can be started, false otherwise -bool TMoverParameters::dizel_StartupCheck() { +bool TMoverParameters::dizel_StartupCheck() +{ - auto engineisready { true }; // make inital optimistic presumption, then watch the reality crush it + auto engineisready{true}; // make inital optimistic presumption, then watch the reality crush it - // test the fuel pump - // TODO: add fuel pressure check - if( ( false == FuelPump.is_active ) - || ( ( EngineType == TEngineType::DieselEngine ) && ( RList[ MainCtrlPos ].R == 0.0 ) ) ) { - engineisready = false; -// if( FuelPump.start_type == start_t::manual ) { - // with manual pump control startup procedure is done only once per starter switch press - dizel_startup = false; -// } - } - // test the oil pump - if( ( false == OilPump.is_active ) - || ( OilPump.pressure < OilPump.pressure_minimum ) ) { - engineisready = false; - if( OilPump.start_type == start_t::manual ) { - // with manual pump control startup procedure is done only once per starter switch press - dizel_startup = false; - } - } - // test the water circuits and water temperature - if( true == dizel_heat.PA ) { - engineisready = false; - // TBD, TODO: reset startup procedure depending on pump and heater control mode - dizel_startup = false; - } + // test the fuel pump + // TODO: add fuel pressure check + if ((false == FuelPump.is_active) || ((EngineType == TEngineType::DieselEngine) && (RList[MainCtrlPos].R == 0.0))) + { + engineisready = false; + // if( FuelPump.start_type == start_t::manual ) { + // with manual pump control startup procedure is done only once per starter switch press + dizel_startup = false; + // } + } + // test the oil pump + if ((false == OilPump.is_active) || (OilPump.pressure < OilPump.pressure_minimum)) + { + engineisready = false; + if (OilPump.start_type == start_t::manual) + { + // with manual pump control startup procedure is done only once per starter switch press + dizel_startup = false; + } + } + // test the water circuits and water temperature + if (true == dizel_heat.PA) + { + engineisready = false; + // TBD, TODO: reset startup procedure depending on pump and heater control mode + dizel_startup = false; + } - return engineisready; + return engineisready; } // ************************************************************************************************* // Q: 20160715 // Aktualizacja stanu silnika // ************************************************************************************************* -bool TMoverParameters::dizel_Update(double dt) { +bool TMoverParameters::dizel_Update(double dt) +{ - WaterPumpCheck( dt ); - WaterHeaterCheck( dt ); - OilPumpCheck( dt ); - FuelPumpCheck( dt ); - if( ( true == dizel_startup ) - && ( true == dizel_StartupCheck() ) ) { - dizel_ignition = true; - } + WaterPumpCheck(dt); + WaterHeaterCheck(dt); + OilPumpCheck(dt); + FuelPumpCheck(dt); + if ((true == dizel_startup) && (true == dizel_StartupCheck())) + { + dizel_ignition = true; + } - if( ( true == dizel_ignition ) - && ( LastSwitchingTime >= InitialCtrlDelay ) ) { + if ((true == dizel_ignition) && (LastSwitchingTime >= InitialCtrlDelay)) + { - dizel_startup = false; - dizel_ignition = false; - // TODO: split engine and main circuit state indicator in two separate flags - LastSwitchingTime = 0; - Mains = true; - dizel_spinup = true; - enrot = std::max( - enrot, - 0.35 * ( // TODO: dac zaleznie od temperatury i baterii - EngineType == TEngineType::DieselEngine ? - dizel_nmin : - DElist[ 0 ].RPM / 60.0 ) ); + dizel_startup = false; + dizel_ignition = false; + // TODO: split engine and main circuit state indicator in two separate flags + LastSwitchingTime = 0; + Mains = true; + dizel_spinup = true; + enrot = std::max(enrot, + 0.35 * ( // TODO: dac zaleznie od temperatury i baterii + EngineType == TEngineType::DieselEngine ? dizel_nmin : DElist[0].RPM / 60.0)); + } - } + dizel_spinup = (dizel_spinup && Mains && (enrot < 0.95 * (EngineType == TEngineType::DieselEngine ? dizel_nmin : DElist[0].RPM / 60.0))); - dizel_spinup = ( - dizel_spinup - && Mains - && ( enrot < 0.95 * ( - EngineType == TEngineType::DieselEngine ? - dizel_nmin : - DElist[ 0 ].RPM / 60.0 ) ) ); + if ((true == Mains) && (false == FuelPump.is_active)) + { + // knock out the engine if the fuel pump isn't feeding it + // TBD, TODO: grace period before the engine is starved for fuel and knocked out + MainSwitch(false); + } - if( ( true == Mains ) - && ( false == FuelPump.is_active ) ) { - // knock out the engine if the fuel pump isn't feeding it - // TBD, TODO: grace period before the engine is starved for fuel and knocked out - MainSwitch( false ); - } + bool DU{false}; - bool DU { false }; + if (EngineType == TEngineType::DieselEngine) + { + dizel_EngageChange(dt); + DU = dizel_AutoGearCheck(); + double const fillspeed{2}; + dizel_fill = dizel_fill + fillspeed * dt * (dizel_fillcheck(MainCtrlPos, dt) - dizel_fill); + } - if( EngineType == TEngineType::DieselEngine ) { - dizel_EngageChange( dt ); - DU = dizel_AutoGearCheck(); - double const fillspeed { 2 }; - dizel_fill = dizel_fill + fillspeed * dt * ( dizel_fillcheck( MainCtrlPos , dt ) - dizel_fill ); - } + dizel_Heat(dt); - dizel_Heat( dt ); - - return DU; + return DU; } // ************************************************************************************************* @@ -7765,26 +7812,26 @@ bool TMoverParameters::dizel_Update(double dt) { // oblicza napelnienie, uzwglednia regulator obrotow // ************************************************************************************************* double TMoverParameters::dizel_fillcheck(int mcp, double dt) -{ - auto realfill { 0.0 }; +{ + auto realfill{0.0}; - if( ( true == Mains ) - && ( MainCtrlPosNo > 0 ) - && ( true == FuelPump.is_active ) ) { + if ((true == Mains) && (MainCtrlPosNo > 0) && (true == FuelPump.is_active)) + { - if( ( true == dizel_ignition ) - && ( LastSwitchingTime >= 0.9 * InitialCtrlDelay ) ) { - // wzbogacenie przy rozruchu - // NOTE: ignition flag is reset before this code is executed - // TODO: sort this out - realfill = 1; - } - else { - // napelnienie zalezne od MainCtrlPos + if ((true == dizel_ignition) && (LastSwitchingTime >= 0.9 * InitialCtrlDelay)) + { + // wzbogacenie przy rozruchu + // NOTE: ignition flag is reset before this code is executed + // TODO: sort this out + realfill = 1; + } + else + { + // napelnienie zalezne od MainCtrlPos if (EIMCtrlType > 0) { - realfill = std::max(0.0, std::min(eimic_real, 1 - MotorParam[ ScndCtrlActualPos ].Isat)); - if (eimic_real>0.005 && !hydro_TC_Lockup) + realfill = std::max(0.0, std::min(eimic_real, 1 - MotorParam[ScndCtrlActualPos].Isat)); + if (eimic_real > 0.005 && !hydro_TC_Lockup) { dizel_nreg_min = std::min(dizel_nreg_min + 2.5 * dt, dizel_nmin_hdrive + eimic_real * dizel_nmin_hdrive_factor); } @@ -7809,57 +7856,57 @@ double TMoverParameters::dizel_fillcheck(int mcp, double dt) dizel_nreg_max = dizel_nmax; realfill = RList[mcp].R; } - } - if (dizel_nmax_cutoff > 0) - { - auto nreg { 0.0 }; + } + if (dizel_nmax_cutoff > 0) + { + auto nreg{0.0}; if (EIMCtrlType > 0) nreg = (eimic_real > 0.005 ? dizel_nreg_max : dizel_nmin); else - switch (RList[MainCtrlPos].Mn) - { - case 0: - case 1: - nreg = dizel_nmin; - break; - case 2: - if ((dizel_automaticgearstatus == 0)&&(true/*(!hydro_TC) || (dizel_engage>dizel_fill)*/)) - nreg = dizel_nreg_max; - else - nreg = dizel_nmin; - break; - case 3: - if ((dizel_automaticgearstatus == 0) && (Vel > dizel_minVelfullengage)) - nreg = dizel_nreg_max; - else + switch (RList[MainCtrlPos].Mn) + { + case 0: + case 1: nreg = dizel_nmin; - break; - case 4: - if ((dizel_automaticgearstatus == 0) && (Vel > dizel_minVelfullengage)) - nreg = dizel_nmax; - else - nreg = dizel_nmin * 0.75 + dizel_nreg_max * 0.25; - break; - case 5: - if (Vel > dizel_minVelfullengage) - nreg = dizel_nreg_max; - else - nreg = dizel_nmin + 0.8 * (dizel_nreg_max - dizel_nmin) * RList[mcp].R; - break; - default: - realfill = 0; // sluczaj - break; - } - if (enrot > nreg) //nad predkoscia regulatora zeruj dawke - realfill = 0; - if (enrot < nreg) //pod predkoscia regulatora dawka zadana + break; + case 2: + if ((dizel_automaticgearstatus == 0) && (true /*(!hydro_TC) || (dizel_engage>dizel_fill)*/)) + nreg = dizel_nreg_max; + else + nreg = dizel_nmin; + break; + case 3: + if ((dizel_automaticgearstatus == 0) && (Vel > dizel_minVelfullengage)) + nreg = dizel_nreg_max; + else + nreg = dizel_nmin; + break; + case 4: + if ((dizel_automaticgearstatus == 0) && (Vel > dizel_minVelfullengage)) + nreg = dizel_nmax; + else + nreg = dizel_nmin * 0.75 + dizel_nreg_max * 0.25; + break; + case 5: + if (Vel > dizel_minVelfullengage) + nreg = dizel_nreg_max; + else + nreg = dizel_nmin + 0.8 * (dizel_nreg_max - dizel_nmin) * RList[mcp].R; + break; + default: + realfill = 0; // sluczaj + break; + } + if (enrot > nreg) // nad predkoscia regulatora zeruj dawke + realfill = 0; + if (enrot < nreg) // pod predkoscia regulatora dawka zadana realfill = realfill; - if ((enrot < dizel_nreg_min)&&(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; - } - } + } + } - return clamp( realfill, 0.0, 1.0 ); + return clamp(realfill, 0.0, 1.0); } // ************************************************************************************************* @@ -7868,21 +7915,24 @@ double TMoverParameters::dizel_fillcheck(int mcp, double dt) // ************************************************************************************************* double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) { // liczy moment sily wytwarzany przez silnik spalinowy} - double Moment = 0, enMoment = 0, gearMoment = 0, eps = 0, newn = 0, friction = 0, neps = 0; + double Moment = 0, enMoment = 0, gearMoment = 0, eps = 0, newn = 0, friction = 0, neps = 0; double TorqueH = 0, TorqueL = 0, TorqueC = 0; n = n * CabActive; - if ((MotorParam[ScndCtrlActualPos].mIsat < 0.001)||(DirActive == 0)) + if ((MotorParam[ScndCtrlActualPos].mIsat < 0.001) || (DirActive == 0)) n = enrot; - friction = dizel_engagefriction; - hydro_TC_nIn = enrot; //wal wejsciowy przetwornika momentu - hydro_TC_nOut = dizel_n_old; //wal wyjsciowy przetwornika momentu - neps = (n - dizel_n_old) / dt; //przyspieszenie katowe walu wejsciowego skrzyni biegow + friction = dizel_engagefriction; + hydro_TC_nIn = enrot; // wal wejsciowy przetwornika momentu + hydro_TC_nOut = dizel_n_old; // wal wyjsciowy przetwornika momentu + neps = (n - dizel_n_old) / dt; // przyspieszenie katowe walu wejsciowego skrzyni biegow - if( enrot > 0 ) { - if (dizel_Momentum_Table.size() > 1) { + if (enrot > 0) + { + if (dizel_Momentum_Table.size() > 1) + { Moment = TableInterpolation(dizel_Momentum_Table, enrot) * dizel_fill - dizel_Mstand; } - else { + else + { Moment = (dizel_Mmax - (dizel_Mmax - dizel_Mnmax) * square((enrot - dizel_nMmax) / (dizel_nMmax - dizel_nmax))) * dizel_fill - dizel_Mstand; } Mm = Moment; @@ -7890,45 +7940,46 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) dizel_FuelConsumptedTotal += dizel_FuelConsumptionActual * dt / 3600.0; if ((hydro_R) && (hydro_R_Placement == 2)) Moment -= dizel_MomentumRetarder(enrot, dt); - } - else { - Moment = -dizel_Mstand; - } - if( ( enrot < dizel_nmin / 10.0 ) - && ( eAngle < M_PI_2 ) ) { - // wstrzymywanie przy malych obrotach - Moment -= dizel_Mstand; - } + } + else + { + Moment = -dizel_Mstand; + } + if ((enrot < dizel_nmin / 10.0) && (eAngle < M_PI_2)) + { + // wstrzymywanie przy malych obrotach + Moment -= dizel_Mstand; + } if (true == dizel_spinup) - Moment += dizel_Mstand / (0.3 + std::max(0.0, enrot/dizel_nmin)); //rozrusznik + Moment += dizel_Mstand / (0.3 + std::max(0.0, enrot / dizel_nmin)); // rozrusznik dizel_Torque = Moment; - if (hydro_TC) //jesli przetwornik momentu + if (hydro_TC) // jesli przetwornik momentu { - //napelnianie przetwornika + // napelnianie przetwornika bool IsPower = (EIMCtrlType > 0 ? eimic_real > 0.005 : MainCtrlPowerPos() > 0); - if ((IsPower) && (Mains) && (enrot>dizel_nmin*0.9)) + if ((IsPower) && (Mains) && (enrot > dizel_nmin * 0.9)) hydro_TC_Fill += hydro_TC_FillRateInc * dt; - //oproznianie przetwornika - if (((!IsPower) && (Vel hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (IsPower)) { + // blokowanie sprzegla blokującego + if ((Vel > hydro_TC_LockupSpeed) && (Mains) && (enrot > 0.9 * dizel_nmin) && (IsPower)) + { hydro_TC_Lockup = true; - hydro_TC_LockupRate += hydro_TC_FillRateInc*dt; + hydro_TC_LockupRate += hydro_TC_FillRateInc * dt; } - //luzowanie sprzegla blokujacego - if ((Vel < (IsPower ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) { + // luzowanie sprzegla blokujacego + if ((Vel < (IsPower ? hydro_TC_LockupSpeed : hydro_TC_UnlockSpeed)) || (!Mains) || (enrot < 0.8 * dizel_nmin)) + { hydro_TC_Lockup = false; - 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); } else @@ -7937,18 +7988,19 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) hydro_TC_LockupRate = 0.0; } - //obliczanie momentow poszczegolnych sprzegiel - //sprzeglo glowne (skrzynia biegow) + // obliczanie momentow poszczegolnych sprzegiel + // sprzeglo glowne (skrzynia biegow) TorqueC = dizel_engageMaxForce * dizel_engage * dizel_engageDia * friction; - if (hydro_TC) //jesli hydro + if (hydro_TC) // jesli hydro { double HydroTorque = 0; HydroTorque += hydro_TC_nIn * hydro_TC_nIn * hydro_TC_TorqueInIn; HydroTorque += (hydro_TC_nIn - hydro_TC_nOut) * hydro_TC_TorqueInOut; HydroTorque += hydro_TC_nOut * hydro_TC_nOut * hydro_TC_TorqueOutOut; double nOut2In = hydro_TC_nOut / std::max(0.01, hydro_TC_nIn); - if (hydro_TC_Table.size() > 1) { + if (hydro_TC_Table.size() > 1) + { hydro_TC_TMRatio = TableInterpolation(hydro_TC_Table, nOut2In); hydro_TC_TorqueOut = HydroTorque * hydro_TC_Fill * hydro_TC_TMRatio; hydro_TC_TorqueIn = HydroTorque * hydro_TC_Fill * std::min(1.0, hydro_TC_TMRatio); @@ -7973,12 +8025,12 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) } else { - TorqueH = 0; //brak przetwornika oznacza brak momentu - TorqueL = 1 + TorqueC * 2; //zabezpieczenie, polaczenie trwale + TorqueH = 0; // brak przetwornika oznacza brak momentu + TorqueL = 1 + TorqueC * 2; // zabezpieczenie, polaczenie trwale } - //sprawdzanie dociskow poszczegolnych sprzegiel - if (abs(Moment) > Min0R(TorqueC, TorqueL + abs(hydro_TC_TorqueIn)) || (abs(dizel_n_old - enrot) > 0.1)) //slizga sie z powodu roznic predkosci albo przekroczenia momentu + // sprawdzanie dociskow poszczegolnych sprzegiel + if (abs(Moment) > Min0R(TorqueC, TorqueL + abs(hydro_TC_TorqueIn)) || (abs(dizel_n_old - enrot) > 0.1)) // slizga sie z powodu roznic predkosci albo przekroczenia momentu { dizel_engagedeltaomega = enrot - dizel_n_old; @@ -7988,57 +8040,57 @@ double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt) { hydro_TC_nOut = n; gearMoment = TorqueL + abs(TorqueH) * sign(dizel_engagedeltaomega); - enMoment = Moment - (TorqueL + abs(hydro_TC_TorqueIn))* sign(dizel_engagedeltaomega); + enMoment = Moment - (TorqueL + abs(hydro_TC_TorqueIn)) * sign(dizel_engagedeltaomega); } else { - hydro_TC_nOut = enrot - (n - enrot)*(TorqueC - TorqueL) / TorqueH; //slizganie proporcjonalne, zeby przetwornik nadrabial + hydro_TC_nOut = enrot - (n - enrot) * (TorqueC - TorqueL) / TorqueH; // slizganie proporcjonalne, zeby przetwornik nadrabial gearMoment = TorqueC * sign(dizel_engagedeltaomega); enMoment = Moment - gearMoment; } - } else { hydro_TC_nOut = enrot; - gearMoment = (TorqueC) * sign(dizel_engagedeltaomega); + gearMoment = (TorqueC)*sign(dizel_engagedeltaomega); enMoment = Moment - gearMoment; } eps = enMoment / dizel_AIM; newn = enrot + eps * dt; - if (((newn - n)*(enrot - dizel_n_old) < 0)&&(TorqueC>0.1)) //przejscie przez zero - slizgalo sie i przestało + if (((newn - n) * (enrot - dizel_n_old) < 0) && (TorqueC > 0.1)) // przejscie przez zero - slizgalo sie i przestało newn = n; - if ((newn * enrot <= 0) && (eps * enrot < 0)) //przejscie przez zero obrotow + if ((newn * enrot <= 0) && (eps * enrot < 0)) // przejscie przez zero obrotow newn = 0; enrot = newn; } - else //nie slizga sie (jeszcze) + else // nie slizga sie (jeszcze) { dizel_engagedeltaomega = 0; gearMoment = Moment; enMoment = 0; double enrot_min = 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)) + { + MainSwitch(false); + enrot = 0; + } - if( ( enrot <= 0 ) && ( false == dizel_spinup ) ) { - MainSwitch( false ); - enrot = 0; - } + dizel_n_old = n; // obecna predkosc katowa na potrzeby kolejnej klatki - dizel_n_old = n; //obecna predkosc katowa na potrzeby kolejnej klatki - - return gearMoment; + return gearMoment; } double TMoverParameters::dizel_MomentumRetarder(double n, double dt) { double RetarderRequest = (Mains ? std::max(0.0, -eimic_real) : 0); - if (hydro_R_WithIndividual) RetarderRequest = LocalBrakeRatio(); + if (hydro_R_WithIndividual) + RetarderRequest = LocalBrakeRatio(); if (Vel < hydro_R_MinVel) RetarderRequest = 0; if ((hydro_R_Placement == 2) && (enrot < dizel_nmin)) @@ -8047,14 +8099,13 @@ double TMoverParameters::dizel_MomentumRetarder(double n, double dt) } hydro_R_ClutchActive = (!hydro_R_Clutch) || (RetarderRequest > 0); - if ((!hydro_R_Clutch) - || ((hydro_R_ClutchActive) && (hydro_R_ClutchSpeed == 0))) + if ((!hydro_R_Clutch) || ((hydro_R_ClutchActive) && (hydro_R_ClutchSpeed == 0))) { hydro_R_n = n * 60; } else if (hydro_R_ClutchActive) { - hydro_R_n = sign(n)*std::min(std::abs(hydro_R_n + hydro_R_ClutchSpeed * dt), std::abs(n * 60)); + hydro_R_n = sign(n) * std::min(std::abs(hydro_R_n + hydro_R_ClutchSpeed * dt), std::abs(n * 60)); } else { @@ -8062,713 +8113,648 @@ double TMoverParameters::dizel_MomentumRetarder(double n, double dt) } n = hydro_R_n / 60.f; - if (hydro_R_Fill < RetarderRequest) //gdy zadane hamowanie + if (hydro_R_Fill < RetarderRequest) // gdy zadane hamowanie { - hydro_R_Fill = std::min(hydro_R_Fill + hydro_R_FillRateInc*dt, RetarderRequest); + 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); + hydro_R_Fill = std::max(hydro_R_Fill - hydro_R_FillRateDec * dt, RetarderRequest); } - + double Moment = hydro_R_MaxTorque; double pwr = Moment * std::abs(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; + 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 -void TMoverParameters::dizel_HeatSet( float const Value ) { +void TMoverParameters::dizel_HeatSet(float const Value) +{ - dizel_heat.Te = // TODO: don't include ambient temperature, pull it from environment data instead - dizel_heat.Ts = - dizel_heat.To = - dizel_heat.Tsr = - dizel_heat.Twy = - dizel_heat.Tsr2 = - dizel_heat.Twy2 = - dizel_heat.temperatura1 = - dizel_heat.temperatura2 = Value; + dizel_heat.Te = // TODO: don't include ambient temperature, pull it from environment data instead + dizel_heat.Ts = dizel_heat.To = dizel_heat.Tsr = dizel_heat.Twy = dizel_heat.Tsr2 = dizel_heat.Twy2 = dizel_heat.temperatura1 = dizel_heat.temperatura2 = Value; } // calculates diesel engine temperature and heat transfers // adapted from scripts written by adamst // NOTE: originally executed twice per second -void TMoverParameters::dizel_Heat( double const dt ) { +void TMoverParameters::dizel_Heat(double const dt) +{ - auto const qs { 44700.0 }; - auto const Cs { 11000.0 }; - auto const Cw { 4.189 }; - auto const Co { 1.885 }; - auto const gwmin { 400.0 }; - auto const gwmax { 4000.0 }; - auto const gwmin2 { 400.0 }; - auto const gwmax2 { 4000.0 }; + auto const qs{44700.0}; + auto const Cs{11000.0}; + auto const Cw{4.189}; + auto const Co{1.885}; + auto const gwmin{400.0}; + auto const gwmax{4000.0}; + auto const gwmin2{400.0}; + auto const gwmax2{4000.0}; - dizel_heat.Te = Global.AirTemperature; + dizel_heat.Te = Global.AirTemperature; - auto const engineon { ( Mains ? 1 : 0 ) }; - auto const engineoff { ( Mains ? 0 : 1 ) }; - auto const rpm { enrot * 60 }; - // TODO: calculate this once and cache for further use, instead of doing it repeatedly all over the place - auto const revolutionsfactor { EngineRPMRatio() }; - auto const waterpump { WaterPump.is_active ? 1 : 0 }; + auto const engineon{(Mains ? 1 : 0)}; + auto const engineoff{(Mains ? 0 : 1)}; + auto const rpm{enrot * 60}; + // TODO: calculate this once and cache for further use, instead of doing it repeatedly all over the place + auto const revolutionsfactor{EngineRPMRatio()}; + auto const waterpump{WaterPump.is_active ? 1 : 0}; - auto const gw = engineon * interpolate( gwmin, gwmax, revolutionsfactor ) + waterpump * 1000 + engineoff * 200; - auto const gw2 = engineon * interpolate( gwmin2, gwmax2, revolutionsfactor ) + waterpump * 1000 + engineoff * 200; - auto const gwO = interpolate( gwmin, gwmax, revolutionsfactor ); + auto const gw = engineon * interpolate(gwmin, gwmax, revolutionsfactor) + waterpump * 1000 + engineoff * 200; + auto const gw2 = engineon * interpolate(gwmin2, gwmax2, revolutionsfactor) + waterpump * 1000 + engineoff * 200; + auto const gwO = interpolate(gwmin, gwmax, revolutionsfactor); - dizel_heat.water.is_cold = ( - ( dizel_heat.water.config.temp_min > 0 ) - && ( dizel_heat.temperatura1 < dizel_heat.water.config.temp_min - ( Mains ? 5 : 0 ) ) ); - dizel_heat.water.is_hot = ( - ( dizel_heat.water.config.temp_max > 0 ) - && ( dizel_heat.temperatura1 > dizel_heat.water.config.temp_max - ( dizel_heat.water.is_hot ? 8 : 0 ) ) ); - dizel_heat.water_aux.is_cold = ( - ( dizel_heat.water_aux.config.temp_min > 0 ) - && ( dizel_heat.temperatura2 < dizel_heat.water_aux.config.temp_min - ( Mains ? 5 : 0 ) ) ); - dizel_heat.water_aux.is_hot = ( - ( dizel_heat.water_aux.config.temp_max > 0 ) - && ( dizel_heat.temperatura2 > dizel_heat.water_aux.config.temp_max - ( dizel_heat.water_aux.is_hot ? 8 : 0 ) ) ); - dizel_heat.oil.is_cold = ( - ( dizel_heat.oil.config.temp_min > 0 ) - && ( dizel_heat.To < dizel_heat.oil.config.temp_min - ( Mains ? 5 : 0 ) ) ); - dizel_heat.oil.is_hot = ( - ( dizel_heat.oil.config.temp_max > 0 ) - && ( dizel_heat.To > dizel_heat.oil.config.temp_max - ( dizel_heat.oil.is_hot ? 8 : 0 ) ) ); - // engine overheat check - dizel_heat.engine_is_hot = ( - ( dizel_heat.engine_max_temp > 0 ) - && ( dizel_heat.Ts > dizel_heat.engine_max_temp - ( dizel_heat.engine_is_hot ? 8 : 0 ) ) ); + dizel_heat.water.is_cold = ((dizel_heat.water.config.temp_min > 0) && (dizel_heat.temperatura1 < dizel_heat.water.config.temp_min - (Mains ? 5 : 0))); + dizel_heat.water.is_hot = ((dizel_heat.water.config.temp_max > 0) && (dizel_heat.temperatura1 > dizel_heat.water.config.temp_max - (dizel_heat.water.is_hot ? 8 : 0))); + dizel_heat.water_aux.is_cold = ((dizel_heat.water_aux.config.temp_min > 0) && (dizel_heat.temperatura2 < dizel_heat.water_aux.config.temp_min - (Mains ? 5 : 0))); + dizel_heat.water_aux.is_hot = ((dizel_heat.water_aux.config.temp_max > 0) && (dizel_heat.temperatura2 > dizel_heat.water_aux.config.temp_max - (dizel_heat.water_aux.is_hot ? 8 : 0))); + dizel_heat.oil.is_cold = ((dizel_heat.oil.config.temp_min > 0) && (dizel_heat.To < dizel_heat.oil.config.temp_min - (Mains ? 5 : 0))); + dizel_heat.oil.is_hot = ((dizel_heat.oil.config.temp_max > 0) && (dizel_heat.To > dizel_heat.oil.config.temp_max - (dizel_heat.oil.is_hot ? 8 : 0))); + // engine overheat check + dizel_heat.engine_is_hot = ((dizel_heat.engine_max_temp > 0) && (dizel_heat.Ts > dizel_heat.engine_max_temp - (dizel_heat.engine_is_hot ? 8 : 0))); - auto const PT = ( - ( false == dizel_heat.water.is_cold ) - && ( false == dizel_heat.water.is_hot ) - && ( false == dizel_heat.water_aux.is_cold ) - && ( false == dizel_heat.water_aux.is_hot ) - && ( false == dizel_heat.oil.is_cold ) - && ( false == dizel_heat.oil.is_hot ) - && ( false == dizel_heat.engine.is_hot ) /* && ( false == awaria_termostatow ) */ ) /* || PTp */; - auto const PPT = ( false == PT ) /* && ( false == PPTp ) */; - dizel_heat.PA = ( /* ( ( !zamkniecie or niedomkniecie ) and !WBD ) || */ PPT /* || nurnik || ( woda < 7 ) */ ) /* && ( !PAp ) */; + auto const PT = ((false == dizel_heat.water.is_cold) && (false == dizel_heat.water.is_hot) && (false == dizel_heat.water_aux.is_cold) && (false == dizel_heat.water_aux.is_hot) && + (false == dizel_heat.oil.is_cold) && (false == dizel_heat.oil.is_hot) && (false == dizel_heat.engine.is_hot) /* && ( false == awaria_termostatow ) */) /* || PTp */; + auto const PPT = (false == PT) /* && ( false == PPTp ) */; + dizel_heat.PA = (/* ( ( !zamkniecie or niedomkniecie ) and !WBD ) || */ PPT /* || nurnik || ( woda < 7 ) */) /* && ( !PAp ) */; - // engine heat transfers - auto const Ge { engineon * ( 0.21 * dizel_heat.powerfactor * EnginePower + 12 ) / 3600 }; - // TODO: replace fixed heating power cost with more accurate calculation - auto const obciazenie { engineon * ( ( dizel_heat.powerfactor * EnginePower / 950 ) + ( Heating ? HeatingPower : 0 ) + 70 ) }; - auto const Qd { qs * Ge - obciazenie }; - // silnik oddaje czesc ciepla do wody chlodzacej, a takze pewna niewielka czesc do otoczenia, modyfikowane przez okienko - auto const Qs { ( Qd - ( dizel_heat.kfs * ( dizel_heat.Ts - dizel_heat.Tsr ) ) - ( dizel_heat.kfe * /* ( 0.3 + 0.7 * ( dizel_heat.okienko ? 1 : 0 ) ) * */ ( dizel_heat.Ts - dizel_heat.Te ) ) ) }; - auto const dTss { Qs / Cs }; - dizel_heat.Ts += ( dTss * dt ); + // engine heat transfers + auto const Ge{engineon * (0.21 * dizel_heat.powerfactor * EnginePower + 12) / 3600}; + // TODO: replace fixed heating power cost with more accurate calculation + auto const obciazenie{engineon * ((dizel_heat.powerfactor * EnginePower / 950) + (Heating ? HeatingPower : 0) + 70)}; + auto const Qd{qs * Ge - obciazenie}; + // silnik oddaje czesc ciepla do wody chlodzacej, a takze pewna niewielka czesc do otoczenia, modyfikowane przez okienko + auto const Qs{(Qd - (dizel_heat.kfs * (dizel_heat.Ts - dizel_heat.Tsr)) - (dizel_heat.kfe * /* ( 0.3 + 0.7 * ( dizel_heat.okienko ? 1 : 0 ) ) * */ (dizel_heat.Ts - dizel_heat.Te)))}; + auto const dTss{Qs / Cs}; + dizel_heat.Ts += (dTss * dt); - // oil heat transfers - // olej oddaje cieplo do wody gdy krazy przez wymiennik ciepla == wlaczona pompka lub silnik - auto const dTo { ( - dizel_heat.auxiliary_water_circuit ? - ( ( dizel_heat.kfo * ( dizel_heat.Ts - dizel_heat.To ) ) - ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr2 ) ) ) / ( gwO * Co ) : - ( ( dizel_heat.kfo * ( dizel_heat.Ts - dizel_heat.To ) ) - ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr ) ) ) / ( gwO * Co ) ) }; - dizel_heat.To += ( dTo * dt ); + // oil heat transfers + // olej oddaje cieplo do wody gdy krazy przez wymiennik ciepla == wlaczona pompka lub silnik + auto const dTo{(dizel_heat.auxiliary_water_circuit ? ((dizel_heat.kfo * (dizel_heat.Ts - dizel_heat.To)) - (dizel_heat.kfo2 * (dizel_heat.To - dizel_heat.Tsr2))) / (gwO * Co) : + ((dizel_heat.kfo * (dizel_heat.Ts - dizel_heat.To)) - (dizel_heat.kfo2 * (dizel_heat.To - dizel_heat.Tsr))) / (gwO * Co))}; + dizel_heat.To += (dTo * dt); - // heater -/* - if( typ == "SP45" ) - Qp = (float)( podgrzewacz and ( true == WaterPump.is_active ) and ( Twy < 55 ) and ( Twy2 < 55 ) ) * 1000; - else -*/ - auto const Qp = ( ( ( true == WaterHeater.is_active ) && ( true == WaterPump.is_active ) && ( dizel_heat.Twy < 60 ) && ( dizel_heat.Twy2 < 60 ) ) ? 1 : 0 ) * 1000; + // heater + /* + if( typ == "SP45" ) + Qp = (float)( podgrzewacz and ( true == WaterPump.is_active ) and ( Twy < 55 ) and ( Twy2 < 55 ) ) * 1000; + else + */ + auto const Qp = (((true == WaterHeater.is_active) && (true == WaterPump.is_active) && (dizel_heat.Twy < 60) && (dizel_heat.Twy2 < 60)) ? 1 : 0) * 1000; - auto const kurek07 { 1 }; // unknown/unimplemented device TBD, TODO: identify and implement? + auto const kurek07{1}; // unknown/unimplemented device TBD, TODO: identify and implement? - if( true == dizel_heat.auxiliary_water_circuit ) { - // auxiliary water circuit setup - dizel_heat.water_aux.is_warm = ( - ( true == dizel_heat.cooling ) - || ( ( true == Mains ) - && ( BatteryVoltage > ( 0.75 * NominalBatteryVoltage ) ) /* && !bezpompy && !awaria_chlodzenia && !WS10 */ - && ( dizel_heat.water_aux.config.temp_cooling > 0 ) - && ( dizel_heat.temperatura2 > dizel_heat.water_aux.config.temp_cooling - ( dizel_heat.water_aux.is_warm ? 8 : 0 ) ) ) ); - auto const PTC2 { ( dizel_heat.water_aux.is_warm /*or PTC2p*/ ? 1 : 0 ) }; - dizel_heat.rpmwz2 = PTC2 * ( dizel_heat.fan_speed >= 0 ? ( rpm * dizel_heat.fan_speed ) : ( dizel_heat.fan_speed * -1 ) ); - dizel_heat.zaluzje2 = ( dizel_heat.water_aux.config.shutters ? ( PTC2 == 1 ) : true ); // no shutters is an equivalent to having them open - auto const zaluzje2 { ( dizel_heat.zaluzje2 ? 1 : 0 ) }; - // auxiliary water circuit heat transfer values - auto const kf2 { kurek07 * ( ( dizel_heat.kw * ( 0.3 + 0.7 * zaluzje2 ) ) * dizel_heat.rpmw2 + ( dizel_heat.kv * ( 0.3 + 0.7 * zaluzje2 ) * Vel / 3.6 ) ) + 2 }; - auto const dTs2 { ( ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr2 ) ) ) / ( gw2 * Cw ) }; - // przy otwartym kurku B ma³y obieg jest dogrzewany przez du¿y - stosujemy przy korzystaniu z podgrzewacza oraz w zimie - auto const Qch2 { -kf2 * ( dizel_heat.Tsr2 - dizel_heat.Te ) + ( 80 * ( true == WaterCircuitsLink ? 1 : 0 ) * ( dizel_heat.Twy - dizel_heat.Tsr2 ) ) }; - auto const dTch2 { Qch2 / ( gw2 * Cw ) }; - // auxiliary water circuit heat transfers finalization - // NOTE: since primary circuit doesn't read data from the auxiliary one, we can pretty safely finalize auxiliary updates before touching the primary circuit - auto const Twe2 { dizel_heat.Twy2 + ( dTch2 * dt ) }; - dizel_heat.Twy2 = Twe2 + ( dTs2 * dt ); - dizel_heat.Tsr2 = 0.5 * ( dizel_heat.Twy2 + Twe2 ); - dizel_heat.temperatura2 = dizel_heat.Twy2; - } - // primary water circuit setup - dizel_heat.water.is_flowing = ( - ( dizel_heat.water.config.temp_flow < 0 ) - || ( dizel_heat.temperatura1 > dizel_heat.water.config.temp_flow - ( dizel_heat.water.is_flowing ? 5 : 0 ) ) ); - auto const obieg { ( dizel_heat.water.is_flowing ? 1 : 0 ) }; - dizel_heat.water.is_warm = ( - ( true == dizel_heat.cooling ) - || ( ( true == Mains ) - && ( BatteryVoltage > ( 0.75 * NominalBatteryVoltage ) ) /* && !bezpompy && !awaria_chlodzenia && !WS10 */ - && ( dizel_heat.water.config.temp_cooling > 0 ) - && ( dizel_heat.temperatura1 > dizel_heat.water.config.temp_cooling - ( dizel_heat.water.is_warm ? 8 : 0 ) ) ) ); - auto const PTC1 { ( dizel_heat.water.is_warm /*or PTC1p*/ ? 1 : 0 ) }; - dizel_heat.rpmwz = PTC1 * ( dizel_heat.fan_speed >= 0 ? ( rpm * dizel_heat.fan_speed ) : ( dizel_heat.fan_speed * -1 ) ); - dizel_heat.zaluzje1 = ( dizel_heat.water.config.shutters ? ( PTC1 == 1 ) : true ); // no shutters is an equivalent to having them open - auto const zaluzje1 { ( dizel_heat.zaluzje1 ? 1 : 0 ) }; - // primary water circuit heat transfer values - auto const kf { obieg * kurek07 * ( ( dizel_heat.kw * ( 0.3 + 0.7 * zaluzje1 ) ) * dizel_heat.rpmw + ( dizel_heat.kv * ( 0.3 + 0.7 * zaluzje1 ) * Vel / 3.6 ) + 3 ) + 2 }; - auto const dTs { ( - dizel_heat.auxiliary_water_circuit ? - ( ( dizel_heat.kfs * ( dizel_heat.Ts - dizel_heat.Tsr ) ) ) / ( gw * Cw ) : - ( ( dizel_heat.kfs * ( dizel_heat.Ts - dizel_heat.Tsr ) ) + ( dizel_heat.kfo2 * ( dizel_heat.To - dizel_heat.Tsr ) ) ) / ( gw * Cw ) ) }; - auto const Qch { -kf * ( dizel_heat.Tsr - dizel_heat.Te ) + Qp }; - auto const dTch { Qch / ( gw * Cw ) }; - // primary water circuit heat transfers finalization - auto const Twe { dizel_heat.Twy + ( dTch * dt ) }; - dizel_heat.Twy = Twe + ( dTs * dt ); - dizel_heat.Tsr = 0.5 * ( dizel_heat.Twy + Twe ); - dizel_heat.temperatura1 = dizel_heat.Twy; -/* - fuelConsumed = fuelConsumed + ( Ge * 0.5 ); + if (true == dizel_heat.auxiliary_water_circuit) + { + // auxiliary water circuit setup + dizel_heat.water_aux.is_warm = ((true == dizel_heat.cooling) || ((true == Mains) && (BatteryVoltage > (0.75 * NominalBatteryVoltage)) /* && !bezpompy && !awaria_chlodzenia && !WS10 */ + && (dizel_heat.water_aux.config.temp_cooling > 0) && + (dizel_heat.temperatura2 > dizel_heat.water_aux.config.temp_cooling - (dizel_heat.water_aux.is_warm ? 8 : 0)))); + auto const PTC2{(dizel_heat.water_aux.is_warm /*or PTC2p*/ ? 1 : 0)}; + dizel_heat.rpmwz2 = PTC2 * (dizel_heat.fan_speed >= 0 ? (rpm * dizel_heat.fan_speed) : (dizel_heat.fan_speed * -1)); + dizel_heat.zaluzje2 = (dizel_heat.water_aux.config.shutters ? (PTC2 == 1) : true); // no shutters is an equivalent to having them open + auto const zaluzje2{(dizel_heat.zaluzje2 ? 1 : 0)}; + // auxiliary water circuit heat transfer values + auto const kf2{kurek07 * ((dizel_heat.kw * (0.3 + 0.7 * zaluzje2)) * dizel_heat.rpmw2 + (dizel_heat.kv * (0.3 + 0.7 * zaluzje2) * Vel / 3.6)) + 2}; + auto const dTs2{((dizel_heat.kfo2 * (dizel_heat.To - dizel_heat.Tsr2))) / (gw2 * Cw)}; + // przy otwartym kurku B ma³y obieg jest dogrzewany przez du¿y - stosujemy przy korzystaniu z podgrzewacza oraz w zimie + auto const Qch2{-kf2 * (dizel_heat.Tsr2 - dizel_heat.Te) + (80 * (true == WaterCircuitsLink ? 1 : 0) * (dizel_heat.Twy - dizel_heat.Tsr2))}; + auto const dTch2{Qch2 / (gw2 * Cw)}; + // auxiliary water circuit heat transfers finalization + // NOTE: since primary circuit doesn't read data from the auxiliary one, we can pretty safely finalize auxiliary updates before touching the primary circuit + auto const Twe2{dizel_heat.Twy2 + (dTch2 * dt)}; + dizel_heat.Twy2 = Twe2 + (dTs2 * dt); + dizel_heat.Tsr2 = 0.5 * (dizel_heat.Twy2 + Twe2); + dizel_heat.temperatura2 = dizel_heat.Twy2; + } + // primary water circuit setup + dizel_heat.water.is_flowing = ((dizel_heat.water.config.temp_flow < 0) || (dizel_heat.temperatura1 > dizel_heat.water.config.temp_flow - (dizel_heat.water.is_flowing ? 5 : 0))); + auto const obieg{(dizel_heat.water.is_flowing ? 1 : 0)}; + dizel_heat.water.is_warm = + ((true == dizel_heat.cooling) || ((true == Mains) && (BatteryVoltage > (0.75 * NominalBatteryVoltage)) /* && !bezpompy && !awaria_chlodzenia && !WS10 */ + && (dizel_heat.water.config.temp_cooling > 0) && (dizel_heat.temperatura1 > dizel_heat.water.config.temp_cooling - (dizel_heat.water.is_warm ? 8 : 0)))); + auto const PTC1{(dizel_heat.water.is_warm /*or PTC1p*/ ? 1 : 0)}; + dizel_heat.rpmwz = PTC1 * (dizel_heat.fan_speed >= 0 ? (rpm * dizel_heat.fan_speed) : (dizel_heat.fan_speed * -1)); + dizel_heat.zaluzje1 = (dizel_heat.water.config.shutters ? (PTC1 == 1) : true); // no shutters is an equivalent to having them open + auto const zaluzje1{(dizel_heat.zaluzje1 ? 1 : 0)}; + // primary water circuit heat transfer values + auto const kf{obieg * kurek07 * ((dizel_heat.kw * (0.3 + 0.7 * zaluzje1)) * dizel_heat.rpmw + (dizel_heat.kv * (0.3 + 0.7 * zaluzje1) * Vel / 3.6) + 3) + 2}; + auto const dTs{(dizel_heat.auxiliary_water_circuit ? ((dizel_heat.kfs * (dizel_heat.Ts - dizel_heat.Tsr))) / (gw * Cw) : + ((dizel_heat.kfs * (dizel_heat.Ts - dizel_heat.Tsr)) + (dizel_heat.kfo2 * (dizel_heat.To - dizel_heat.Tsr))) / (gw * Cw))}; + auto const Qch{-kf * (dizel_heat.Tsr - dizel_heat.Te) + Qp}; + auto const dTch{Qch / (gw * Cw)}; + // primary water circuit heat transfers finalization + auto const Twe{dizel_heat.Twy + (dTch * dt)}; + dizel_heat.Twy = Twe + (dTs * dt); + dizel_heat.Tsr = 0.5 * (dizel_heat.Twy + Twe); + dizel_heat.temperatura1 = dizel_heat.Twy; + /* + fuelConsumed = fuelConsumed + ( Ge * 0.5 ); - while( fuelConsumed >= 0.83 ) { - fuelConsumed = fuelConsumed - 0.83; - fuelQueue.DestroyProductMatching( null, 1 ); - }//if + while( fuelConsumed >= 0.83 ) { + fuelConsumed = fuelConsumed - 0.83; + fuelQueue.DestroyProductMatching( null, 1 ); + }//if - if( engineon ) - temp_turbo = temp_turbo + 0.3 * ( t_pozycja ); - if( t_pozycja == 0 and cisnienie > 0.04 ) - temp_turbo = temp_turbo - 1; + if( engineon ) + temp_turbo = temp_turbo + 0.3 * ( t_pozycja ); + if( t_pozycja == 0 and cisnienie > 0.04 ) + temp_turbo = temp_turbo - 1; - if( temp_turbo > 400 ) - temp_turbo = 400; - if( temp_turbo < 0 ) - temp_turbo = 0; + if( temp_turbo > 400 ) + temp_turbo = 400; + if( temp_turbo < 0 ) + temp_turbo = 0; - if( temp_turbo > 50 and cisnienie < 0.05 ) - timer_turbo = timer_turbo + 1; + if( temp_turbo > 50 and cisnienie < 0.05 ) + timer_turbo = timer_turbo + 1; - if( temp_turbo == 0 ) - timer_turbo = 0; + if( temp_turbo == 0 ) + timer_turbo = 0; - if( timer_turbo > 360 ) { - awaria_turbo = true; - timer_turbo = 400; - } + if( timer_turbo > 360 ) { + awaria_turbo = true; + timer_turbo = 400; + } - if( Ts < 50 ) - p_odpal = 3; - if( Ts > 49 and Ts < 76 ) - p_odpal = 4; - if( Ts > 75 ) - p_odpal = 7; + if( Ts < 50 ) + p_odpal = 3; + if( Ts > 49 and Ts < 76 ) + p_odpal = 4; + if( Ts > 75 ) + p_odpal = 7; - stukanie = stukanie or awaria_oleju; + stukanie = stukanie or awaria_oleju; - if( awaria_oleju == true and ilosc_oleju > 0 ) { - ilosc_oleju = ilosc_oleju - ( 0.002 * rpm / 1500 ); - } - if( awaria_oleju == true and cisnienie < 0.06 ) - damage = 1; -*/ + if( awaria_oleju == true and ilosc_oleju > 0 ) { + ilosc_oleju = ilosc_oleju - ( 0.002 * rpm / 1500 ); + } + if( awaria_oleju == true and cisnienie < 0.06 ) + damage = 1; + */ } -bool -TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) { +bool TMoverParameters::AssignLoad(std::string const &Name, float const Amount) +{ - if( Name == "pantstate" ) { - if( EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) { - // wartość niby "pantstate" - nazwa dla formalności, ważna jest ilość - auto const pantographsetup { static_cast( Amount ) }; - if( pantographsetup & ( 1 << 2 ) ) { - DoubleTr = -1; - } - if( pantographsetup & ( 1 << 0 ) ) { - if( DoubleTr == 1 ) { OperatePantographValve( end::front, operation_t::enable, range_t::local ); } - else { OperatePantographValve( end::rear, operation_t::enable, range_t::local ); } - } - if( pantographsetup & ( 1 << 1 ) ) { - if( DoubleTr == 1 ) { OperatePantographValve( end::rear, operation_t::enable, range_t::local ); } - else { OperatePantographValve( end::front, operation_t::enable, range_t::local ); } - } - return true; - } - else { - return false; - } - } + if (Name == "pantstate") + { + if (EnginePowerSource.SourceType == TPowerSource::CurrentCollector) + { + // wartość niby "pantstate" - nazwa dla formalności, ważna jest ilość + auto const pantographsetup{static_cast(Amount)}; + if (pantographsetup & (1 << 2)) + { + DoubleTr = -1; + } + if (pantographsetup & (1 << 0)) + { + if (DoubleTr == 1) + { + OperatePantographValve(end::front, operation_t::enable, range_t::local); + } + else + { + OperatePantographValve(end::rear, operation_t::enable, range_t::local); + } + } + if (pantographsetup & (1 << 1)) + { + if (DoubleTr == 1) + { + OperatePantographValve(end::rear, operation_t::enable, range_t::local); + } + else + { + OperatePantographValve(end::front, operation_t::enable, range_t::local); + } + } + return true; + } + else + { + return false; + } + } - if( Name.empty() ) { - // empty the vehicle if requested - LoadTypeChange = ( LoadType.name != Name ); - LoadType = load_attributes(); - LoadAmount = 0.f; - return true; - } - // can't mix load types, at least for the time being - if( ( LoadAmount > 0 ) && ( LoadType.name != Name ) ) { return false; } + if (Name.empty()) + { + // empty the vehicle if requested + LoadTypeChange = (LoadType.name != Name); + LoadType = load_attributes(); + LoadAmount = 0.f; + return true; + } + // can't mix load types, at least for the time being + if ((LoadAmount > 0) && (LoadType.name != Name)) + { + return false; + } - for( auto const &loadattributes : LoadAttributes ) { - if( Name == loadattributes.name ) { - LoadTypeChange = ( LoadType.name != Name ); - LoadType = loadattributes; - LoadAmount = clamp( Amount, 0.f, MaxLoad ) ; - ComputeMass(); - return true; - } - } - // didn't find matching load configuration, this type is unsupported - return false; + for (auto const &loadattributes : LoadAttributes) + { + if (Name == loadattributes.name) + { + LoadTypeChange = (LoadType.name != Name); + LoadType = loadattributes; + LoadAmount = clamp(Amount, 0.f, MaxLoad); + ComputeMass(); + return true; + } + } + // didn't find matching load configuration, this type is unsupported + return false; } // ************************************************************************************************* // Q: 20160713 // Test zakończenia załadunku / rozładunku // ************************************************************************************************* -bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadname) { +bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadname) +{ - if( LSpeed == 0.0 ) { - // zerowa prędkość zmiany, to koniec - LoadStatus = 4; - return true; - } + if (LSpeed == 0.0) + { + // zerowa prędkość zmiany, to koniec + LoadStatus = 4; + return true; + } - if( Loadname.empty() ) { return ( LoadStatus >= 4 ); } - if( Loadname != LoadType.name ) { return ( LoadStatus >= 4 ); } + if (Loadname.empty()) + { + return (LoadStatus >= 4); + } + if (Loadname != LoadType.name) + { + return (LoadStatus >= 4); + } - // test zakończenia załadunku/rozładunku - // load exchange speed is reduced if the wagon is overloaded - auto const loadchange { static_cast( std::abs( LSpeed * LastLoadChangeTime ) * ( LoadAmount > MaxLoad ? 0.5 : 1.0 ) ) }; + // test zakończenia załadunku/rozładunku + // load exchange speed is reduced if the wagon is overloaded + auto const loadchange{static_cast(std::abs(LSpeed * LastLoadChangeTime) * (LoadAmount > MaxLoad ? 0.5 : 1.0))}; - if( LSpeed < 0 ) { - // gdy rozładunek - LoadStatus = 2; // trwa rozładunek (włączenie naliczania czasu) - if( loadchange > 0 ) // jeśli coś przeładowano - { - LastLoadChangeTime = 0; // naliczony czas został zużyty - LoadAmount -= loadchange; // zmniejszenie ilości ładunku - CommandIn.Value1 -= loadchange; // zmniejszenie ilości do rozładowania - if( ( LoadAmount <= 0 ) || ( CommandIn.Value1 <= 0 ) ) { - // pusto lub rozładowano żądaną ilość - LoadStatus = 4; // skończony rozładunek - LoadAmount = clamp( LoadAmount, 0.f, MaxLoad); //ładunek nie może być ujemny - } - if( LoadAmount == 0.f ) { - AssignLoad(""); // jak nic nie ma, to nie ma też nazwy - } - ComputeMass(); - } - } - else if( LSpeed > 0 ) { - // gdy załadunek - LoadStatus = 1; // trwa załadunek (włączenie naliczania czasu) - if( loadchange > 0 ) // jeśli coś przeładowano - { - LastLoadChangeTime = 0; // naliczony czas został zużyty - LoadAmount += loadchange; // zwiększenie ładunku - CommandIn.Value1 -= loadchange; - if( ( LoadAmount >= MaxLoad * ( 1.0 + OverLoadFactor ) ) || ( CommandIn.Value1 <= 0 ) ) { - LoadStatus = 4; // skończony załadunek - LoadAmount = std::min( MaxLoad * ( 1.0 + OverLoadFactor ), LoadAmount ); - } - ComputeMass(); - } - } + if (LSpeed < 0) + { + // gdy rozładunek + LoadStatus = 2; // trwa rozładunek (włączenie naliczania czasu) + if (loadchange > 0) // jeśli coś przeładowano + { + LastLoadChangeTime = 0; // naliczony czas został zużyty + LoadAmount -= loadchange; // zmniejszenie ilości ładunku + CommandIn.Value1 -= loadchange; // zmniejszenie ilości do rozładowania + if ((LoadAmount <= 0) || (CommandIn.Value1 <= 0)) + { + // pusto lub rozładowano żądaną ilość + LoadStatus = 4; // skończony rozładunek + LoadAmount = clamp(LoadAmount, 0.f, MaxLoad); // ładunek nie może być ujemny + } + if (LoadAmount == 0.f) + { + AssignLoad(""); // jak nic nie ma, to nie ma też nazwy + } + ComputeMass(); + } + } + else if (LSpeed > 0) + { + // gdy załadunek + LoadStatus = 1; // trwa załadunek (włączenie naliczania czasu) + if (loadchange > 0) // jeśli coś przeładowano + { + LastLoadChangeTime = 0; // naliczony czas został zużyty + LoadAmount += loadchange; // zwiększenie ładunku + CommandIn.Value1 -= loadchange; + if ((LoadAmount >= MaxLoad * (1.0 + OverLoadFactor)) || (CommandIn.Value1 <= 0)) + { + LoadStatus = 4; // skończony załadunek + LoadAmount = std::min(MaxLoad * (1.0 + OverLoadFactor), LoadAmount); + } + ComputeMass(); + } + } - return ( LoadStatus >= 4 ); + return (LoadStatus >= 4); } -bool TMoverParameters::ChangeDoorPermitPreset( int const Change, range_t const Notify ) { +bool TMoverParameters::ChangeDoorPermitPreset(int const Change, range_t const Notify) +{ - auto const initialstate { Doors.permit_preset }; + auto const initialstate{Doors.permit_preset}; - if( false == Doors.permit_presets.empty() ) { + if (false == Doors.permit_presets.empty()) + { - Doors.permit_preset = clamp( Doors.permit_preset + Change, 0, Doors.permit_presets.size() - 1 ); - auto const doors { Doors.permit_presets[ Doors.permit_preset ] }; - auto const permitleft { ( ( doors & 1 ) != 0 ) }; - auto const permitright { ( ( doors & 2 ) != 0 ) }; + Doors.permit_preset = clamp(Doors.permit_preset + Change, 0, Doors.permit_presets.size() - 1); + auto const doors{Doors.permit_presets[Doors.permit_preset]}; + auto const permitleft{((doors & 1) != 0)}; + auto const permitright{((doors & 2) != 0)}; - PermitDoors( ( CabActive > 0 ? side::left : side::right ), permitleft, Notify ); - PermitDoors( ( CabActive > 0 ? side::right : side::left ), permitright, Notify ); - } + PermitDoors((CabActive > 0 ? side::left : side::right), permitleft, Notify); + PermitDoors((CabActive > 0 ? side::right : side::left), permitright, Notify); + } - return ( Doors.permit_preset != initialstate ); + return (Doors.permit_preset != initialstate); } -bool TMoverParameters::PermitDoorStep( bool const State, range_t const Notify ) { +bool TMoverParameters::PermitDoorStep(bool const State, range_t const Notify) +{ - auto const initialstate { Doors.step_enabled }; + auto const initialstate{Doors.step_enabled}; - Doors.step_enabled = State; - if( Notify != range_t::local ) { - // wysłanie wyłączenia do pozostałych? - SendCtrlToNext( - "DoorStep", - ( State == true ? - 1 : - 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + Doors.step_enabled = State; + if (Notify != range_t::local) + { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext("DoorStep", (State == true ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( Doors.step_enabled != initialstate ); + return (Doors.step_enabled != initialstate); } -bool TMoverParameters::PermitDoors( side const Door, bool const State, range_t const Notify ) { +bool TMoverParameters::PermitDoors(side const Door, bool const State, range_t const Notify) +{ - bool const initialstate { Doors.instances[Door].open_permit }; + bool const initialstate{Doors.instances[Door].open_permit}; - PermitDoors_( Door, State ); + PermitDoors_(Door, State); - if( Notify != range_t::local ) { + if (Notify != range_t::local) + { - SendCtrlToNext( - "DoorPermit", - ( State ? 1 : -1 ) // positive: grant, negative: revoke - * ( Door == ( CabActive > 0 ? side::left : side::right ) ? // 1=lewe, 2=prawe (swap if reversed) - 1 : - 2 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + SendCtrlToNext("DoorPermit", + (State ? 1 : -1) // positive: grant, negative: revoke + * (Door == (CabActive > 0 ? side::left : side::right) ? // 1=lewe, 2=prawe (swap if reversed) + 1 : + 2), + CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( Doors.instances[ Door ].open_permit != initialstate ); + return (Doors.instances[Door].open_permit != initialstate); } -void TMoverParameters::PermitDoors_( side const Door, bool const State ) { +void TMoverParameters::PermitDoors_(side const Door, bool const State) +{ - if( ( State ) && ( State != Doors.instances[ Door ].open_permit ) ) { - SetFlag( SoundFlag, sound::doorpermit ); - } - Doors.instances[ Door ].open_permit = State; + if ((State) && (State != Doors.instances[Door].open_permit)) + { + SetFlag(SoundFlag, sound::doorpermit); + } + Doors.instances[Door].open_permit = State; } -bool TMoverParameters::ChangeDoorControlMode( bool const State, range_t const Notify ) { +bool TMoverParameters::ChangeDoorControlMode(bool const State, range_t const Notify) +{ - auto const initialstate { Doors.remote_only }; + auto const initialstate{Doors.remote_only}; - Doors.remote_only = State; - if( Notify != range_t::local ) { - // wysłanie wyłączenia do pozostałych? - SendCtrlToNext( - "DoorMode", - ( State == true ? - 1 : - 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + Doors.remote_only = State; + if (Notify != range_t::local) + { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext("DoorMode", (State == true ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - if( true == State ) { - // when door are put in remote control mode they're automatically open - // TBD, TODO: make it dependant on config switch? - OperateDoors( side::left, true ); - OperateDoors( side::right, true ); - } + if (true == State) + { + // when door are put in remote control mode they're automatically open + // TBD, TODO: make it dependant on config switch? + OperateDoors(side::left, true); + OperateDoors(side::right, true); + } - return ( Doors.remote_only != initialstate ); + return (Doors.remote_only != initialstate); } -bool TMoverParameters::OperateDoors( side const Door, bool const State, range_t const Notify ) { +bool TMoverParameters::OperateDoors(side const Door, bool const State, range_t const Notify) +{ - auto &door { Doors.instances[ Door ] }; -/* - if( ( State == true ? door.is_open : door.is_closed ) ) { - // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? - // (for the time being no, methods are often invoked blindly which would lead to commands spam) - return false; - } -*/ - bool result { false }; + auto &door{Doors.instances[Door]}; + /* + if( ( State == true ? door.is_open : door.is_closed ) ) { + // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? + // (for the time being no, methods are often invoked blindly which would lead to commands spam) + return false; + } + */ + bool result{false}; - if( Notify == range_t::local ) { - door.local_open = State; - door.local_close = ( false == State ); - result = true; - } - else { - // remote door operation signals require power to propagate - if( ( Power24vIsAvailable || Power110vIsAvailable ) ) { - door.remote_open = State; - door.remote_close = ( false == State ); - result = true; - } - } + if (Notify == range_t::local) + { + door.local_open = State; + door.local_close = (false == State); + result = true; + } + else + { + // remote door operation signals require power to propagate + if ((Power24vIsAvailable || Power110vIsAvailable)) + { + door.remote_open = State; + door.remote_close = (false == State); + result = true; + } + } - if( Notify != range_t::local ) { + if (Notify != range_t::local) + { - SendCtrlToNext( - ( State == true ? - "DoorOpen" : - "DoorClose" ), - ( Door == ( CabActive > 0 ? side::left : side::right ) ? // 1=lewe, 2=prawe (swap if reversed) - 1 : - 2 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + SendCtrlToNext((State == true ? "DoorOpen" : "DoorClose"), + (Door == (CabActive > 0 ? side::left : side::right) ? // 1=lewe, 2=prawe (swap if reversed) + 1 : + 2), + CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return result; + return result; } // toggle door lock -bool TMoverParameters::LockDoors( bool const State, range_t const Notify ) { +bool TMoverParameters::LockDoors(bool const State, range_t const Notify) +{ - auto const initialstate { Doors.lock_enabled }; + auto const initialstate{Doors.lock_enabled}; - Doors.lock_enabled = State; - if( Notify != range_t::local ) { - // wysłanie wyłączenia do pozostałych? - SendCtrlToNext( - "DoorLock", - ( State == true ? - 1 : - 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + Doors.lock_enabled = State; + if (Notify != range_t::local) + { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext("DoorLock", (State == true ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return ( Doors.lock_enabled != initialstate ); + return (Doors.lock_enabled != initialstate); } // toggles departure warning -bool -TMoverParameters::signal_departure( bool const State, range_t const Notify ) { +bool TMoverParameters::signal_departure(bool const State, range_t const Notify) +{ - if( DepartureSignal == State ) { - // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? - return false; - } + if (DepartureSignal == State) + { + // TBD: should the command be passed to other vehicles regardless of whether it affected the primary target? + return false; + } - DepartureSignal = State; - if( Notify != range_t::local ) { - // wysłanie wyłączenia do pozostałych? - SendCtrlToNext( - "DepartureSignal", - ( State == true ? - 1 : - 0 ), - CabActive, - ( Notify == range_t::unit ? - coupling::control | coupling::permanent : - coupling::control ) ); - } + DepartureSignal = State; + if (Notify != range_t::local) + { + // wysłanie wyłączenia do pozostałych? + SendCtrlToNext("DepartureSignal", (State == true ? 1 : 0), CabActive, (Notify == range_t::unit ? coupling::control | coupling::permanent : coupling::control)); + } - return true; + return true; } // automatic door controller update -void -TMoverParameters::update_doors( double const Deltatime ) { +void TMoverParameters::update_doors(double const Deltatime) +{ - if( Doors.range == 0.f ) { return; } // HACK: crude way to distinguish vehicles with actual doors + if (Doors.range == 0.f) + { + return; + } // HACK: crude way to distinguish vehicles with actual doors - // NBMX Obsluga drzwi, MC: zuniwersalnione - auto const localopencontrol { - ( false == Doors.remote_only ) - && ( ( Doors.open_control == control_t::passenger ) - || ( Doors.open_control == control_t::mixed ) ) }; - auto const remoteopencontrol { - ( Doors.open_control == control_t::driver ) - || ( Doors.open_control == control_t::conductor ) - || ( Doors.open_control == control_t::mixed ) }; - auto const localclosecontrol { - ( false == Doors.remote_only ) - && ( ( Doors.close_control == control_t::passenger ) - || ( Doors.close_control == control_t::mixed ) ) }; - auto const remoteclosecontrol { - ( Doors.close_control == control_t::driver ) - || ( Doors.close_control == control_t::conductor ) - || ( Doors.close_control == control_t::mixed ) }; + // NBMX Obsluga drzwi, MC: zuniwersalnione + auto const localopencontrol{(false == Doors.remote_only) && ((Doors.open_control == control_t::passenger) || (Doors.open_control == control_t::mixed))}; + auto const remoteopencontrol{(Doors.open_control == control_t::driver) || (Doors.open_control == control_t::conductor) || (Doors.open_control == control_t::mixed)}; + auto const localclosecontrol{(false == Doors.remote_only) && ((Doors.close_control == control_t::passenger) || (Doors.close_control == control_t::mixed))}; + auto const remoteclosecontrol{(Doors.close_control == control_t::driver) || (Doors.close_control == control_t::conductor) || (Doors.close_control == control_t::mixed)}; - Doors.is_locked = - ( true == Doors.has_lock ) - && ( true == Doors.lock_enabled ) && (Vel >= Doors.doorLockSpeed); + Doors.is_locked = (true == Doors.has_lock) && (true == Doors.lock_enabled) && (Vel >= Doors.doorLockSpeed); - for( auto &door : Doors.instances ) { - // revoke permit if... - door.open_permit = - ( true == door.open_permit ) // ...we already have one... - && ( ( false == Doors.permit_presets.empty() ) // ...there's no preset switch controlling permit state... - || ( ( false == Doors.is_locked ) // ...and the door lock is engaged... - && ( false == door.remote_close ) ) );// ...or the door is about to be closed + for (auto &door : Doors.instances) + { + // revoke permit if... + door.open_permit = (true == door.open_permit) // ...we already have one... + && ((false == Doors.permit_presets.empty()) // ...there's no preset switch controlling permit state... + || ((false == Doors.is_locked) // ...and the door lock is engaged... + && (false == door.remote_close))); // ...or the door is about to be closed - door.is_open = - ( door.position >= Doors.range ) - && ( ( false == Doors.step_enabled ) - || ( door.step_position >= ( Doors.step_range != 0.f ? 1.f : 0.f ) ) ); - door.is_closed = - ( door.position <= 0.f ) - && ( door.step_position <= 0.f ); + door.is_open = (door.position >= Doors.range) && ((false == Doors.step_enabled) || (door.step_position >= (Doors.step_range != 0.f ? 1.f : 0.f))); + door.is_closed = (door.position <= 0.f) && (door.step_position <= 0.f); door.is_door_closed = (door.position <= 0.f); - door.local_open = door.local_open && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); - door.remote_open = ( door.remote_open || Doors.remote_only ) && ( false == door.is_open ) && ( ( false == Doors.permit_needed ) || door.open_permit ); - door.local_close = door.local_close && ( false == door.is_closed ) && ( ( false == remoteopencontrol ) || ( false == door.remote_open ) ); - door.remote_close = door.remote_close && ( false == door.is_closed ) && ( ( false == localopencontrol ) || ( false == door.local_open ) ); + door.local_open = door.local_open && (false == door.is_open) && ((false == Doors.permit_needed) || door.open_permit); + door.remote_open = (door.remote_open || Doors.remote_only) && (false == door.is_open) && ((false == Doors.permit_needed) || door.open_permit); + door.local_close = door.local_close && (false == door.is_closed) && ((false == remoteopencontrol) || (false == door.remote_open)); + door.remote_close = door.remote_close && (false == door.is_closed) && ((false == localopencontrol) || (false == door.local_open)); - auto const autoopenrequest { - ( Doors.open_control == control_t::autonomous ) - && ( ( false == Doors.permit_needed ) || door.open_permit ) }; - auto const openrequest { - ( localopencontrol && door.local_open ) - || ( remoteopencontrol && door.remote_open ) - || ( autoopenrequest && ( false == door.is_open ) ) }; + auto const autoopenrequest{(Doors.open_control == control_t::autonomous) && ((false == Doors.permit_needed) || door.open_permit)}; + auto const openrequest{(localopencontrol && door.local_open) || (remoteopencontrol && door.remote_open) || (autoopenrequest && (false == door.is_open))}; - auto const autocloserequest { - ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) ) - || ( ( door.auto_timer != -1.f ) && ( door.auto_timer <= 0.f ) ) - || ( ( Doors.permit_needed ) && ( false == door.open_permit ) ) }; - auto const closerequest { - ( door.remote_close && remoteclosecontrol ) - || ( door.local_close && localclosecontrol ) - || ( autocloserequest && door.is_open ) }; + auto const autocloserequest{((Doors.auto_velocity != -1.f) && (Vel > Doors.auto_velocity)) || ((door.auto_timer != -1.f) && (door.auto_timer <= 0.f)) || + ((Doors.permit_needed) && (false == door.open_permit))}; + auto const closerequest{(door.remote_close && remoteclosecontrol) || (door.local_close && localclosecontrol) || (autocloserequest && door.is_open)}; - auto const ispowered { ( - Doors.voltage == 0 ? true : - Doors.voltage == 24 ? ( Power24vIsAvailable || Power110vIsAvailable ) : - Doors.voltage == 110 ? Power110vIsAvailable : - false ) }; + auto const ispowered{(Doors.voltage == 0 ? true : Doors.voltage == 24 ? (Power24vIsAvailable || Power110vIsAvailable) : Doors.voltage == 110 ? Power110vIsAvailable : false)}; - door.is_opening = - ( false == door.is_open ) - && ( true == ispowered ) - && ( false == closerequest ) - && ( ( true == door.is_opening ) - || ( ( true == openrequest ) - && ( false == Doors.is_locked ) ) ); - door.is_closing = - ( false == door.is_closed ) - && ( true == ispowered ) - && ( false == openrequest ) - && ( door.is_closing || closerequest ); - door.step_unfolding = ( - ( Doors.step_range != 0.f ) - && ( Doors.step_enabled ) - && ( false == Doors.is_locked ) - && ( door.step_position < 1.f ) - && ( door.is_opening ) ); - door.step_folding = ( - ( door.step_position > 0.f ) // is unfolded - && ( ( false == Doors.step_enabled ) // we lost permission to stay open or our door is calling the shots - || ( Doors.permit_needed ? - ( false == door.open_permit ) : - door.is_closing ) ) - && ( ( door.close_delay > Doors.close_delay ) || door.position <= 0.f ) ); // door is about to close, or already done + door.is_opening = (false == door.is_open) && (true == ispowered) && (false == closerequest) && ((true == door.is_opening) || ((true == openrequest) && (false == Doors.is_locked))); + door.is_closing = (false == door.is_closed) && (true == ispowered) && (false == openrequest) && (door.is_closing || closerequest); + door.step_unfolding = ((Doors.step_range != 0.f) && (Doors.step_enabled) && (false == Doors.is_locked) && (door.step_position < 1.f) && (door.is_opening)); + door.step_folding = ((door.step_position > 0.f) // is unfolded + && ((false == Doors.step_enabled) // we lost permission to stay open or our door is calling the shots + || (Doors.permit_needed ? (false == door.open_permit) : door.is_closing)) && + ((door.close_delay > Doors.close_delay) || door.position <= 0.f)); // door is about to close, or already done - if( true == door.is_opening ) { - door.auto_timer = ( - ( localopencontrol && door.local_open ) ? Doors.auto_duration : - ( remoteopencontrol && door.remote_open && Doors.auto_include_remote ) ? Doors.auto_duration : - -1.f ); - } - // doors - if( true == door.is_opening ) { - // open door - if( ( false == door.step_unfolding ) // no wait if no doorstep - || ( Doors.step_type == 2 ) ) { // no wait for rotating doorstep - door.open_delay += Deltatime; - if( door.open_delay > Doors.open_delay ) { - door.position = std::min( - Doors.range, - door.position + Doors.open_rate * Deltatime ); - } - } - door.close_delay = 0.f; - } - if( true == door.is_closing ) { - // close door - door.close_delay += Deltatime; - if( door.close_delay > Doors.close_delay ) { - door.position = std::max( - 0.f, - door.position - Doors.close_rate * Deltatime ); - } - door.open_delay = 0.f; - } - // doorsteps - if( door.step_unfolding ) { - // unfold left doorstep - door.step_position = std::min( - 1.f, - door.step_position + Doors.step_rate * Deltatime ); - } - if( door.step_folding ) { - // fold left doorstep - if( ( TrainType == dt_EZT ) - || ( TrainType == dt_DMU ) ) { - // multi-unit vehicles typically fold the doorstep only after closing the door - if( door.position <= 0.f ) { - door.step_position = std::max( - 0.f, - door.step_position - Doors.step_rate * Deltatime ); - } - } - else { - door.step_position = std::max( - 0.f, - door.step_position - Doors.step_rate * Deltatime ); - } - } - } + if (true == door.is_opening) + { + door.auto_timer = ((localopencontrol && door.local_open) ? Doors.auto_duration : (remoteopencontrol && door.remote_open && Doors.auto_include_remote) ? Doors.auto_duration : -1.f); + } + // doors + if (true == door.is_opening) + { + // open door + if ((false == door.step_unfolding) // no wait if no doorstep + || (Doors.step_type == 2)) + { // no wait for rotating doorstep + door.open_delay += Deltatime; + if (door.open_delay > Doors.open_delay) + { + door.position = std::min(Doors.range, door.position + Doors.open_rate * Deltatime); + } + } + door.close_delay = 0.f; + } + if (true == door.is_closing) + { + // close door + door.close_delay += Deltatime; + if (door.close_delay > Doors.close_delay) + { + door.position = std::max(0.f, door.position - Doors.close_rate * Deltatime); + } + door.open_delay = 0.f; + } + // doorsteps + if (door.step_unfolding) + { + // unfold left doorstep + door.step_position = std::min(1.f, door.step_position + Doors.step_rate * Deltatime); + } + if (door.step_folding) + { + // fold left doorstep + if ((TrainType == dt_EZT) || (TrainType == dt_DMU)) + { + // multi-unit vehicles typically fold the doorstep only after closing the door + if (door.position <= 0.f) + { + door.step_position = std::max(0.f, door.step_position - Doors.step_rate * Deltatime); + } + } + else + { + door.step_position = std::max(0.f, door.step_position - Doors.step_rate * Deltatime); + } + } + } - if( ( false == Doors.instances[side::right].is_open ) - && ( false == Doors.instances[side::left].is_open ) ) { return; } + if ((false == Doors.instances[side::right].is_open) && (false == Doors.instances[side::left].is_open)) + { + return; + } - if( Doors.auto_duration > 0.f ) { - // update door timers if the door close after defined time - for( auto &door : Doors.instances ) { + if (Doors.auto_duration > 0.f) + { + // update door timers if the door close after defined time + for (auto &door : Doors.instances) + { - if( false == door.is_open ) { continue; } + if (false == door.is_open) + { + continue; + } - if( door.auto_timer > 0.f ) { - door.auto_timer -= Deltatime; - } - // if there's load exchange in progress, reset the timer(s) for already open doors - if( ( door.auto_timer != -1.f ) - && ( ( LoadStatus & ( 2 | 1 ) ) != 0 ) ) { - door.auto_timer = Doors.auto_duration; - } - } - } -/* - // the door are closed if their timer goes below 0, or if the vehicle is moving faster than defined threshold - std::array const doorids { side::right, side::left }; - for( auto const doorid : doorids ) { - auto const &door { Doors.instances[ doorid ] }; - if( true == door.is_open ) { - if( ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) ) - || ( ( door.auto_timer != -1.f ) && ( door.auto_timer <= 0.f ) ) ) { - // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) - OperateDoors( doorid, false, range_t::local ); - } - } - } -*/ + if (door.auto_timer > 0.f) + { + door.auto_timer -= Deltatime; + } + // if there's load exchange in progress, reset the timer(s) for already open doors + if ((door.auto_timer != -1.f) && ((LoadStatus & (2 | 1)) != 0)) + { + door.auto_timer = Doors.auto_duration; + } + } + } + /* + // the door are closed if their timer goes below 0, or if the vehicle is moving faster than defined threshold + std::array const doorids { side::right, side::left }; + for( auto const doorid : doorids ) { + auto const &door { Doors.instances[ doorid ] }; + if( true == door.is_open ) { + if( ( ( Doors.auto_velocity != -1.f ) && ( Vel > Doors.auto_velocity ) ) + || ( ( door.auto_timer != -1.f ) && ( door.auto_timer <= 0.f ) ) ) { + // close the door and set the timer to expired state (closing may happen sooner if vehicle starts moving) + OperateDoors( doorid, false, range_t::local ); + } + } + } + */ } // ************************************************************************************************* @@ -8777,21 +8763,20 @@ TMoverParameters::update_doors( double const Deltatime ) { // ************************************************************************************************* bool TMoverParameters::ChangeOffsetH(double DeltaOffset) { - bool COH = false; - if (TestFlag(CategoryFlag, 2) && TestFlag(RunningTrack.CategoryFlag, 2)) - { - OffsetTrackH = OffsetTrackH + DeltaOffset; - // if (abs(OffsetTrackH) > (RunningTrack.Width / 1.95 - TrackW / 2.0)) - if (abs(OffsetTrackH) > - (0.5 * (RunningTrack.Width - Dim.W) - 0.05)) // Ra: może pół pojazdu od brzegu? - COH = false; // kola na granicy drogi - else - COH = true; - } - else - COH = false; + bool COH = false; + if (TestFlag(CategoryFlag, 2) && TestFlag(RunningTrack.CategoryFlag, 2)) + { + OffsetTrackH = OffsetTrackH + DeltaOffset; + // if (abs(OffsetTrackH) > (RunningTrack.Width / 1.95 - TrackW / 2.0)) + if (abs(OffsetTrackH) > (0.5 * (RunningTrack.Width - Dim.W) - 0.05)) // Ra: może pół pojazdu od brzegu? + COH = false; // kola na granicy drogi + else + COH = true; + } + else + COH = false; - return COH; + return COH; } // ************************************************************************************************* @@ -8800,99 +8785,106 @@ bool TMoverParameters::ChangeOffsetH(double DeltaOffset) // ************************************************************************************************* std::string TMoverParameters::EngineDescription(int what) const { - std::string outstr { "OK" }; - switch (what) { - case 0: { - if( DamageFlag == 255 ) { - outstr = "WRECKED"; - } - else { - if( TestFlag( DamageFlag, dtrain_thinwheel ) ) { - if( Power > 0.1 ) - outstr = "Thin wheel"; - else - outstr = "Load shifted"; - } - if( ( WheelFlat > 5.0 ) - || ( TestFlag( DamageFlag, dtrain_wheelwear ) ) ) { - outstr = "Wheel wear"; - } - if( TestFlag( DamageFlag, dtrain_bearing ) ) { - outstr = "Bearing damaged"; - } - if( TestFlag( DamageFlag, dtrain_coupling ) ) { - outstr = "Coupler broken"; - } - if( TestFlag( DamageFlag, dtrain_loaddamage ) ) { - if( Power > 0.1 ) - outstr = "Ventilator damaged"; - else - outstr = "Load damaged"; - } - if( TestFlag( DamageFlag, dtrain_loaddestroyed ) ) { - if( Power > 0.1 ) - outstr = "Engine damaged"; - else - outstr = "LOAD DESTROYED"; - } - if( TestFlag( DamageFlag, dtrain_axle ) ) { - outstr = "Axle broken"; - } - if( TestFlag( DamageFlag, dtrain_out ) ) { - outstr = "DERAILED"; - } - } - break; - } - default: { - outstr = "Invalid qualifier"; - break; - } - } - return outstr; + std::string outstr{"OK"}; + switch (what) + { + case 0: + { + if (DamageFlag == 255) + { + outstr = "WRECKED"; + } + else + { + if (TestFlag(DamageFlag, dtrain_thinwheel)) + { + if (Power > 0.1) + outstr = "Thin wheel"; + else + outstr = "Load shifted"; + } + if ((WheelFlat > 5.0) || (TestFlag(DamageFlag, dtrain_wheelwear))) + { + outstr = "Wheel wear"; + } + if (TestFlag(DamageFlag, dtrain_bearing)) + { + outstr = "Bearing damaged"; + } + if (TestFlag(DamageFlag, dtrain_coupling)) + { + outstr = "Coupler broken"; + } + if (TestFlag(DamageFlag, dtrain_loaddamage)) + { + if (Power > 0.1) + outstr = "Ventilator damaged"; + else + outstr = "Load damaged"; + } + if (TestFlag(DamageFlag, dtrain_loaddestroyed)) + { + if (Power > 0.1) + outstr = "Engine damaged"; + else + outstr = "LOAD DESTROYED"; + } + if (TestFlag(DamageFlag, dtrain_axle)) + { + outstr = "Axle broken"; + } + if (TestFlag(DamageFlag, dtrain_out)) + { + outstr = "DERAILED"; + } + } + break; + } + default: + { + outstr = "Invalid qualifier"; + break; + } + } + return outstr; } // ************************************************************************************************* // Q: 20160709 // Funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT // ************************************************************************************************* -double TMoverParameters::GetTrainsetVoltage( int const Coupling ) const -{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT - // TBD, TODO: call once per vehicle update, return cached results? - double voltages[] = { 0.0, 0.0 }; - for( int end = end::front; end <= end::rear; ++end ) { - if( Couplers[ end ].Connected == nullptr ) { - continue; - } - auto const &coupler { Couplers[ end ] }; - auto const fullcoupling { - coupler.CouplingFlag - | ( TestFlag( coupler.CouplingFlag, coupler.PowerCoupling ) ? - coupler.PowerFlag : - 0 ) }; - if( ( fullcoupling & Coupling ) == 0 ) { - continue; - } - auto *connectedpowercoupling = ( - ( Coupling & ( coupling::highvoltage | coupling::heating ) ) != 0 ? &coupler.Connected->Couplers[ coupler.ConnectedNr ].power_high : - ( Coupling & coupling::power110v ) != 0 ? &coupler.Connected->Couplers[ coupler.ConnectedNr ].power_110v : - ( Coupling & coupling::power24v ) != 0 ? &coupler.Connected->Couplers[ coupler.ConnectedNr ].power_24v : - nullptr ); - if( ( connectedpowercoupling != nullptr ) - && ( connectedpowercoupling->is_live ) ) { - voltages[ end ] = connectedpowercoupling->voltage; - } - } - return std::max( voltages[ end::front ], voltages[ end::rear ] ); +double TMoverParameters::GetTrainsetVoltage(int const Coupling) const +{ // ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT + // TBD, TODO: call once per vehicle update, return cached results? + double voltages[] = {0.0, 0.0}; + for (int end = end::front; end <= end::rear; ++end) + { + if (Couplers[end].Connected == nullptr) + { + continue; + } + auto const &coupler{Couplers[end]}; + auto const fullcoupling{coupler.CouplingFlag | (TestFlag(coupler.CouplingFlag, coupler.PowerCoupling) ? coupler.PowerFlag : 0)}; + if ((fullcoupling & Coupling) == 0) + { + continue; + } + auto *connectedpowercoupling = ((Coupling & (coupling::highvoltage | coupling::heating)) != 0 ? &coupler.Connected->Couplers[coupler.ConnectedNr].power_high : + (Coupling & coupling::power110v) != 0 ? &coupler.Connected->Couplers[coupler.ConnectedNr].power_110v : + (Coupling & coupling::power24v) != 0 ? &coupler.Connected->Couplers[coupler.ConnectedNr].power_24v : + nullptr); + if ((connectedpowercoupling != nullptr) && (connectedpowercoupling->is_live)) + { + voltages[end] = connectedpowercoupling->voltage; + } + } + return std::max(voltages[end::front], voltages[end::rear]); } -double TMoverParameters::GetTrainsetHighVoltage() const { +double TMoverParameters::GetTrainsetHighVoltage() const +{ - return std::max( - GetTrainsetVoltage( coupling::highvoltage ), - ( HeatingAllow ? - GetTrainsetVoltage( coupling::heating ) : - 0.0 ) ); + return std::max(GetTrainsetVoltage(coupling::highvoltage), (HeatingAllow ? GetTrainsetVoltage(coupling::heating) : 0.0)); } // ************************************************************************************************* @@ -8900,14 +8892,18 @@ double TMoverParameters::GetTrainsetHighVoltage() const { // ************************************************************************************************* bool TMoverParameters::switch_physics(bool const State) // DO PRZETLUMACZENIA NA KONCU { - if( PhysicActivation == State ) { return false; } + if (PhysicActivation == State) + { + return false; + } - PhysicActivation = State; - if( true == State ) { - LastSwitchingTime = 0; - } + PhysicActivation = State; + if (true == State) + { + LastSwitchingTime = 0; + } - return true; + return true; } // ************************************************************************************************* @@ -8922,9 +8918,10 @@ bool startLIGHTSLIST; bool startCOMPRESSORLIST; int LISTLINE; -bool issection( std::string const &Name, std::string const &Input ) { +bool issection(std::string const &Name, std::string const &Input) +{ - return ( Input.compare( 0, Name.size(), Name ) == 0 ); + return (Input.compare(0, Name.size(), Name) == 0); } int s2NPW(std::string s) @@ -8955,225 +8952,238 @@ int s2NNW(std::string s) // Q: 20160717 // ************************************************************************************************* // parsowanie Motor Param Table -bool TMoverParameters::readMPT0( std::string const &line ) { - - // TBD, TODO: split into separate functions similar to readMPT if more varied schemes appear? - cParser parser( line ); - if( false == parser.getTokens( 7, false ) ) { - WriteLog( "Read MPT0: arguments missing in line " + std::to_string( LISTLINE ) ); - return false; - } - int idx = 0; // numer pozycji - parser >> idx; - switch( EngineType ) { - case TEngineType::DieselEngine: { - parser - >> MotorParam[ idx ].mIsat - >> MotorParam[ idx ].fi0 - >> MotorParam[ idx ].fi - >> MotorParam[ idx ].mfi0 - >> MotorParam[ idx ].mfi - >> MotorParam[ idx ].Isat; - break; - } - default: { - parser - >> MotorParam[ idx ].mfi - >> MotorParam[ idx ].mIsat - >> MotorParam[ idx ].mfi0 - >> MotorParam[ idx ].fi - >> MotorParam[ idx ].Isat - >> MotorParam[ idx ].fi0; - break; - } - } - if( true == parser.getTokens( 1, false ) ) { - int autoswitch; - parser >> autoswitch; - MotorParam[ idx ].AutoSwitch = ( autoswitch == 1 ); - } - else { - MotorParam[ idx ].AutoSwitch = false; - } - return true; -} - -bool TMoverParameters::readMPT( std::string const &line ) { - - ++LISTLINE; - - switch( EngineType ) { - - case TEngineType::ElectricSeriesMotor: { return readMPTElectricSeries( line ); } - case TEngineType::DieselElectric: { return readMPTDieselElectric( line ); } - case TEngineType::DieselEngine: { return readMPTDieselEngine( line ); } - default: { return false; } - } -} - -bool TMoverParameters::readMPTElectricSeries(std::string const &line) { - - cParser parser( line ); - if( false == parser.getTokens( 5, false ) ) { - WriteLog( "Read MPT: arguments missing in line " + std::to_string( LISTLINE ) ); - return false; - } - int idx = 0; // numer pozycji - parser >> idx; - parser - >> MotorParam[ idx ].mfi - >> MotorParam[ idx ].mIsat - >> MotorParam[ idx ].fi - >> MotorParam[ idx ].Isat; - if( true == parser.getTokens( 1, false ) ) { - int autoswitch; - parser >> autoswitch; - MotorParam[ idx ].AutoSwitch = (autoswitch == 1); } - else{ - MotorParam[ idx ].AutoSwitch = false; - } - return true; -} - -bool TMoverParameters::readMPTDieselElectric( std::string const &line ) { - - cParser parser( line ); - if( false == parser.getTokens( 7, false ) ) { - WriteLog( "Read MPT: arguments missing in line " + std::to_string( LISTLINE ) ); - return false; - } - int idx = 0; // numer pozycji - parser >> idx; - parser - >> MotorParam[ idx ].mfi - >> MotorParam[ idx ].mIsat - >> MotorParam[ idx ].fi - >> MotorParam[ idx ].Isat - >> MPTRelay[ idx ].Iup - >> MPTRelay[ idx ].Idown; - - return true; -} - -bool TMoverParameters::readMPTDieselEngine( std::string const &line ) { - - cParser parser( line ); - if( false == parser.getTokens( 4, false ) ) { - WriteLog( "Read MPT: arguments missing in line " + std::to_string( LISTLINE ) ); - return false; - } - int idx = 0; // numer pozycji - parser >> idx; - parser - >> MotorParam[ idx ].mIsat - >> MotorParam[ idx ].fi - >> MotorParam[ idx ].mfi; - if( true == parser.getTokens( 1, false ) ) { - int autoswitch; - parser >> autoswitch; - MotorParam[ idx ].AutoSwitch = ( autoswitch == 1 ); - } - else { - MotorParam[ idx ].AutoSwitch = false; - } - return true; -} - -bool TMoverParameters::readBPT( std::string const &line ) { - - cParser parser( line ); - if( false == parser.getTokens( 5, false ) ) { - - WriteLog( "Read BPT: arguments missing in line " + std::to_string( LISTLINE + 1 ) ); - return false; - } - ++LISTLINE; - std::string braketype; int idx = 0; - parser >> idx; - parser - >> BrakePressureTable[ idx ].PipePressureVal - >> BrakePressureTable[ idx ].BrakePressureVal - >> BrakePressureTable[ idx ].FlowSpeedVal - >> braketype; - if( braketype == "Pneumatic" ) { BrakePressureTable[ idx ].BrakeType = TBrakeSystem::Pneumatic; } - else if( braketype == "ElectroPneumatic" ) { BrakePressureTable[ idx ].BrakeType = TBrakeSystem::ElectroPneumatic; } - else { BrakePressureTable[ idx ].BrakeType = TBrakeSystem::Individual; } - - return true; -} - -bool TMoverParameters::readRList( std::string const &Input ) { - - cParser parser( Input ); - if( false == parser.getTokens( 5, false ) ) { - - WriteLog( "Read RList: arguments missing in line " + std::to_string( LISTLINE + 1 ) ); - return false; - } - auto idx = LISTLINE++; - if( idx >= sizeof( RList ) / sizeof( TScheme ) ) { - WriteLog( "Read RList: number of entries exceeded capacity of the data table" ); - return false; - } - parser - >> RList[ idx ].Relay - >> RList[ idx ].R - >> RList[ idx ].Bn - >> RList[ idx ].Mn - >> RList[ idx ].AutoSwitch; - - if( true == parser.getTokens( 1, false ) ) { parser >> RList[ idx ].ScndAct; } - else { RList[ idx ].ScndAct = 0; } - - return true; -} - -bool TMoverParameters::readUCList(std::string const &line) { +bool TMoverParameters::readMPT0(std::string const &line) +{ + // TBD, TODO: split into separate functions similar to readMPT if more varied schemes appear? cParser parser(line); - parser.getTokens(10, false); - auto idx = LISTLINE++; - if (idx >= sizeof(UniCtrlList) / sizeof(TUniversalCtrl)) { - WriteLog("Read UCList: number of entries exceeded capacity of the data table"); + if (false == parser.getTokens(7, false)) + { + WriteLog("Read MPT0: arguments missing in line " + std::to_string(LISTLINE)); return false; } - int i = 0; - parser - >> i - >> UniCtrlList[idx].mode - >> UniCtrlList[idx].MinCtrlVal - >> UniCtrlList[idx].MaxCtrlVal - >> UniCtrlList[idx].SetCtrlVal - >> UniCtrlList[idx].SpeedUp - >> UniCtrlList[idx].SpeedDown - >> UniCtrlList[idx].ReturnPosition - >> UniCtrlList[idx].NextPosFastInc - >> UniCtrlList[idx].PrevPosFastDec; + int idx = 0; // numer pozycji + parser >> idx; + switch (EngineType) + { + case TEngineType::DieselEngine: + { + parser >> MotorParam[idx].mIsat >> MotorParam[idx].fi0 >> MotorParam[idx].fi >> MotorParam[idx].mfi0 >> MotorParam[idx].mfi >> MotorParam[idx].Isat; + break; + } + default: + { + parser >> MotorParam[idx].mfi >> MotorParam[idx].mIsat >> MotorParam[idx].mfi0 >> MotorParam[idx].fi >> MotorParam[idx].Isat >> MotorParam[idx].fi0; + break; + } + } + if (true == parser.getTokens(1, false)) + { + int autoswitch; + parser >> autoswitch; + MotorParam[idx].AutoSwitch = (autoswitch == 1); + } + else + { + MotorParam[idx].AutoSwitch = false; + } + return true; +} + +bool TMoverParameters::readMPT(std::string const &line) +{ + + ++LISTLINE; + + switch (EngineType) + { + + case TEngineType::ElectricSeriesMotor: + { + return readMPTElectricSeries(line); + } + case TEngineType::DieselElectric: + { + return readMPTDieselElectric(line); + } + case TEngineType::DieselEngine: + { + return readMPTDieselEngine(line); + } + default: + { + return false; + } + } +} + +bool TMoverParameters::readMPTElectricSeries(std::string const &line) +{ + + cParser parser(line); + if (false == parser.getTokens(5, false)) + { + WriteLog("Read MPT: arguments missing in line " + std::to_string(LISTLINE)); + return false; + } + int idx = 0; // numer pozycji + parser >> idx; + parser >> MotorParam[idx].mfi >> MotorParam[idx].mIsat >> MotorParam[idx].fi >> MotorParam[idx].Isat; + if (true == parser.getTokens(1, false)) + { + int autoswitch; + parser >> autoswitch; + MotorParam[idx].AutoSwitch = (autoswitch == 1); + } + else + { + MotorParam[idx].AutoSwitch = false; + } + return true; +} + +bool TMoverParameters::readMPTDieselElectric(std::string const &line) +{ + + cParser parser(line); + if (false == parser.getTokens(7, false)) + { + WriteLog("Read MPT: arguments missing in line " + std::to_string(LISTLINE)); + return false; + } + int idx = 0; // numer pozycji + parser >> idx; + parser >> MotorParam[idx].mfi >> MotorParam[idx].mIsat >> MotorParam[idx].fi >> MotorParam[idx].Isat >> MPTRelay[idx].Iup >> MPTRelay[idx].Idown; return true; } -bool TMoverParameters::readDList( std::string const &line ) { - - cParser parser( line ); - parser.getTokens( 3, false ); - auto idx = LISTLINE++; - if( idx >= sizeof( RList ) / sizeof( TScheme ) ) { - WriteLog( "Read DList: number of entries exceeded capacity of the data table" ); - return false; - } - parser - >> RList[ idx ].Relay - >> RList[ idx ].R - >> RList[ idx ].Mn; - - return true; -} - -bool TMoverParameters::readDMList(std::string const &line) { +bool TMoverParameters::readMPTDieselEngine(std::string const &line) +{ cParser parser(line); - if (false == parser.getTokens(2, false)) { + if (false == parser.getTokens(4, false)) + { + WriteLog("Read MPT: arguments missing in line " + std::to_string(LISTLINE)); + return false; + } + int idx = 0; // numer pozycji + parser >> idx; + parser >> MotorParam[idx].mIsat >> MotorParam[idx].fi >> MotorParam[idx].mfi; + if (true == parser.getTokens(1, false)) + { + int autoswitch; + parser >> autoswitch; + MotorParam[idx].AutoSwitch = (autoswitch == 1); + } + else + { + MotorParam[idx].AutoSwitch = false; + } + return true; +} + +bool TMoverParameters::readBPT(std::string const &line) +{ + + cParser parser(line); + if (false == parser.getTokens(5, false)) + { + + WriteLog("Read BPT: arguments missing in line " + std::to_string(LISTLINE + 1)); + return false; + } + ++LISTLINE; + std::string braketype; + int idx = 0; + parser >> idx; + parser >> BrakePressureTable[idx].PipePressureVal >> BrakePressureTable[idx].BrakePressureVal >> BrakePressureTable[idx].FlowSpeedVal >> braketype; + if (braketype == "Pneumatic") + { + BrakePressureTable[idx].BrakeType = TBrakeSystem::Pneumatic; + } + else if (braketype == "ElectroPneumatic") + { + BrakePressureTable[idx].BrakeType = TBrakeSystem::ElectroPneumatic; + } + else + { + BrakePressureTable[idx].BrakeType = TBrakeSystem::Individual; + } + + return true; +} + +bool TMoverParameters::readRList(std::string const &Input) +{ + + cParser parser(Input); + if (false == parser.getTokens(5, false)) + { + + WriteLog("Read RList: arguments missing in line " + std::to_string(LISTLINE + 1)); + return false; + } + auto idx = LISTLINE++; + if (idx >= sizeof(RList) / sizeof(TScheme)) + { + WriteLog("Read RList: number of entries exceeded capacity of the data table"); + return false; + } + parser >> RList[idx].Relay >> RList[idx].R >> RList[idx].Bn >> RList[idx].Mn >> RList[idx].AutoSwitch; + + if (true == parser.getTokens(1, false)) + { + parser >> RList[idx].ScndAct; + } + else + { + RList[idx].ScndAct = 0; + } + + return true; +} + +bool TMoverParameters::readUCList(std::string const &line) +{ + + cParser parser(line); + parser.getTokens(10, false); + auto idx = LISTLINE++; + if (idx >= sizeof(UniCtrlList) / sizeof(TUniversalCtrl)) + { + WriteLog("Read UCList: number of entries exceeded capacity of the data table"); + return false; + } + int i = 0; + parser >> i >> UniCtrlList[idx].mode >> UniCtrlList[idx].MinCtrlVal >> UniCtrlList[idx].MaxCtrlVal >> UniCtrlList[idx].SetCtrlVal >> UniCtrlList[idx].SpeedUp >> UniCtrlList[idx].SpeedDown >> + UniCtrlList[idx].ReturnPosition >> UniCtrlList[idx].NextPosFastInc >> UniCtrlList[idx].PrevPosFastDec; + + return true; +} + +bool TMoverParameters::readDList(std::string const &line) +{ + + cParser parser(line); + parser.getTokens(3, false); + auto idx = LISTLINE++; + if (idx >= sizeof(RList) / sizeof(TScheme)) + { + WriteLog("Read DList: number of entries exceeded capacity of the data table"); + return false; + } + parser >> RList[idx].Relay >> RList[idx].R >> RList[idx].Mn; + + return true; +} + +bool TMoverParameters::readDMList(std::string const &line) +{ + + cParser parser(line); + if (false == parser.getTokens(2, false)) + { WriteLog("Read DMList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; @@ -9181,19 +9191,19 @@ bool TMoverParameters::readDMList(std::string const &line) { auto idx = LISTLINE++; double x = 0.0; double y = 0.0; - parser - >> x - >> y; + parser >> x >> y; dizel_Momentum_Table.emplace(x / 60.0, y); return true; } -bool TMoverParameters::readV2NMAXList(std::string const &line) { +bool TMoverParameters::readV2NMAXList(std::string const &line) +{ cParser parser(line); - if (false == parser.getTokens(2, false)) { + if (false == parser.getTokens(2, false)) + { WriteLog("Read V2nmaxList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; @@ -9201,19 +9211,19 @@ bool TMoverParameters::readV2NMAXList(std::string const &line) { auto idx = LISTLINE++; double x = 0.0; double y = 0.0; - parser - >> x - >> y; + parser >> x >> y; dizel_vel2nmax_Table.emplace(x, y / 60.0); return true; } -bool TMoverParameters::readHTCList(std::string const &line) { +bool TMoverParameters::readHTCList(std::string const &line) +{ cParser parser(line); - if (false == parser.getTokens(2, false)) { + if (false == parser.getTokens(2, false)) + { WriteLog("Read HTCList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; @@ -9221,19 +9231,19 @@ bool TMoverParameters::readHTCList(std::string const &line) { auto idx = LISTLINE++; double x = 0.0; double y = 0.0; - parser - >> x - >> y; + parser >> x >> y; hydro_TC_Table.emplace(x, y); return true; } -bool TMoverParameters::readPmaxList(std::string const &line) { +bool TMoverParameters::readPmaxList(std::string const &line) +{ cParser parser(line); - if (false == parser.getTokens(2, false)) { + if (false == parser.getTokens(2, false)) + { WriteLog("Read PmaxList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; @@ -9241,55 +9251,55 @@ bool TMoverParameters::readPmaxList(std::string const &line) { auto idx = LISTLINE++; double x = 0.0; double y = 0.0; - parser - >> x - >> y; + parser >> x >> y; EIM_Pmax_Table.emplace(x, y); return true; } -bool TMoverParameters::readFFList( std::string const &line ) { +bool TMoverParameters::readFFList(std::string const &line) +{ - cParser parser( line ); - if( false == parser.getTokens( 2, false ) ) { - WriteLog( "Read FList: arguments missing in line " + std::to_string( LISTLINE + 1 ) ); + cParser parser(line); + if (false == parser.getTokens(2, false)) + { + WriteLog("Read FList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; } int idx = LISTLINE++; - if( idx >= sizeof( FFlist ) / sizeof( TFFScheme ) ) { - WriteLog( "Read FList: number of entries exceeded capacity of the data table" ); + if (idx >= sizeof(FFlist) / sizeof(TFFScheme)) + { + WriteLog("Read FList: number of entries exceeded capacity of the data table"); return false; } - parser - >> FFlist[ idx ].v - >> FFlist[ idx ].freq; + parser >> FFlist[idx].v >> FFlist[idx].freq; return true; } -bool TMoverParameters::readFFEDList( std::string const &line ) { +bool TMoverParameters::readFFEDList(std::string const &line) +{ - cParser parser( line ); - if( false == parser.getTokens( 2, false ) ) { - WriteLog( "Read FList: arguments missing in line " + std::to_string( LISTLINE + 1 ) ); + cParser parser(line); + if (false == parser.getTokens(2, false)) + { + WriteLog("Read FList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; } int idx = LISTLINE++; - if( idx >= sizeof( FFEDlist ) / sizeof( TFFScheme ) ) { - WriteLog( "Read FList: number of entries exceeded capacity of the data table" ); + if (idx >= sizeof(FFEDlist) / sizeof(TFFScheme)) + { + WriteLog("Read FList: number of entries exceeded capacity of the data table"); return false; } - parser - >> FFEDlist[ idx ].v - >> FFEDlist[ idx ].freq; + parser >> FFEDlist[idx].v >> FFEDlist[idx].freq; return true; } // parsowanie wiperList -bool TMoverParameters::readWiperList(std::string const& line) +bool TMoverParameters::readWiperList(std::string const &line) { cParser parser(line); if (false == parser.getTokens(4, false)) @@ -9307,7 +9317,7 @@ bool TMoverParameters::readWiperList(std::string const& line) return true; } -bool TMoverParameters::readDimmerList(std::string const& line) +bool TMoverParameters::readDimmerList(std::string const &line) { cParser parser(line); if (false == parser.getTokens(3, false)) @@ -9317,81 +9327,78 @@ bool TMoverParameters::readDimmerList(std::string const& line) } int idx = LISTLINE++; - dimPosition dps; + dimPosition dps; parser >> dps.isHighBeam >> dps.isDimmed >> dps.isOff; dimPositions.push_back(dps); return true; } // parsowanie WWList -bool TMoverParameters::readWWList( std::string const &line ) { +bool TMoverParameters::readWWList(std::string const &line) +{ - cParser parser( line ); - if( false == parser.getTokens( 4, false ) ) { - WriteLog( "Read WWList: arguments missing in line " + std::to_string( LISTLINE + 1 ) ); - return false; - } - int idx = LISTLINE++; - if( idx >= sizeof( DElist ) / sizeof( TDEScheme ) ) { - WriteLog( "Read WWList: number of entries exceeded capacity of the data table" ); - return false; - } - parser - >> DElist[ idx ].RPM - >> DElist[ idx ].GenPower - >> DElist[ idx ].Umax - >> DElist[ idx ].Imax; + cParser parser(line); + if (false == parser.getTokens(4, false)) + { + WriteLog("Read WWList: arguments missing in line " + std::to_string(LISTLINE + 1)); + return false; + } + int idx = LISTLINE++; + if (idx >= sizeof(DElist) / sizeof(TDEScheme)) + { + WriteLog("Read WWList: number of entries exceeded capacity of the data table"); + return false; + } + parser >> DElist[idx].RPM >> DElist[idx].GenPower >> DElist[idx].Umax >> DElist[idx].Imax; - if( true == parser.getTokens( 3, false ) ) { - // optional parameters for shunt mode - parser - >> SST[ idx ].Umin - >> SST[ idx ].Umax - >> SST[ idx ].Pmax; + if (true == parser.getTokens(3, false)) + { + // optional parameters for shunt mode + parser >> SST[idx].Umin >> SST[idx].Umax >> SST[idx].Pmax; - SST[ idx ].Pmin = std::sqrt( std::pow( SST[ idx ].Umin, 2 ) / 47.6 ); - SST[ idx ].Pmax = std::min( SST[ idx ].Pmax, std::pow( SST[ idx ].Umax, 2 ) / 47.6 ); - } - return true; + SST[idx].Pmin = std::sqrt(std::pow(SST[idx].Umin, 2) / 47.6); + SST[idx].Pmax = std::min(SST[idx].Pmax, std::pow(SST[idx].Umax, 2) / 47.6); + } + return true; } -bool TMoverParameters::readLightsList( std::string const &Input ) { - - cParser parser( Input ); - if( false == parser.getTokens( 2, false ) ) { - WriteLog( "Read LightsList: arguments missing in line " + std::to_string( LISTLINE + 1 ) ); - return false; - } - int idx = LISTLINE++; - if( idx > 16 ) { - WriteLog( "Read LightsList: number of entries exceeded capacity of the data table" ); - return false; - } - parser - >> Lights[0][idx] - >> Lights[1][idx]; - - return true; -} - -bool TMoverParameters::readCompressorList(std::string const &Input) { +bool TMoverParameters::readLightsList(std::string const &Input) +{ cParser parser(Input); - if (false == parser.getTokens(4, false)) { + if (false == parser.getTokens(2, false)) + { + WriteLog("Read LightsList: arguments missing in line " + std::to_string(LISTLINE + 1)); + return false; + } + int idx = LISTLINE++; + if (idx > 16) + { + WriteLog("Read LightsList: number of entries exceeded capacity of the data table"); + return false; + } + parser >> Lights[0][idx] >> Lights[1][idx]; + + return true; +} + +bool TMoverParameters::readCompressorList(std::string const &Input) +{ + + cParser parser(Input); + if (false == parser.getTokens(4, false)) + { WriteLog("Read CompressorList: arguments missing in line " + std::to_string(LISTLINE + 1)); return false; } int idx = LISTLINE++; - if (idx > 8 - 1) { + if (idx > 8 - 1) + { WriteLog("Read CompressorList: number of entries exceeded capacity of the data table"); return false; } - // NOTE: content of slot [x][0] is hardcoded elsewhere - parser - >> CompressorList[ 0 ][ idx + 1 ] - >> CompressorList[ 1 ][ idx + 1 ] - >> CompressorList[ 2 ][ idx + 1 ] - >> CompressorList[ 3 ][ idx + 1 ]; + // NOTE: content of slot [x][0] is hardcoded elsewhere + parser >> CompressorList[0][idx + 1] >> CompressorList[1][idx + 1] >> CompressorList[2][idx + 1] >> CompressorList[3][idx + 1]; return true; } @@ -9399,49 +9406,45 @@ bool TMoverParameters::readCompressorList(std::string const &Input) { // ************************************************************************************************* // Q: 20160719 // ************************************************************************************************* -void TMoverParameters::BrakeValveDecode( std::string const &Valve ) { +void TMoverParameters::BrakeValveDecode(std::string const &Valve) +{ - std::map valvetypes { - { "W", TBrakeValve::W }, - { "W_Lu_L", TBrakeValve::W_Lu_L }, - { "W_Lu_XR", TBrakeValve::W_Lu_XR }, - { "W_Lu_VI", TBrakeValve::W_Lu_VI }, - { "K", TBrakeValve::K }, - { "Kg", TBrakeValve::Kg }, - { "Kp", TBrakeValve::Kp }, - { "Kss", TBrakeValve::Kss }, - { "Kkg", TBrakeValve::Kkg }, - { "Kkp", TBrakeValve::Kkp }, - { "Kks", TBrakeValve::Kks }, - { "Hikp1", TBrakeValve::Hikp1 }, - { "Hikss", TBrakeValve::Hikss }, - { "Hikg1", TBrakeValve::Hikg1 }, - { "KE", TBrakeValve::KE }, - { "SW", TBrakeValve::SW }, - { "EStED", TBrakeValve::EStED }, - { "NESt3", TBrakeValve::NESt3 }, - { "ESt3", TBrakeValve::ESt3 }, - { "LSt", TBrakeValve::LSt }, - { "ESt4", TBrakeValve::ESt4 }, - { "ESt3AL2", TBrakeValve::ESt3AL2 }, - { "EP1", TBrakeValve::EP1 }, - { "EP2", TBrakeValve::EP2 }, - { "M483", TBrakeValve::M483 }, - { "CV1_L_TR", TBrakeValve::CV1_L_TR }, - { "CV1", TBrakeValve::CV1 }, - { "CV1_R", TBrakeValve::CV1_R } - }; - auto lookup = valvetypes.find( Valve ); - BrakeValve = - lookup != valvetypes.end() ? - lookup->second : - TBrakeValve::Other; + std::map valvetypes{{"W", TBrakeValve::W}, + {"W_Lu_L", TBrakeValve::W_Lu_L}, + {"W_Lu_XR", TBrakeValve::W_Lu_XR}, + {"W_Lu_VI", TBrakeValve::W_Lu_VI}, + {"K", TBrakeValve::K}, + {"Kg", TBrakeValve::Kg}, + {"Kp", TBrakeValve::Kp}, + {"Kss", TBrakeValve::Kss}, + {"Kkg", TBrakeValve::Kkg}, + {"Kkp", TBrakeValve::Kkp}, + {"Kks", TBrakeValve::Kks}, + {"Hikp1", TBrakeValve::Hikp1}, + {"Hikss", TBrakeValve::Hikss}, + {"Hikg1", TBrakeValve::Hikg1}, + {"KE", TBrakeValve::KE}, + {"SW", TBrakeValve::SW}, + {"EStED", TBrakeValve::EStED}, + {"NESt3", TBrakeValve::NESt3}, + {"ESt3", TBrakeValve::ESt3}, + {"LSt", TBrakeValve::LSt}, + {"ESt4", TBrakeValve::ESt4}, + {"ESt3AL2", TBrakeValve::ESt3AL2}, + {"EP1", TBrakeValve::EP1}, + {"EP2", TBrakeValve::EP2}, + {"M483", TBrakeValve::M483}, + {"CV1_L_TR", TBrakeValve::CV1_L_TR}, + {"CV1", TBrakeValve::CV1}, + {"CV1_R", TBrakeValve::CV1_R}}; + auto lookup = valvetypes.find(Valve); + BrakeValve = lookup != valvetypes.end() ? lookup->second : TBrakeValve::Other; - if( ( BrakeValve == TBrakeValve::Other ) - && ( contains( Valve, "ESt" ) ) ) { + if ((BrakeValve == TBrakeValve::Other) && (contains(Valve, "ESt"))) + { - BrakeValve = TBrakeValve::ESt3; - } + BrakeValve = TBrakeValve::ESt3; + } } // ************************************************************************************************* @@ -9449,34 +9452,34 @@ void TMoverParameters::BrakeValveDecode( std::string const &Valve ) { // ************************************************************************************************* void TMoverParameters::BrakeSubsystemDecode() { - BrakeSubsystem = TBrakeSubSystem::ss_None; - switch (BrakeValve) - { + BrakeSubsystem = TBrakeSubSystem::ss_None; + switch (BrakeValve) + { case TBrakeValve::W: case TBrakeValve::W_Lu_L: case TBrakeValve::W_Lu_VI: - case TBrakeValve::W_Lu_XR: - BrakeSubsystem = TBrakeSubSystem::ss_W; - break; + case TBrakeValve::W_Lu_XR: + BrakeSubsystem = TBrakeSubSystem::ss_W; + break; case TBrakeValve::ESt3: case TBrakeValve::ESt3AL2: case TBrakeValve::ESt4: case TBrakeValve::EP2: case TBrakeValve::EP1: - BrakeSubsystem = TBrakeSubSystem::ss_ESt; - break; - case TBrakeValve::KE: - BrakeSubsystem = TBrakeSubSystem::ss_KE; - break; + BrakeSubsystem = TBrakeSubSystem::ss_ESt; + break; + case TBrakeValve::KE: + BrakeSubsystem = TBrakeSubSystem::ss_KE; + break; case TBrakeValve::CV1: case TBrakeValve::CV1_L_TR: - BrakeSubsystem = TBrakeSubSystem::ss_Dako; - break; + BrakeSubsystem = TBrakeSubSystem::ss_Dako; + break; case TBrakeValve::LSt: case TBrakeValve::EStED: - BrakeSubsystem = TBrakeSubSystem::ss_LSt; - break; - } + BrakeSubsystem = TBrakeSubSystem::ss_LSt; + break; + } } // ************************************************************************************************* @@ -9488,135 +9491,148 @@ void TMoverParameters::BrakeSubsystemDecode() bool TMoverParameters::LoadFIZ(std::string chkpath) { chkPath = chkpath; // assign class path for reloading - const int param_ok = 1; - const int wheels_ok = 2; - const int dimensions_ok = 4; + const int param_ok = 1; + const int wheels_ok = 2; + const int dimensions_ok = 4; - ConversionError = 666; - LISTLINE = 0; - startBPT = false; - startMPT = false; - startMPT0 = false; - startRLIST = false; + ConversionError = 666; + LISTLINE = 0; + startBPT = false; + startMPT = false; + startMPT0 = false; + startRLIST = false; startUCLIST = false; - startDLIST = false; + startDLIST = false; startDIZELMOMENTUMLIST = false; startDIZELV2NMAXLIST = false; startHYDROTCLIST = false; startPMAXLIST = false; startFFLIST = false; startFFEDLIST = false; - startWWLIST = false; + startWWLIST = false; startWiperList = false; startDimmerList = false; - startLIGHTSLIST = false; + startLIGHTSLIST = false; startCOMPRESSORLIST = false; - std::string file = TypeName + ".fiz"; + std::string file = TypeName + ".fiz"; - WriteLog("LOAD FIZ FROM " + file); -/* - std::ifstream in(file); - if (!in.is_open()) + 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, chkpath); + if (false == fizparser.ok()) { WriteLog("E8 - FIZ FILE NOT EXIST."); return false; } -*/ - cParser fizparser( file, cParser::buffer_FILE, chkpath ); - if( false == fizparser.ok() ) { - WriteLog( "E8 - FIZ FILE NOT EXIST." ); - return false; - } - ConversionError = 0; + ConversionError = 0; - // Zbieranie danych zawartych w pliku FIZ - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - std::unordered_map fizlines; - std::string inputline; -/* - while (std::getline(in, inputline)) -*/ - while( fizparser.ok() ) { + // Zbieranie danych zawartych w pliku FIZ + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + std::unordered_map fizlines; + std::string inputline; + /* + while (std::getline(in, inputline)) + */ + while (fizparser.ok()) + { - inputline = fizparser.getToken( false, "\n\r" ); + inputline = fizparser.getToken(false, "\n\r"); - bool comment = ( ( contains( inputline, '#') ) - || ( starts_with( inputline, "//" ) ) ); - if( true == comment ) { - // skip commented lines - continue; - } + bool comment = ((contains(inputline, '#')) || (starts_with(inputline, "//"))); + if (true == comment) + { + // skip commented lines + continue; + } - if( !inputline.empty() && inputline.front() == ' ' ) { - // guard against malformed config files with leading spaces - inputline.erase( 0, inputline.find_first_not_of( ' ' ) ); - } + if (!inputline.empty() && inputline.front() == ' ') + { + // guard against malformed config files with leading spaces + inputline.erase(0, inputline.find_first_not_of(' ')); + } // trim CR at end (mainly for linux) if (!inputline.empty() && inputline.back() == '\r') inputline.pop_back(); - if( inputline.length() == 0 ) { + if (inputline.length() == 0) + { startBPT = false; continue; } - // checking if table parsing should be switched off goes first... - if( issection( "END-MPT", inputline ) ) { + // checking if table parsing should be switched off goes first... + if (issection("END-MPT", inputline)) + { startBPT = false; startMPT = false; - startMPT0 = false; + startMPT0 = false; continue; } - if( issection( "END-RL", inputline ) ) { + if (issection("END-RL", inputline)) + { startBPT = false; startRLIST = false; continue; } - if (issection("END-UCL", inputline)) { + if (issection("END-UCL", inputline)) + { startBPT = false; startUCLIST = false; continue; } - if( issection( "END-DL", inputline ) ) { - startBPT = false; - startDLIST = false; - continue; - } - if (issection("END-DML", inputline)) { + if (issection("END-DL", inputline)) + { + startBPT = false; + startDLIST = false; + continue; + } + if (issection("END-DML", inputline)) + { startBPT = false; startDIZELMOMENTUMLIST = false; continue; } - if (issection("END-V2NL", inputline)) { + if (issection("END-V2NL", inputline)) + { startBPT = false; startDIZELV2NMAXLIST = false; continue; } - if (issection("END-HTCL", inputline)) { + if (issection("END-HTCL", inputline)) + { startBPT = false; startHYDROTCLIST = false; continue; } - if (issection("END-PML", inputline)) { + if (issection("END-PML", inputline)) + { startBPT = false; startPMAXLIST = false; continue; } - if( issection( "endff", inputline ) ) { - startBPT = false; - startFFLIST = false; - startFFEDLIST = false; - continue; - } - if (issection("endwl", inputline)) - { - // skonczylismy czytac liste konfiguracji wycieraczek + if (issection("endff", inputline)) + { startBPT = false; - startWiperList = false; + startFFLIST = false; + startFFEDLIST = false; continue; - } + } + if (issection("endwl", inputline)) + { + // skonczylismy czytac liste konfiguracji wycieraczek + startBPT = false; + startWiperList = false; + continue; + } if (issection("endDimmerList", inputline)) { // skonczylismy czytac liste konfiguracji pstryka od przyciemnienia @@ -9624,176 +9640,194 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) startDimmerList = false; continue; } - if( issection( "END-WWL", inputline ) ) { - startBPT = false; - startWWLIST = false; - continue; - } - if( issection( "endL", inputline ) ) { - startBPT = false; - startLIGHTSLIST = false; - continue; - } - if ( issection( "endCL", inputline ) ) { + if (issection("END-WWL", inputline)) + { + startBPT = false; + startWWLIST = false; + continue; + } + if (issection("endL", inputline)) + { + startBPT = false; + startLIGHTSLIST = false; + continue; + } + if (issection("endCL", inputline)) + { startBPT = false; startCOMPRESSORLIST = false; continue; } - // ...then all recognized sections... - if( issection( "Param.", inputline ) ) - { + // ...then all recognized sections... + if (issection("Param.", inputline)) + { startBPT = false; - fizlines.emplace( "Param", inputline ); - LoadFIZ_Param( inputline ); - continue; - } - - if( issection( "Load:", inputline ) ) - { - startBPT = false; - fizlines.emplace( "Load", inputline ); - LoadFIZ_Load( inputline ); - continue; - } - - if( issection( "Dimensions:", inputline ) ) - { - startBPT = false; - fizlines.emplace( "Dimensions", inputline ); - LoadFIZ_Dimensions( inputline ); - continue; - } - - if( issection( "Wheels:", inputline ) ) - { - startBPT = false; - fizlines.emplace( "Wheels", inputline ); - LoadFIZ_Wheels( inputline ); - continue; - } - - if( issection( "Brake:", inputline ) ) - { - startBPT = false; - fizlines.emplace( "Brake", inputline ); - LoadFIZ_Brake( inputline ); - continue; - } - - if( issection( "Doors:", inputline ) ) { - - startBPT = false; - fizlines.emplace( "Doors", inputline ); - LoadFIZ_Doors( inputline ); - continue; - } - - if( issection( "BuffCoupl.", inputline ) ) { - - startBPT = false; - fizlines.emplace( "BuffCoupl", inputline ); - LoadFIZ_BuffCoupl( inputline, 0 ); - continue; - } - - else if( issection( "BuffCoupl1.", inputline ) ) { - - startBPT = false; - fizlines.emplace( "BuffCoupl1", inputline ); - LoadFIZ_BuffCoupl( inputline, 1 ); - continue; - } - - else if( issection( "BuffCoupl2.", inputline ) ) { - - startBPT = false; - fizlines.emplace( "BuffCoupl2", inputline ); - LoadFIZ_BuffCoupl( inputline, 2 ); - continue; - } - - if( issection( "TurboPos:", inputline ) ) { - - startBPT = false; - fizlines.emplace( "TurboPos", inputline ); - LoadFIZ_TurboPos( inputline ); - continue; - } - - if( issection( "Cntrl.", inputline ) ) { - - startBPT = true; LISTLINE = 0; - fizlines.emplace( "Cntrl", inputline ); - LoadFIZ_Cntrl( inputline ); - continue; - } - - if (issection("Headlights:", inputline)) - { - startBPT = false; - fizlines.emplace("Headlights", inputline); - LoadFIZ_Headlights(inputline); - continue; - } - - if (issection("Blending:", inputline)) { - - startBPT = false; LISTLINE = 0; - fizlines.emplace( "Blending", inputline); - LoadFIZ_Blending( inputline ); + fizlines.emplace("Param", inputline); + LoadFIZ_Param(inputline); continue; } - if (issection("DCEMUED:", inputline)) { + if (issection("Load:", inputline)) + { + startBPT = false; + fizlines.emplace("Load", inputline); + LoadFIZ_Load(inputline); + continue; + } - startBPT = false; LISTLINE = 0; + if (issection("Dimensions:", inputline)) + { + startBPT = false; + fizlines.emplace("Dimensions", inputline); + LoadFIZ_Dimensions(inputline); + continue; + } + + if (issection("Wheels:", inputline)) + { + startBPT = false; + fizlines.emplace("Wheels", inputline); + LoadFIZ_Wheels(inputline); + continue; + } + + if (issection("Brake:", inputline)) + { + startBPT = false; + fizlines.emplace("Brake", inputline); + LoadFIZ_Brake(inputline); + continue; + } + + if (issection("Doors:", inputline)) + { + + startBPT = false; + fizlines.emplace("Doors", inputline); + LoadFIZ_Doors(inputline); + continue; + } + + if (issection("BuffCoupl.", inputline)) + { + + startBPT = false; + fizlines.emplace("BuffCoupl", inputline); + LoadFIZ_BuffCoupl(inputline, 0); + continue; + } + + else if (issection("BuffCoupl1.", inputline)) + { + + startBPT = false; + fizlines.emplace("BuffCoupl1", inputline); + LoadFIZ_BuffCoupl(inputline, 1); + continue; + } + + else if (issection("BuffCoupl2.", inputline)) + { + + startBPT = false; + fizlines.emplace("BuffCoupl2", inputline); + LoadFIZ_BuffCoupl(inputline, 2); + continue; + } + + if (issection("TurboPos:", inputline)) + { + + startBPT = false; + fizlines.emplace("TurboPos", inputline); + LoadFIZ_TurboPos(inputline); + continue; + } + + if (issection("Cntrl.", inputline)) + { + + startBPT = true; + LISTLINE = 0; + fizlines.emplace("Cntrl", inputline); + LoadFIZ_Cntrl(inputline); + continue; + } + + if (issection("Headlights:", inputline)) + { + startBPT = false; + fizlines.emplace("Headlights", inputline); + LoadFIZ_Headlights(inputline); + continue; + } + + if (issection("Blending:", inputline)) + { + + startBPT = false; + LISTLINE = 0; + fizlines.emplace("Blending", inputline); + LoadFIZ_Blending(inputline); + continue; + } + + if (issection("DCEMUED:", inputline)) + { + + startBPT = false; + LISTLINE = 0; fizlines.emplace("DCEMUED", inputline); LoadFIZ_DCEMUED(inputline); continue; } - if (issection("SpringBrake:", inputline)) { + if (issection("SpringBrake:", inputline)) + { - startBPT = false; LISTLINE = 0; + startBPT = false; + LISTLINE = 0; fizlines.emplace("SpringBrake", inputline); LoadFIZ_SpringBrake(inputline); continue; } - if( issection( "Light:", inputline ) ) { + if (issection("Light:", inputline)) + { - startBPT = false; - fizlines.emplace( "Light", inputline ); - LoadFIZ_Light( inputline ); - continue; - } - - if( issection( "Security:", inputline ) ) - { startBPT = false; - fizlines.emplace( "Security", inputline ); + fizlines.emplace("Light", inputline); + LoadFIZ_Light(inputline); + continue; + } + + if (issection("Security:", inputline)) + { + startBPT = false; + fizlines.emplace("Security", inputline); SecuritySystem.load(inputline, Vmax); - extract_value( EmergencyBrakeWarningSignal, "EmergencyBrakeWarningSignal", inputline, "" ); - continue; - } + extract_value(EmergencyBrakeWarningSignal, "EmergencyBrakeWarningSignal", inputline, ""); + continue; + } - if( issection( "Clima:", inputline ) ) { + if (issection("Clima:", inputline)) + { - startBPT = false; - fizlines.emplace( "Clima", inputline ); - LoadFIZ_Clima( inputline ); - continue; - } - - if( issection( "Power:", inputline ) ) - { startBPT = false; - fizlines.emplace( "Power", inputline ); - LoadFIZ_Power( inputline ); - continue; - } + fizlines.emplace("Clima", inputline); + LoadFIZ_Clima(inputline); + continue; + } - if (issection("SpeedControl:", inputline)) + if (issection("Power:", inputline)) + { + startBPT = false; + fizlines.emplace("Power", inputline); + LoadFIZ_Power(inputline); + continue; + } + + if (issection("SpeedControl:", inputline)) { startBPT = false; fizlines.emplace("SpeedControl", inputline); @@ -9801,82 +9835,92 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) continue; } - if( issection( "Engine:", inputline ) ) - { + if (issection("Engine:", inputline)) + { startBPT = false; - fizlines.emplace( "Engine", inputline ); - LoadFIZ_Engine( inputline ); + fizlines.emplace("Engine", inputline); + LoadFIZ_Engine(inputline); continue; - } + } - if( issection( "Switches:", inputline ) ) { - startBPT = false; - fizlines.emplace( "Switches", inputline ); - LoadFIZ_Switches( inputline ); - continue; - } - - if( issection( "MotorParamTable:", inputline ) ) { - startBPT = false; - startMPT = true; LISTLINE = 0; - fizlines.emplace( "MotorParamTable", inputline ); - LoadFIZ_MotorParamTable( inputline ); - continue; - } - - if( issection( "MotorParamTable0:", inputline ) ) { - startBPT = false; - startMPT0 = true; LISTLINE = 0; - continue; - } - - if( issection( "Circuit:", inputline ) ) - { + if (issection("Switches:", inputline)) + { startBPT = false; - fizlines.emplace( "Circuit", inputline ); - LoadFIZ_Circuit( inputline ); - continue; - } + fizlines.emplace("Switches", inputline); + LoadFIZ_Switches(inputline); + continue; + } - if( issection( "AI:", inputline ) ) { - startBPT = false; - fizlines.emplace( "AI", inputline ); - LoadFIZ_AI( inputline ); - continue; - } - - if( issection( "RList:", inputline ) ) - { + if (issection("MotorParamTable:", inputline)) + { startBPT = false; - fizlines.emplace( "RList", inputline ); - startRLIST = true; LISTLINE = 0; - LoadFIZ_RList( inputline ); - continue; - } + startMPT = true; + LISTLINE = 0; + fizlines.emplace("MotorParamTable", inputline); + LoadFIZ_MotorParamTable(inputline); + continue; + } + + if (issection("MotorParamTable0:", inputline)) + { + startBPT = false; + startMPT0 = true; + LISTLINE = 0; + continue; + } + + if (issection("Circuit:", inputline)) + { + startBPT = false; + fizlines.emplace("Circuit", inputline); + LoadFIZ_Circuit(inputline); + continue; + } + + if (issection("AI:", inputline)) + { + startBPT = false; + fizlines.emplace("AI", inputline); + LoadFIZ_AI(inputline); + continue; + } + + if (issection("RList:", inputline)) + { + startBPT = false; + fizlines.emplace("RList", inputline); + startRLIST = true; + LISTLINE = 0; + LoadFIZ_RList(inputline); + continue; + } if (issection("UCList:", inputline)) { startBPT = false; fizlines.emplace("UCList", inputline); - startUCLIST = true; LISTLINE = 0; + startUCLIST = true; + LISTLINE = 0; LoadFIZ_UCList(inputline); continue; } - if( issection( "DList:", inputline ) ) - { + if (issection("DList:", inputline)) + { startBPT = false; - fizlines.emplace( "DList", inputline ); - startDLIST = true; LISTLINE = 0; - LoadFIZ_DList( inputline ); - continue; - } + fizlines.emplace("DList", inputline); + startDLIST = true; + LISTLINE = 0; + LoadFIZ_DList(inputline); + continue; + } if (issection("DMList:", inputline)) { startBPT = false; fizlines.emplace("DMList", inputline); - startDIZELMOMENTUMLIST = true; LISTLINE = 0; + startDIZELMOMENTUMLIST = true; + LISTLINE = 0; continue; } @@ -9884,7 +9928,8 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) { startBPT = false; fizlines.emplace("HTCList", inputline); - startHYDROTCLIST = true; LISTLINE = 0; + startHYDROTCLIST = true; + LISTLINE = 0; continue; } @@ -9892,7 +9937,8 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) { startBPT = false; fizlines.emplace("PmaxList", inputline); - startPMAXLIST = true; LISTLINE = 0; + startPMAXLIST = true; + LISTLINE = 0; continue; } @@ -9900,249 +9946,270 @@ bool TMoverParameters::LoadFIZ(std::string chkpath) { startBPT = false; fizlines.emplace("V2NList", inputline); - startDIZELV2NMAXLIST = true; LISTLINE = 0; + startDIZELV2NMAXLIST = true; + LISTLINE = 0; continue; } - if( issection( "ffList:", inputline ) ) { - startBPT = false; - startFFLIST = true; LISTLINE = 0; - LoadFIZ_FFList( inputline ); - continue; - } - - if( issection( "ffBrakeList:", inputline ) ) { - startBPT = false; - startFFEDLIST = true; LISTLINE = 0; - LoadFIZ_FFEDList( inputline ); - continue; - } - - if( issection( "WWList:", inputline ) ) - { + if (issection("ffList:", inputline)) + { startBPT = false; - startWWLIST = true; LISTLINE = 0; - + startFFLIST = true; + LISTLINE = 0; + LoadFIZ_FFList(inputline); continue; - } + } - if (issection("WiperList:", inputline)) + if (issection("ffBrakeList:", inputline)) + { + startBPT = false; + startFFEDLIST = true; + LISTLINE = 0; + LoadFIZ_FFEDList(inputline); + continue; + } + + if (issection("WWList:", inputline)) + { + startBPT = false; + startWWLIST = true; + LISTLINE = 0; + + continue; + } + + if (issection("WiperList:", inputline)) { startBPT = false; fizlines.emplace("WiperList", inputline); startWiperList = true; - LISTLINE = 0; - LoadFIZ_WiperList(inputline); + LISTLINE = 0; + LoadFIZ_WiperList(inputline); - continue; - } + continue; + } - if (issection("DimmerList:", inputline)) - { - dimPositions.clear(); // uzywamy customowej listy + if (issection("DimmerList:", inputline)) + { + dimPositions.clear(); // uzywamy customowej listy startBPT = false; startDimmerList = true; fizlines.emplace("DimmerList", inputline); LoadFIZ_DimmerList(inputline); continue; - } + } - - if( issection( "LightsList:", inputline ) ) { - startBPT = false; - fizlines.emplace( "LightsList", inputline ); - startLIGHTSLIST = true; LISTLINE = 0; - LoadFIZ_LightsList( inputline ); - continue; - } - - if (issection("CompressorList:", inputline)) { + if (issection("LightsList:", inputline)) + { startBPT = false; - fizlines.emplace("CompressorList", inputline); - startCOMPRESSORLIST = true; LISTLINE = 0; - LoadFIZ_CompressorList( inputline ); + fizlines.emplace("LightsList", inputline); + startLIGHTSLIST = true; + LISTLINE = 0; + LoadFIZ_LightsList(inputline); continue; } - // ...and finally, table parsers. - // NOTE: once table parsing is enabled it lasts until switched off, when another section is recognized - if( true == startBPT ) { - readBPT( inputline ); - continue; - } - if( true == startMPT ) { - readMPT( inputline ); - continue; - } - if( true == startMPT0 ) { - readMPT0( inputline ); - continue; - } - if( true == startRLIST ) { - readRList( inputline ); - continue; - } - if (true == startUCLIST) { + if (issection("CompressorList:", inputline)) + { + startBPT = false; + fizlines.emplace("CompressorList", inputline); + startCOMPRESSORLIST = true; + LISTLINE = 0; + LoadFIZ_CompressorList(inputline); + continue; + } + + // ...and finally, table parsers. + // NOTE: once table parsing is enabled it lasts until switched off, when another section is recognized + if (true == startBPT) + { + readBPT(inputline); + continue; + } + if (true == startMPT) + { + readMPT(inputline); + continue; + } + if (true == startMPT0) + { + readMPT0(inputline); + continue; + } + if (true == startRLIST) + { + readRList(inputline); + continue; + } + if (true == startUCLIST) + { readUCList(inputline); continue; } - if( true == startDLIST ) { - readDList( inputline ); - continue; - } - if (true == startDIZELMOMENTUMLIST) { + if (true == startDLIST) + { + readDList(inputline); + continue; + } + if (true == startDIZELMOMENTUMLIST) + { readDMList(inputline); continue; } - if (true == startDIZELV2NMAXLIST) { + if (true == startDIZELV2NMAXLIST) + { readV2NMAXList(inputline); continue; } - if (true == startHYDROTCLIST) { + if (true == startHYDROTCLIST) + { readHTCList(inputline); continue; } - if (true == startPMAXLIST) { + if (true == startPMAXLIST) + { readPmaxList(inputline); continue; } - if( true == startFFLIST ) { - readFFList( inputline ); - continue; - } - if( true == startFFEDLIST ) { - readFFEDList( inputline ); - continue; - } - if( true == startWWLIST ) { - readWWList( inputline ); + if (true == startFFLIST) + { + readFFList(inputline); + continue; + } + if (true == startFFEDLIST) + { + readFFEDList(inputline); + continue; + } + if (true == startWWLIST) + { + readWWList(inputline); continue; } if (true == startWiperList) - { + { readWiperList(inputline); continue; - } - if (true == startDimmerList) - { + } + if (true == startDimmerList) + { readDimmerList(inputline); - } - if( true == startLIGHTSLIST ) { - readLightsList( inputline ); - continue; - } - if (true == startCOMPRESSORLIST) { + } + if (true == startLIGHTSLIST) + { + readLightsList(inputline); + continue; + } + if (true == startCOMPRESSORLIST) + { readCompressorList(inputline); continue; } - } // while line -/* - in.close(); -*/ - // Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie - // zaleznosci + } // while line + /* + in.close(); + */ + // Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie + // zaleznosci - bool result; - if (ConversionError == 0) - result = true; - else - result = false; + bool result; + if (ConversionError == 0) + result = true; + else + result = false; - // ustawiamy domyslna pozycje dimmera + // ustawiamy domyslna pozycje dimmera if (!enableModernDimmer) { modernDimmerPosition = modernDimmerDefaultPosition; } - WriteLog("CERROR: " + to_string(ConversionError) + ", SUCCES: " + to_string(result)); - return result; + WriteLog("CERROR: " + to_string(ConversionError) + ", SUCCES: " + to_string(result)); + return result; } -void TMoverParameters::LoadFIZ_Param( std::string const &line ) { +void TMoverParameters::LoadFIZ_Param(std::string const &line) +{ - extract_value( Mass, "M", line, "0" ); - extract_value( Mred, "Mred", line, "0" ); - extract_value( Vmax, "Vmax", line, "0" ); - extract_value( Power, "PWR", line, "0" ); - extract_value( SandCapacity, "SandCap", line, "0" ); - extract_value( HeatingPower, "HeatingP", line, "0" ); - extract_value( LightPower, "LightP", line, "0" ); + extract_value(Mass, "M", line, "0"); + extract_value(Mred, "Mred", line, "0"); + extract_value(Vmax, "Vmax", line, "0"); + extract_value(Power, "PWR", line, "0"); + extract_value(SandCapacity, "SandCap", line, "0"); + extract_value(HeatingPower, "HeatingP", line, "0"); + extract_value(LightPower, "LightP", line, "0"); - { - std::map categories{ - { "train", 1 }, - { "road", 2 }, - { "unimog", 3 }, - { "ship", 4 }, - { "airplane,", 8 } - }; - std::string category; extract_value( category, "Category", line, "none" ); - auto lookup = categories.find( category ); - CategoryFlag = ( - lookup != categories.end() ? - lookup->second : - 0 ); - if( CategoryFlag == 0 ) { - ErrorLog( "Unknown vehicle category: \"" + category + "\"." ); - } - } + { + std::map categories{{"train", 1}, {"road", 2}, {"unimog", 3}, {"ship", 4}, {"airplane,", 8}}; + std::string category; + extract_value(category, "Category", line, "none"); + auto lookup = categories.find(category); + CategoryFlag = (lookup != categories.end() ? lookup->second : 0); + if (CategoryFlag == 0) + { + ErrorLog("Unknown vehicle category: \"" + category + "\"."); + } + } - { - std::map types{ - { "pseudodiesel", dt_PseudoDiesel }, - { "ezt", dt_EZT }, - { "dmu", dt_DMU }, - { "sn61", dt_SN61 }, - { "et22", dt_ET22 }, - { "et40", dt_ET40 }, - { "et41", dt_ET41 }, - { "et42", dt_ET42 }, - { "ep05", dt_EP05 }, - { "181", dt_181 }, - { "182", dt_181 } // na razie tak - }; - std::string type; extract_value( type, "Type", line, "none" ); - auto lookup = types.find( ToLower( type ) ); - TrainType = ( - lookup != types.end() ? - lookup->second : - dt_Default ); - } + { + std::map types{ + {"pseudodiesel", dt_PseudoDiesel}, + {"ezt", dt_EZT}, + {"dmu", dt_DMU}, + {"sn61", dt_SN61}, + {"et22", dt_ET22}, + {"et40", dt_ET40}, + {"et41", dt_ET41}, + {"et42", dt_ET42}, + {"ep05", dt_EP05}, + {"181", dt_181}, + {"182", dt_181} // na razie tak + }; + std::string type; + extract_value(type, "Type", line, "none"); + auto lookup = types.find(ToLower(type)); + TrainType = (lookup != types.end() ? lookup->second : dt_Default); + } - if( TrainType == dt_EZT ) { + if (TrainType == dt_EZT) + { - IminLo = 1; - IminHi = 2; - Imin = 1; - } + IminLo = 1; + IminHi = 2; + Imin = 1; + } } -void TMoverParameters::LoadFIZ_Load( std::string const &line ) { +void TMoverParameters::LoadFIZ_Load(std::string const &line) +{ - auto const acceptedloads { Split( extract_value( "LoadAccepted", line ), ',' ) }; + auto const acceptedloads{Split(extract_value("LoadAccepted", line), ',')}; - if( acceptedloads.empty() ) { return; } + if (acceptedloads.empty()) + { + return; + } - auto const minoffsets { Split( extract_value( "LoadMinOffset", line ), ',' ) }; - auto minoffset { 0.f }; - auto minoffsetsiterator { std::begin( minoffsets ) }; - // NOTE: last (if any) offset parameter retrieved from the list applies to the remainder of the list - // TBD, TODO: include other load parameters in this system - for( auto &load : acceptedloads ) { - if( minoffsetsiterator != std::end( minoffsets ) ) { - minoffset = std::stof( *minoffsetsiterator ); - ++minoffsetsiterator; - } - LoadAttributes.emplace_back( - ToLower( load ), - minoffset ); - } + auto const minoffsets{Split(extract_value("LoadMinOffset", line), ',')}; + auto minoffset{0.f}; + auto minoffsetsiterator{std::begin(minoffsets)}; + // NOTE: last (if any) offset parameter retrieved from the list applies to the remainder of the list + // TBD, TODO: include other load parameters in this system + for (auto &load : acceptedloads) + { + if (minoffsetsiterator != std::end(minoffsets)) + { + minoffset = std::stof(*minoffsetsiterator); + ++minoffsetsiterator; + } + LoadAttributes.emplace_back(ToLower(load), minoffset); + } - extract_value( MaxLoad, "MaxLoad", line, "" ); - extract_value( LoadQuantity, "LoadQ", line, "" ); - extract_value( OverLoadFactor, "OverLoadFactor", line, "" ); - extract_value( LoadSpeed, "LoadSpeed", line, "" ); - extract_value( UnLoadSpeed, "UnLoadSpeed", line, "" ); + extract_value(MaxLoad, "MaxLoad", line, ""); + extract_value(LoadQuantity, "LoadQ", line, ""); + extract_value(OverLoadFactor, "OverLoadFactor", line, ""); + extract_value(LoadSpeed, "LoadSpeed", line, ""); + extract_value(UnLoadSpeed, "UnLoadSpeed", line, ""); } void TMoverParameters::LoadFIZ_Headlights(std::string const &line) @@ -10151,192 +10218,196 @@ void TMoverParameters::LoadFIZ_Headlights(std::string const &line) extract_value(refG, "LampGreen", line, ""); extract_value(refB, "LampBlue", line, ""); - extract_value(dimMultiplier, "DimmedMultiplier", line, ""); - extract_value(normMultiplier, "NormalMultiplier", line, ""); - extract_value(highDimMultiplier, "HighbeamDimmedMultiplier", line, ""); - extract_value(highMultiplier, "HighBeamMultiplier", line, ""); + extract_value(dimMultiplier, "DimmedMultiplier", line, ""); + extract_value(normMultiplier, "NormalMultiplier", line, ""); + extract_value(highDimMultiplier, "HighbeamDimmedMultiplier", line, ""); + extract_value(highMultiplier, "HighBeamMultiplier", line, ""); } -void TMoverParameters::LoadFIZ_Dimensions( std::string const &line ) { +void TMoverParameters::LoadFIZ_Dimensions(std::string const &line) +{ - extract_value( Dim.L, "L", line, "" ); - extract_value( Dim.H, "H", line, "" ); - extract_value( Dim.W, "W", line, "" ); + extract_value(Dim.L, "L", line, ""); + extract_value(Dim.H, "H", line, ""); + extract_value(Dim.W, "W", line, ""); - extract_value( Cx, "Cx", line, "0.3" ); - if( Dim.H <= 2.0 ) { - //gdyby nie było parametru, lepsze to niż zero - Floor = Dim.H; - } - else { - //zgodność wsteczna - Floor = 0.0; - } - extract_value( Floor, "Floor", line, "" ); + extract_value(Cx, "Cx", line, "0.3"); + if (Dim.H <= 2.0) + { + // gdyby nie było parametru, lepsze to niż zero + Floor = Dim.H; + } + else + { + // zgodność wsteczna + Floor = 0.0; + } + extract_value(Floor, "Floor", line, ""); } -void TMoverParameters::LoadFIZ_Wheels( std::string const &line ) { +void TMoverParameters::LoadFIZ_Wheels(std::string const &line) +{ - extract_value( WheelDiameter, "D", line, "" ); - WheelDiameterL = WheelDiameter; //gdyby nie było parametru, lepsze to niż zero - extract_value( WheelDiameterL, "Dl", line, "" ); - WheelDiameterT = WheelDiameter; //gdyby nie było parametru, lepsze to niż zero - extract_value( WheelDiameterT, "Dt", line, "" ); + extract_value(WheelDiameter, "D", line, ""); + WheelDiameterL = WheelDiameter; // gdyby nie było parametru, lepsze to niż zero + extract_value(WheelDiameterL, "Dl", line, ""); + WheelDiameterT = WheelDiameter; // gdyby nie było parametru, lepsze to niż zero + extract_value(WheelDiameterT, "Dt", line, ""); - extract_value( TrackW, "Tw", line, "" ); - extract_value( AxleInertialMoment, "AIM", line, "" ); + extract_value(TrackW, "Tw", line, ""); + extract_value(AxleInertialMoment, "AIM", line, ""); - extract_value( AxleArangement, "Axle", line, "" ); - NPoweredAxles = s2NPW( AxleArangement ); - NAxles = NPoweredAxles + s2NNW( AxleArangement ); + extract_value(AxleArangement, "Axle", line, ""); + NPoweredAxles = s2NPW(AxleArangement); + NAxles = NPoweredAxles + s2NNW(AxleArangement); - BearingType = - ( extract_value( "BearingType", line ) == "Roll" ) ? - 1 : - 0; + BearingType = (extract_value("BearingType", line) == "Roll") ? 1 : 0; - extract_value( ADist, "Ad", line, "" ); - extract_value( BDist, "Bd", line, "" ); + extract_value(ADist, "Ad", line, ""); + extract_value(BDist, "Bd", line, ""); - if( AxleInertialMoment <= 0.0 ) { -/* - AxleInertialMoment = 1.0; -*/ - // approximation formula by youby - auto const k = 472.0; // arbitrary constant - AxleInertialMoment = k / 4.0 * std::pow( WheelDiameter, 4.0 ) * NAxles; - Mred = k * std::pow( WheelDiameter, 2.0 ) * NAxles; - } + if (AxleInertialMoment <= 0.0) + { + /* + AxleInertialMoment = 1.0; + */ + // approximation formula by youby + auto const k = 472.0; // arbitrary constant + AxleInertialMoment = k / 4.0 * std::pow(WheelDiameter, 4.0) * NAxles; + Mred = k * std::pow(WheelDiameter, 2.0) * NAxles; + } } -void TMoverParameters::LoadFIZ_Brake( std::string const &line ) { +void TMoverParameters::LoadFIZ_Brake(std::string const &line) +{ - extract_value( BrakeValveParams, "BrakeValve", line, "" ); - BrakeValveDecode( BrakeValveParams ); - BrakeSubsystemDecode(); + extract_value(BrakeValveParams, "BrakeValve", line, ""); + BrakeValveDecode(BrakeValveParams); + BrakeSubsystemDecode(); - extract_value( NBpA, "NBpA", line, "" ); - extract_value( MaxBrakeForce, "MBF", line, "" ); - extract_value( BrakeValveSize, "Size", line, "" ); - extract_value( TrackBrakeForce, "TBF", line, "" ); TrackBrakeForce *= 1000.0; + extract_value(NBpA, "NBpA", line, ""); + extract_value(MaxBrakeForce, "MBF", line, ""); + extract_value(BrakeValveSize, "Size", line, ""); + extract_value(TrackBrakeForce, "TBF", line, ""); + TrackBrakeForce *= 1000.0; - extract_value( MaxBrakePress[ 3 ], "MaxBP", line, "" ); - if( MaxBrakePress[ 3 ] > 0.0 ) { + extract_value(MaxBrakePress[3], "MaxBP", line, ""); + if (MaxBrakePress[3] > 0.0) + { - extract_value( BrakeCylNo, "BCN", line, "" ); - if( BrakeCylNo > 0 ) { + extract_value(BrakeCylNo, "BCN", line, ""); + if (BrakeCylNo > 0) + { - extract_value( MaxBrakePress[ 0 ], "MaxLBP", line, "" ); - if( MaxBrakePress[ 0 ] < 0.01 ) { MaxBrakePress[ 0 ] = MaxBrakePress[ 3 ]; } - extract_value( MaxBrakePress[ 1 ], "TareMaxBP", line, "" ); - extract_value( MaxBrakePress[ 2 ], "MedMaxBP", line, "" ); - extract_value( MaxBrakePress[ 4 ], "MaxASBP", line, "" ); - if( MaxBrakePress[ 4 ] < 0.01 ) { MaxBrakePress[ 4 ] = 0.0; } + extract_value(MaxBrakePress[0], "MaxLBP", line, ""); + if (MaxBrakePress[0] < 0.01) + { + MaxBrakePress[0] = MaxBrakePress[3]; + } + extract_value(MaxBrakePress[1], "TareMaxBP", line, ""); + extract_value(MaxBrakePress[2], "MedMaxBP", line, ""); + extract_value(MaxBrakePress[4], "MaxASBP", line, ""); + if (MaxBrakePress[4] < 0.01) + { + MaxBrakePress[4] = 0.0; + } - extract_value( BrakeCylRadius, "BCR", line, "" ); - extract_value( BrakeCylDist, "BCD", line, "" ); - extract_value( BrakeCylSpring, "BCS", line, "" ); - extract_value( BrakeSlckAdj, "BSA", line, "" ); - extract_value( BrakeRigEff, "BRE", line, "1" ); + extract_value(BrakeCylRadius, "BCR", line, ""); + extract_value(BrakeCylDist, "BCD", line, ""); + extract_value(BrakeCylSpring, "BCS", line, ""); + extract_value(BrakeSlckAdj, "BSA", line, ""); + extract_value(BrakeRigEff, "BRE", line, "1"); - extract_value( BrakeCylMult[ 0 ], "BCM", line, "" ); - extract_value( BrakeCylMult[ 1 ], "BCMlo", line, "" ); - extract_value( BrakeCylMult[ 2 ], "BCMHi", line, "" ); + extract_value(BrakeCylMult[0], "BCM", line, ""); + extract_value(BrakeCylMult[1], "BCMlo", line, ""); + extract_value(BrakeCylMult[2], "BCMHi", line, ""); - P2FTrans = 100 * M_PI * std::pow( BrakeCylRadius, 2 ); // w kN/bar + P2FTrans = 100 * M_PI * std::pow(BrakeCylRadius, 2); // w kN/bar - if( ( BrakeCylMult[ 1 ] > 0.0 ) || ( MaxBrakePress[ 1 ] > 0.0 ) ) { LoadFlag = 1; } - else { LoadFlag = 0; } + if ((BrakeCylMult[1] > 0.0) || (MaxBrakePress[1] > 0.0)) + { + LoadFlag = 1; + } + else + { + LoadFlag = 0; + } - BrakeVolume = M_PI * std::pow( BrakeCylRadius, 2 ) * BrakeCylDist * BrakeCylNo; - extract_value( BrakeVVolume, "BVV", line, "" ); + BrakeVolume = M_PI * std::pow(BrakeCylRadius, 2) * BrakeCylDist * BrakeCylNo; + extract_value(BrakeVVolume, "BVV", line, ""); - { - std::map brakemethods{ - { "P10-Bg", bp_P10Bg }, - { "P10-Bgu", bp_P10Bgu }, - { "FR513", bp_FR513 }, - { "FR510", bp_FR510 }, - { "Cosid", bp_Cosid }, - { "P10yBg", bp_P10yBg }, - { "P10yBgu", bp_P10yBgu }, - { "Disk1", bp_D1 }, - { "Disk1+Mg", bp_D1 + bp_MHS }, - { "Disk2", bp_D2 } - }; - auto lookup = brakemethods.find( extract_value( "BM", line ) ); - BrakeMethod = - lookup != brakemethods.end() ? - lookup->second : - 0; - } + { + std::map brakemethods{{"P10-Bg", bp_P10Bg}, {"P10-Bgu", bp_P10Bgu}, {"FR513", bp_FR513}, {"FR510", bp_FR510}, {"Cosid", bp_Cosid}, + {"P10yBg", bp_P10yBg}, {"P10yBgu", bp_P10yBgu}, {"Disk1", bp_D1}, {"Disk1+Mg", bp_D1 + bp_MHS}, {"Disk2", bp_D2}}; + auto lookup = brakemethods.find(extract_value("BM", line)); + BrakeMethod = lookup != brakemethods.end() ? lookup->second : 0; + } - extract_value( RapidMult, "RM", line, "1" ); - extract_value( RapidVel, "RV", line, "55" ); - } - } - else { - // maxbrakepress[3] == 0 or less - P2FTrans = 0; - } + extract_value(RapidMult, "RM", line, "1"); + extract_value(RapidVel, "RV", line, "55"); + } + } + else + { + // maxbrakepress[3] == 0 or less + P2FTrans = 0; + } - CntrlPipePress = 5 + 0.001 * ( Random( 10 ) - Random( 10 ) ); //Ra 2014-07: trochę niedokładności - extract_value( CntrlPipePress, "HiPP", line, "" ); - HighPipePress = CntrlPipePress; - LowPipePress = std::min( HighPipePress, 3.5 ); - extract_value( LowPipePress, "LoPP", line, "" ); - DeltaPipePress = HighPipePress - LowPipePress; + CntrlPipePress = 5 + 0.001 * (Random(10) - Random(10)); // Ra 2014-07: trochę niedokładności + extract_value(CntrlPipePress, "HiPP", line, ""); + HighPipePress = CntrlPipePress; + LowPipePress = std::min(HighPipePress, 3.5); + extract_value(LowPipePress, "LoPP", line, ""); + DeltaPipePress = HighPipePress - LowPipePress; - extract_value( VeselVolume, "Vv", line, "" ); -/* - if( VeselVolume == 0.0 ) { VeselVolume = 0.01; } -*/ - extract_value( MinCompressor, "MinCP", line, "" ); - extract_value( MaxCompressor, "MaxCP", line, "" ); - extract_value( MinCompressor_cabB, "MinCP_B", line, "" ); - extract_value( MaxCompressor_cabB, "MaxCP_B", line, "" ); - extract_value( CompressorTankValve, "CompressorTankValve", line, "" ); - extract_value( CompressorSpeed, "CompressorSpeed", line, "" ); - extract_value( EmergencyValveOff, "MinEVP", line, "" ); - extract_value( EmergencyValveOn, "MaxEVP", line, "" ); - extract_value( EmergencyValveArea, "EVArea", line, "" ); - extract_value( UniversalBrakeButtonFlag[0], "UBB1", line, ""); - extract_value( UniversalBrakeButtonFlag[1], "UBB2", line, ""); - extract_value( UniversalBrakeButtonFlag[2], "UBB3", line, ""); - extract_value( LockPipeOn, "LPOn", line, "-1"); - extract_value( LockPipeOff, "LPOff", line, "-1"); - extract_value( HandleUnlock, "HandlePipeUnlockPos", line, "-3"); - extract_value( EmergencyCutsOffHandle, "EmergencyCutsOffHandle", line, ""); - { - std::map compressorpowers{ - { "Main", 0 }, - // 1: default, powered by converter, with manual state control - { "Converter", 2 }, - { "Engine", 3 }, // equivalent of 0, TODO: separate 'main' and 'engine' in the code - { "Coupler1", 4 },//włączana w silnikowym EZT z przodu - { "Coupler2", 5 } //włączana w silnikowym EZT z tyłu - }; - auto lookup = compressorpowers.find( extract_value( "CompressorPower", line ) ); - CompressorPower = - lookup != compressorpowers.end() ? - lookup->second : - 1; - } + extract_value(VeselVolume, "Vv", line, ""); + /* + if( VeselVolume == 0.0 ) { VeselVolume = 0.01; } + */ + extract_value(MinCompressor, "MinCP", line, ""); + extract_value(MaxCompressor, "MaxCP", line, ""); + extract_value(MinCompressor_cabB, "MinCP_B", line, ""); + extract_value(MaxCompressor_cabB, "MaxCP_B", line, ""); + extract_value(CompressorTankValve, "CompressorTankValve", line, ""); + extract_value(CompressorSpeed, "CompressorSpeed", line, ""); + extract_value(EmergencyValveOff, "MinEVP", line, ""); + extract_value(EmergencyValveOn, "MaxEVP", line, ""); + extract_value(EmergencyValveArea, "EVArea", line, ""); + extract_value(UniversalBrakeButtonFlag[0], "UBB1", line, ""); + extract_value(UniversalBrakeButtonFlag[1], "UBB2", line, ""); + extract_value(UniversalBrakeButtonFlag[2], "UBB3", line, ""); + extract_value(LockPipeOn, "LPOn", line, "-1"); + extract_value(LockPipeOff, "LPOff", line, "-1"); + extract_value(HandleUnlock, "HandlePipeUnlockPos", line, "-3"); + extract_value(EmergencyCutsOffHandle, "EmergencyCutsOffHandle", line, ""); + { + std::map compressorpowers{ + {"Main", 0}, + // 1: default, powered by converter, with manual state control + {"Converter", 2}, + {"Engine", 3}, // equivalent of 0, TODO: separate 'main' and 'engine' in the code + {"Coupler1", 4}, // włączana w silnikowym EZT z przodu + {"Coupler2", 5} // włączana w silnikowym EZT z tyłu + }; + auto lookup = compressorpowers.find(extract_value("CompressorPower", line)); + CompressorPower = lookup != compressorpowers.end() ? lookup->second : 1; + } - if( true == extract_value( AirLeakRate, "AirLeakRate", line, "" ) ) { - // the parameter is provided in form of a multiplier, where 1.0 means the default rate of 0.01 - AirLeakRate *= 0.01; - } + if (true == extract_value(AirLeakRate, "AirLeakRate", line, "")) + { + // the parameter is provided in form of a multiplier, where 1.0 means the default rate of 0.01 + AirLeakRate *= 0.01; + } - extract_value( - ReleaserEnabledOnlyAtNoPowerPos, "ReleaserPowerPosLock", line, - ( ( EngineType == TEngineType::DieselEngine ) || ( EngineType == TEngineType::DieselElectric ) ) ? "yes" : "no" ); + extract_value(ReleaserEnabledOnlyAtNoPowerPos, "ReleaserPowerPosLock", line, ((EngineType == TEngineType::DieselEngine) || (EngineType == TEngineType::DieselElectric)) ? "yes" : "no"); - if (MinCompressor_cabB > 0.0) { + if (MinCompressor_cabB > 0.0) + { MinCompressor_cabA = MinCompressor; CabDependentCompressor = true; } - else { + else + { MinCompressor_cabB = MinCompressor; } if (MaxCompressor_cabB > 0.0) @@ -10344,547 +10415,452 @@ void TMoverParameters::LoadFIZ_Brake( std::string const &line ) { MaxCompressor_cabA = MaxCompressor; CabDependentCompressor = true; } - else { + else + { MaxCompressor_cabB = MaxCompressor; } } -void TMoverParameters::LoadFIZ_Doors( std::string const &line ) { +void TMoverParameters::LoadFIZ_Doors(std::string const &line) +{ - std::map doorcontrols { - { "Passenger", control_t::passenger }, - { "AutomaticCtrl", control_t::autonomous }, - { "DriverCtrl", control_t::driver }, - { "Conductor", control_t::conductor }, - { "Mixed", control_t::mixed } - }; - // opening method - { - auto lookup = doorcontrols.find( extract_value( "OpenCtrl", line ) ); - Doors.open_control = - lookup != doorcontrols.end() ? - lookup->second : - control_t::passenger; - } - // closing method - { - auto lookup = doorcontrols.find( extract_value( "CloseCtrl", line ) ); - Doors.close_control = - lookup != doorcontrols.end() ? - lookup->second : - control_t::passenger; - } - // automatic closing conditions - extract_value( Doors.auto_duration, "DoorStayOpen", line, "" ); - extract_value( Doors.auto_velocity, "DoorAutoCloseVel", line, "" ); - extract_value( Doors.auto_include_remote, "DoorAutoCloseRemote", line, "" ); - // operation permit - extract_value( Doors.permit_needed, "DoorNeedPermit", line, "" ); - { - auto permitpresets = Split( extract_value( "DoorPermitList", line ), '|' ); - for( auto const &permit : permitpresets ) { - Doors.permit_presets.emplace_back( std::stoi( permit ) ); - } - if( false == Doors.permit_presets.empty() ) { - // HACK: legacy position indices start from 1, so we deduct 1 to arrive at proper index into the array - extract_value( Doors.permit_preset, "DoorPermitListDefault", line, "1" ); - Doors.permit_preset = - std::min( - Doors.permit_presets.size(), - Doors.permit_preset ) - - 1; - } - } + std::map doorcontrols{ + {"Passenger", control_t::passenger}, {"AutomaticCtrl", control_t::autonomous}, {"DriverCtrl", control_t::driver}, {"Conductor", control_t::conductor}, {"Mixed", control_t::mixed}}; + // opening method + { + auto lookup = doorcontrols.find(extract_value("OpenCtrl", line)); + Doors.open_control = lookup != doorcontrols.end() ? lookup->second : control_t::passenger; + } + // closing method + { + auto lookup = doorcontrols.find(extract_value("CloseCtrl", line)); + Doors.close_control = lookup != doorcontrols.end() ? lookup->second : control_t::passenger; + } + // automatic closing conditions + extract_value(Doors.auto_duration, "DoorStayOpen", line, ""); + extract_value(Doors.auto_velocity, "DoorAutoCloseVel", line, ""); + extract_value(Doors.auto_include_remote, "DoorAutoCloseRemote", line, ""); + // operation permit + extract_value(Doors.permit_needed, "DoorNeedPermit", line, ""); + { + auto permitpresets = Split(extract_value("DoorPermitList", line), '|'); + for (auto const &permit : permitpresets) + { + Doors.permit_presets.emplace_back(std::stoi(permit)); + } + if (false == Doors.permit_presets.empty()) + { + // HACK: legacy position indices start from 1, so we deduct 1 to arrive at proper index into the array + extract_value(Doors.permit_preset, "DoorPermitListDefault", line, "1"); + Doors.permit_preset = std::min(Doors.permit_presets.size(), Doors.permit_preset) - 1; + } + } - extract_value( Doors.open_rate, "OpenSpeed", line, "" ); - extract_value( Doors.open_delay, "DoorOpenDelay", line, "" ); - extract_value( Doors.close_rate, "CloseSpeed", line, "" ); - extract_value( Doors.close_delay, "DoorCloseDelay", line, "" ); - extract_value( Doors.range, "DoorMaxShiftL", line, "" ); - extract_value( Doors.range, "DoorMaxShiftR", line, "" ); - extract_value( Doors.range_out, "DoorMaxShiftPlug", line, "" ); + extract_value(Doors.open_rate, "OpenSpeed", line, ""); + extract_value(Doors.open_delay, "DoorOpenDelay", line, ""); + extract_value(Doors.close_rate, "CloseSpeed", line, ""); + extract_value(Doors.close_delay, "DoorCloseDelay", line, ""); + extract_value(Doors.range, "DoorMaxShiftL", line, ""); + extract_value(Doors.range, "DoorMaxShiftR", line, ""); + extract_value(Doors.range_out, "DoorMaxShiftPlug", line, ""); - std::map doortypes { - { "Shift", 1 }, - { "Rotate", 2 }, - { "Fold", 3 }, - { "Plug", 4 }, - }; - // opening method - { - auto lookup = doortypes.find( extract_value( "DoorOpenMethod", line ) ); - Doors.type = - lookup != doortypes.end() ? - lookup->second : - 2; // default type is plain, rotating door - } + std::map doortypes{ + {"Shift", 1}, + {"Rotate", 2}, + {"Fold", 3}, + {"Plug", 4}, + }; + // opening method + { + auto lookup = doortypes.find(extract_value("DoorOpenMethod", line)); + Doors.type = lookup != doortypes.end() ? lookup->second : 2; // default type is plain, rotating door + } - extract_value( Doors.has_warning, "DoorClosureWarning", line, "" ); - extract_value( Doors.has_autowarning, "DoorClosureWarningAuto", line, "" ); - extract_value( Doors.has_lock, "DoorBlocked", line, "" ); + extract_value(Doors.has_warning, "DoorClosureWarning", line, ""); + extract_value(Doors.has_autowarning, "DoorClosureWarningAuto", line, ""); + extract_value(Doors.has_lock, "DoorBlocked", line, ""); extract_value(Doors.doorLockSpeed, "DoorLockSpeed", line, ""); - { - auto const remotedoorcontrol { - ( Doors.open_control == control_t::driver ) - || ( Doors.open_control == control_t::conductor ) - || ( Doors.open_control == control_t::mixed ) }; + { + auto const remotedoorcontrol{(Doors.open_control == control_t::driver) || (Doors.open_control == control_t::conductor) || (Doors.open_control == control_t::mixed)}; - extract_value( Doors.voltage, "DoorVoltage", line, ( remotedoorcontrol ? "24" : "0" ) ); - } + extract_value(Doors.voltage, "DoorVoltage", line, (remotedoorcontrol ? "24" : "0")); + } - extract_value( Doors.step_rate, "PlatformSpeed", line, "" ); - extract_value( Doors.step_range, "PlatformMaxShift", line, "" ); + extract_value(Doors.step_rate, "PlatformSpeed", line, ""); + extract_value(Doors.step_range, "PlatformMaxShift", line, ""); - std::string platformopenmethod; extract_value( platformopenmethod, "PlatformOpenMethod", line, "" ); - if( platformopenmethod == "Shift" ) { Doors.step_type = 1; } // przesuw + std::string platformopenmethod; + extract_value(platformopenmethod, "PlatformOpenMethod", line, ""); + if (platformopenmethod == "Shift") + { + Doors.step_type = 1; + } // przesuw - extract_value( MirrorMaxShift, "MirrorMaxShift", line, "" ); - extract_value( MirrorVelClose, "MirrorVelClose", line, ""); + extract_value(MirrorMaxShift, "MirrorMaxShift", line, ""); + extract_value(MirrorVelClose, "MirrorVelClose", line, ""); - extract_value( DoorsOpenWithPermitAfter, "DoorOpenWithPermit", line, "" ); - extract_value( DoorsPermitLightBlinking, "DoorsPermitLightBlinking", line, "" ); + extract_value(DoorsOpenWithPermitAfter, "DoorOpenWithPermit", line, ""); + extract_value(DoorsPermitLightBlinking, "DoorsPermitLightBlinking", line, ""); } -void TMoverParameters::LoadFIZ_BuffCoupl( std::string const &line, int const Index ) { +void TMoverParameters::LoadFIZ_BuffCoupl(std::string const &line, int const Index) +{ - TCoupling *coupler; - if( Index == 2 ) { coupler = &Couplers[ 1 ]; } - else { coupler = &Couplers[ 0 ]; } + TCoupling *coupler; + if (Index == 2) + { + coupler = &Couplers[1]; + } + else + { + coupler = &Couplers[0]; + } - std::map couplertypes { - { "Automatic", TCouplerType::Automatic }, - { "Screw", TCouplerType::Screw }, - { "Chain", TCouplerType::Chain }, - { "Bare", TCouplerType::Bare }, - { "Articulated", TCouplerType::Articulated }, - }; - auto lookup = couplertypes.find( extract_value( "CType", line ) ); - coupler->CouplerType = ( - lookup != couplertypes.end() ? - lookup->second : - TCouplerType::NoCoupler ); + std::map couplertypes{ + {"Automatic", TCouplerType::Automatic}, {"Screw", TCouplerType::Screw}, {"Chain", TCouplerType::Chain}, {"Bare", TCouplerType::Bare}, {"Articulated", TCouplerType::Articulated}, + }; + auto lookup = couplertypes.find(extract_value("CType", line)); + coupler->CouplerType = (lookup != couplertypes.end() ? lookup->second : TCouplerType::NoCoupler); - extract_value( coupler->SpringKC, "kC", line, "" ); - extract_value( coupler->DmaxC, "DmaxC", line, "" ); - extract_value( coupler->FmaxC, "FmaxC", line, "" ); - extract_value( coupler->SpringKB, "kB", line, "" ); - extract_value( coupler->DmaxB, "DmaxB", line, "" ); - extract_value( coupler->FmaxB, "FmaxB", line, "" ); - extract_value( coupler->beta, "beta", line, "" ); - extract_value( coupler->AutomaticCouplingFlag, "AutomaticFlag", line, "" ); - extract_value( coupler->AllowedFlag, "AllowedFlag", line, "" ); - if( coupler->AllowedFlag < 0 ) { - coupler->AllowedFlag = ( ( -coupler->AllowedFlag ) | coupling::permanent ); - } - extract_value( coupler->PowerCoupling, "PowerCoupling", line, "" ); - extract_value( coupler->PowerFlag, "PowerFlag", line, "" ); - extract_value( coupler->control_type, "ControlType", line, "" ); + extract_value(coupler->SpringKC, "kC", line, ""); + extract_value(coupler->DmaxC, "DmaxC", line, ""); + extract_value(coupler->FmaxC, "FmaxC", line, ""); + extract_value(coupler->SpringKB, "kB", line, ""); + extract_value(coupler->DmaxB, "DmaxB", line, ""); + extract_value(coupler->FmaxB, "FmaxB", line, ""); + extract_value(coupler->beta, "beta", line, ""); + extract_value(coupler->AutomaticCouplingFlag, "AutomaticFlag", line, ""); + extract_value(coupler->AllowedFlag, "AllowedFlag", line, ""); + if (coupler->AllowedFlag < 0) + { + coupler->AllowedFlag = ((-coupler->AllowedFlag) | coupling::permanent); + } + extract_value(coupler->PowerCoupling, "PowerCoupling", line, ""); + extract_value(coupler->PowerFlag, "PowerFlag", line, ""); + extract_value(coupler->control_type, "ControlType", line, ""); - if( ( coupler->CouplerType != TCouplerType::NoCoupler ) - && ( coupler->CouplerType != TCouplerType::Bare ) - && ( coupler->CouplerType != TCouplerType::Articulated ) ) { + if ((coupler->CouplerType != TCouplerType::NoCoupler) && (coupler->CouplerType != TCouplerType::Bare) && (coupler->CouplerType != TCouplerType::Articulated)) + { - coupler->SpringKC *= 1000; - coupler->FmaxC *= 1000; - coupler->SpringKB *= 1000; - coupler->FmaxB *= 1000; - } - else if( coupler->CouplerType == TCouplerType::Bare ) { + coupler->SpringKC *= 1000; + coupler->FmaxC *= 1000; + coupler->SpringKB *= 1000; + coupler->FmaxB *= 1000; + } + else if (coupler->CouplerType == TCouplerType::Bare) + { - coupler->SpringKC = 50.0 * Mass + Ftmax / 0.05; - coupler->DmaxC = 0.05; - coupler->FmaxC = 100.0 * Mass + 2 * Ftmax; - coupler->SpringKB = 60.0 * Mass + Ftmax / 0.05; - coupler->DmaxB = 0.05; - coupler->FmaxB = 50.0 * Mass + 2.0 * Ftmax; - coupler->beta = 0.3; - } - else if( coupler->CouplerType == TCouplerType::Articulated ) { -/* - coupler->SpringKC = 60.0 * Mass + 1000; - coupler->DmaxC = 0.05; - coupler->FmaxC = 20000000.0 + 2.0 * Ftmax; - coupler->SpringKB = 70.0 * Mass + 1000; - coupler->DmaxB = 0.05; - coupler->FmaxB = 4000000.0 + 2.0 * Ftmax; - coupler->beta = 0.55; -*/ - coupler->SpringKC = 4500 * 1000; - coupler->DmaxC = 0.05; - coupler->FmaxC = 850 * 1000; - coupler->SpringKB = 9200 * 1000; - coupler->DmaxB = 0.05; - coupler->FmaxB = 320 * 1000; - coupler->beta = 0.55; - } + coupler->SpringKC = 50.0 * Mass + Ftmax / 0.05; + coupler->DmaxC = 0.05; + coupler->FmaxC = 100.0 * Mass + 2 * Ftmax; + coupler->SpringKB = 60.0 * Mass + Ftmax / 0.05; + coupler->DmaxB = 0.05; + coupler->FmaxB = 50.0 * Mass + 2.0 * Ftmax; + coupler->beta = 0.3; + } + else if (coupler->CouplerType == TCouplerType::Articulated) + { + /* + coupler->SpringKC = 60.0 * Mass + 1000; + coupler->DmaxC = 0.05; + coupler->FmaxC = 20000000.0 + 2.0 * Ftmax; + coupler->SpringKB = 70.0 * Mass + 1000; + coupler->DmaxB = 0.05; + coupler->FmaxB = 4000000.0 + 2.0 * Ftmax; + coupler->beta = 0.55; + */ + coupler->SpringKC = 4500 * 1000; + coupler->DmaxC = 0.05; + coupler->FmaxC = 850 * 1000; + coupler->SpringKB = 9200 * 1000; + coupler->DmaxB = 0.05; + coupler->FmaxB = 320 * 1000; + coupler->beta = 0.55; + } - if( Index == 0 ) { - // 0 indicates single entry for both couplers - Couplers[ 1 ] = Couplers[ 0 ]; - } + if (Index == 0) + { + // 0 indicates single entry for both couplers + Couplers[1] = Couplers[0]; + } } -void TMoverParameters::LoadFIZ_TurboPos( std::string const &Input ) { +void TMoverParameters::LoadFIZ_TurboPos(std::string const &Input) +{ - extract_value( TurboTest, "TurboPos", Input, "" ); + extract_value(TurboTest, "TurboPos", Input, ""); } -void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) { +void TMoverParameters::LoadFIZ_Cntrl(std::string const &line) +{ - { - std::map brakesystems{ - { "Pneumatic", TBrakeSystem::Pneumatic }, - { "ElectroPneumatic", TBrakeSystem::ElectroPneumatic } - }; - auto lookup = brakesystems.find( extract_value( "BrakeSystem", line ) ); - BrakeSystem = - lookup != brakesystems.end() ? - lookup->second : - TBrakeSystem::Individual; - } - if( BrakeSystem != TBrakeSystem::Individual ) { + { + std::map brakesystems{{"Pneumatic", TBrakeSystem::Pneumatic}, {"ElectroPneumatic", TBrakeSystem::ElectroPneumatic}}; + auto lookup = brakesystems.find(extract_value("BrakeSystem", line)); + BrakeSystem = lookup != brakesystems.end() ? lookup->second : TBrakeSystem::Individual; + } + if (BrakeSystem != TBrakeSystem::Individual) + { - extract_value( BrakeCtrlPosNo, "BCPN", line, "" ); - for( int idx = 0; idx < 4; ++idx ) { + extract_value(BrakeCtrlPosNo, "BCPN", line, ""); + for (int idx = 0; idx < 4; ++idx) + { - extract_value( BrakeDelay[ idx ], "BDelay" + std::to_string( idx + 1 ), line, "" ); - } - // brakedelays, brakedelayflag - { - std::map brakedelays { - { "GPR", bdelay_G + bdelay_P + bdelay_R }, - { "PR", bdelay_P + bdelay_R }, - { "GP", bdelay_G + bdelay_P }, - { "R", bdelay_R }, - { "P", bdelay_P }, - { "G", bdelay_G }, - { "GPR+Mg", bdelay_G + bdelay_P + bdelay_R + bdelay_M }, - { "PR+Mg", bdelay_P + bdelay_R + bdelay_M } - }; - std::map brakedelayflags { - { "R", bdelay_R }, - { "P", bdelay_P }, - { "G", bdelay_G } - }; - std::string brakedelay; - extract_value( brakedelay, "BrakeDelays", line, "" ); - auto lookup = brakedelays.find( brakedelay ); - BrakeDelays = - lookup != brakedelays.end() ? - lookup->second : - 0; - lookup = brakedelayflags.find( brakedelay ); - BrakeDelayFlag = - lookup != brakedelayflags.end() ? - lookup->second : - 0; - } - // brakeopmode - { - std::map brakeopmodes{ - { "PN", bom_PS + bom_PN }, - { "PNEP", bom_PS + bom_PN + bom_EP }, - { "PNEPMED", bom_PS + bom_PN + bom_EP + bom_MED } - }; - auto lookup = brakeopmodes.find( extract_value( "BrakeOpModes", line ) ); - BrakeOpModes = - lookup != brakeopmodes.end() ? - lookup->second : - 0; - } - // brakehandle - { - std::map brakehandles{ - { "FV4a", TBrakeHandle::FV4a }, - { "test", TBrakeHandle::testH }, - { "D2", TBrakeHandle::D2 }, - { "MHZ_EN57", TBrakeHandle::MHZ_EN57 }, - { "MHZ_K5P", TBrakeHandle::MHZ_K5P }, - { "MHZ_K8P", TBrakeHandle::MHZ_K8P }, - { "MHZ_6P", TBrakeHandle::MHZ_6P }, - { "M394", TBrakeHandle::M394 }, - { "Knorr", TBrakeHandle::Knorr }, - { "Westinghouse", TBrakeHandle::West }, - { "FVel6", TBrakeHandle::FVel6 }, - { "FVE408", TBrakeHandle::FVE408 }, - { "St113", TBrakeHandle::St113 } - }; - auto lookup = brakehandles.find( extract_value( "BrakeHandle", line ) ); - BrakeHandle = - lookup != brakehandles.end() ? - lookup->second : - TBrakeHandle::NoHandle; - } - extract_value( Handle_AutomaticOverload, "HAO", line, "" ); - extract_value( Handle_ManualOverload, "HMO", line, "" ); - extract_value( Handle_GenericDoubleParameter1, "HGDP1", line, "" ); - extract_value( Handle_GenericDoubleParameter2, "HGDP2", line, "" ); - extract_value( Handle_OverloadMaxPressure, "OMP", line, "" ); - extract_value( Handle_OverloadPressureDecrease, "OPD", line, "" ); - // brakelochandle - { - std::map locbrakehandles{ - { "FD1", TBrakeHandle::FD1 }, - { "Knorr", TBrakeHandle::Knorr }, - { "Westinghouse", TBrakeHandle::West } - }; - auto lookup = locbrakehandles.find( extract_value( "LocBrakeHandle", line ) ); - BrakeLocHandle = - lookup != locbrakehandles.end() ? - lookup->second : - TBrakeHandle::NoHandle; - } + extract_value(BrakeDelay[idx], "BDelay" + std::to_string(idx + 1), line, ""); + } + // brakedelays, brakedelayflag + { + std::map brakedelays{{"GPR", bdelay_G + bdelay_P + bdelay_R}, + {"PR", bdelay_P + bdelay_R}, + {"GP", bdelay_G + bdelay_P}, + {"R", bdelay_R}, + {"P", bdelay_P}, + {"G", bdelay_G}, + {"GPR+Mg", bdelay_G + bdelay_P + bdelay_R + bdelay_M}, + {"PR+Mg", bdelay_P + bdelay_R + bdelay_M}}; + std::map brakedelayflags{{"R", bdelay_R}, {"P", bdelay_P}, {"G", bdelay_G}}; + std::string brakedelay; + extract_value(brakedelay, "BrakeDelays", line, ""); + auto lookup = brakedelays.find(brakedelay); + BrakeDelays = lookup != brakedelays.end() ? lookup->second : 0; + lookup = brakedelayflags.find(brakedelay); + BrakeDelayFlag = lookup != brakedelayflags.end() ? lookup->second : 0; + } + // brakeopmode + { + std::map brakeopmodes{{"PN", bom_PS + bom_PN}, {"PNEP", bom_PS + bom_PN + bom_EP}, {"PNEPMED", bom_PS + bom_PN + bom_EP + bom_MED}}; + auto lookup = brakeopmodes.find(extract_value("BrakeOpModes", line)); + BrakeOpModes = lookup != brakeopmodes.end() ? lookup->second : 0; + } + // brakehandle + { + std::map brakehandles{ + {"FV4a", TBrakeHandle::FV4a}, {"test", TBrakeHandle::testH}, {"D2", TBrakeHandle::D2}, {"MHZ_EN57", TBrakeHandle::MHZ_EN57}, {"MHZ_K5P", TBrakeHandle::MHZ_K5P}, + {"MHZ_K8P", TBrakeHandle::MHZ_K8P}, {"MHZ_6P", TBrakeHandle::MHZ_6P}, {"M394", TBrakeHandle::M394}, {"Knorr", TBrakeHandle::Knorr}, {"Westinghouse", TBrakeHandle::West}, + {"FVel6", TBrakeHandle::FVel6}, {"FVE408", TBrakeHandle::FVE408}, {"St113", TBrakeHandle::St113}}; + auto lookup = brakehandles.find(extract_value("BrakeHandle", line)); + BrakeHandle = lookup != brakehandles.end() ? lookup->second : TBrakeHandle::NoHandle; + } + extract_value(Handle_AutomaticOverload, "HAO", line, ""); + extract_value(Handle_ManualOverload, "HMO", line, ""); + extract_value(Handle_GenericDoubleParameter1, "HGDP1", line, ""); + extract_value(Handle_GenericDoubleParameter2, "HGDP2", line, ""); + extract_value(Handle_OverloadMaxPressure, "OMP", line, ""); + extract_value(Handle_OverloadPressureDecrease, "OPD", line, ""); + // brakelochandle + { + std::map locbrakehandles{{"FD1", TBrakeHandle::FD1}, {"Knorr", TBrakeHandle::Knorr}, {"Westinghouse", TBrakeHandle::West}}; + auto lookup = locbrakehandles.find(extract_value("LocBrakeHandle", line)); + BrakeLocHandle = lookup != locbrakehandles.end() ? lookup->second : TBrakeHandle::NoHandle; + } - // mbpm - if( true == extract_value( MBPM, "MaxBPMass", line, "" ) ) { - // NOTE: only convert the value from tons to kilograms if the entry is present in the config file - MBPM *= 1000.0; - } + // mbpm + if (true == extract_value(MBPM, "MaxBPMass", line, "")) + { + // NOTE: only convert the value from tons to kilograms if the entry is present in the config file + MBPM *= 1000.0; + } - // asbtype - std::string const asb { ToLower( extract_value( "ASB", line ) ) }; - if( BrakeCtrlPosNo > 0 ) { + // asbtype + std::string const asb{ToLower(extract_value("ASB", line))}; + if (BrakeCtrlPosNo > 0) + { - if( asb == "manual" ) { ASBType = 1; } - else if( asb == "automatic" ) { ASBType = 2; } - else if( asb == "yes") { ASBType = 128; } - } - else { + if (asb == "manual") + { + ASBType = 1; + } + else if (asb == "automatic") + { + ASBType = 2; + } + else if (asb == "yes") + { + ASBType = 128; + } + } + else + { - if( asb == "yes" ) { ASBType = 128; } - } - } // brakesystem != individual + if (asb == "yes") + { + ASBType = 128; + } + } + } // brakesystem != individual - // localbrake - { - std::map localbrakes{ - { "ManualBrake", TLocalBrake::ManualBrake }, - { "PneumaticBrake", TLocalBrake::PneumaticBrake }, - { "HydraulicBrake", TLocalBrake::HydraulicBrake } - }; - auto lookup = localbrakes.find( extract_value( "LocalBrake", line ) ); - LocalBrake = - lookup != localbrakes.end() ? - lookup->second : - TLocalBrake::NoBrake; - } - // mbrake - extract_value( MBrake, "ManualBrake", line, "" ); + // localbrake + { + std::map localbrakes{{"ManualBrake", TLocalBrake::ManualBrake}, {"PneumaticBrake", TLocalBrake::PneumaticBrake}, {"HydraulicBrake", TLocalBrake::HydraulicBrake}}; + auto lookup = localbrakes.find(extract_value("LocalBrake", line)); + LocalBrake = lookup != localbrakes.end() ? lookup->second : TLocalBrake::NoBrake; + } + // mbrake + extract_value(MBrake, "ManualBrake", line, ""); - // maksymalna predkosc dostepna na tarczce predkosciomierza + // maksymalna predkosc dostepna na tarczce predkosciomierza extract_value(maxTachoSpeed, "MaxTachoSpeed", line, ""); - // dynamicbrake - { - std::map dynamicbrakes{ - { "Passive", dbrake_passive }, - { "Switch", dbrake_switch }, - { "Reversal", dbrake_reversal }, - { "Automatic", dbrake_automatic } - }; - auto lookup = dynamicbrakes.find( extract_value( "DynamicBrake", line ) ); - DynamicBrakeType = - lookup != dynamicbrakes.end() ? - lookup->second : - dbrake_none; + // dynamicbrake + { + std::map dynamicbrakes{{"Passive", dbrake_passive}, {"Switch", dbrake_switch}, {"Reversal", dbrake_reversal}, {"Automatic", dbrake_automatic}}; + auto lookup = dynamicbrakes.find(extract_value("DynamicBrake", line)); + DynamicBrakeType = lookup != dynamicbrakes.end() ? lookup->second : dbrake_none; extract_value(DynamicBrakeAmpmeters, "DBAM", line, ""); - } + } - extract_value( MainCtrlPosNo, "MCPN", line, "" ); - extract_value( ScndCtrlPosNo, "SCPN", line, "" ); - extract_value( ScndInMain, "SCIM", line, "" ); - extract_value( MainCtrlMaxDirChangePos, "DirChangeMaxPos", line, "" ); + extract_value(MainCtrlPosNo, "MCPN", line, ""); + extract_value(ScndCtrlPosNo, "SCPN", line, ""); + extract_value(ScndInMain, "SCIM", line, ""); + extract_value(MainCtrlMaxDirChangePos, "DirChangeMaxPos", line, ""); - auto const autorelay { ToLower( extract_value( "AutoRelay", line ) ) }; - if( autorelay == "optional" ) { AutoRelayType = 2; } - else if( autorelay == "yes" ) { AutoRelayType = 1; } - else { AutoRelayType = 0; } + auto const autorelay{ToLower(extract_value("AutoRelay", line))}; + if (autorelay == "optional") + { + AutoRelayType = 2; + } + else if (autorelay == "yes") + { + AutoRelayType = 1; + } + else + { + AutoRelayType = 0; + } - extract_value( CoupledCtrl, "CoupledCtrl", line, "" ); - extract_value( HasCamshaft, "Camshaft", line, "" ); - extract_value( EIMCtrlType, "EIMCtrlType", line, "" ); - EIMCtrlType = clamp( EIMCtrlType, 0, 3 ); - extract_value( LocHandleTimeTraxx, "LocalBrakeTraxx", line, "" ); - extract_value( EIMCtrlAdditionalZeros, "EIMCtrlAddZeros", line, "" ); - extract_value( EIMCtrlEmergency, "EIMCtrlEmergency", line, ""); + extract_value(CoupledCtrl, "CoupledCtrl", line, ""); + extract_value(HasCamshaft, "Camshaft", line, ""); + extract_value(EIMCtrlType, "EIMCtrlType", line, ""); + EIMCtrlType = clamp(EIMCtrlType, 0, 3); + extract_value(LocHandleTimeTraxx, "LocalBrakeTraxx", line, ""); + extract_value(EIMCtrlAdditionalZeros, "EIMCtrlAddZeros", line, ""); + extract_value(EIMCtrlEmergency, "EIMCtrlEmergency", line, ""); - extract_value( ScndS, "ScndS", line, "" ); // brak pozycji rownoleglej przy niskiej nastawie PSR + extract_value(ScndS, "ScndS", line, ""); // brak pozycji rownoleglej przy niskiej nastawie PSR - extract_value( InitialCtrlDelay, "IniCDelay", line, "" ); - extract_value( CtrlDelay, "SCDelay", line, "" ); - CtrlDownDelay = CtrlDelay; //hunter-101012: jesli nie ma SCDDelay; - extract_value( CtrlDownDelay, "SCDDelay", line, "" ); + extract_value(InitialCtrlDelay, "IniCDelay", line, ""); + extract_value(CtrlDelay, "SCDelay", line, ""); + CtrlDownDelay = CtrlDelay; // hunter-101012: jesli nie ma SCDDelay; + extract_value(CtrlDownDelay, "SCDDelay", line, ""); - //hunter-111012: dla siodemek 303E - FastSerialCircuit = - ( ToLower( extract_value( "FSCircuit", line ) ) == "yes" ) ? - 1 : - 0; - extract_value( BackwardsBranchesAllowed, "BackwardsBranchesAllowed", line, "" ); + // hunter-111012: dla siodemek 303E + FastSerialCircuit = (ToLower(extract_value("FSCircuit", line)) == "yes") ? 1 : 0; + extract_value(BackwardsBranchesAllowed, "BackwardsBranchesAllowed", line, ""); - extract_value( AutomaticCabActivation, "AutomaticCabActivation", line, "" ); - extract_value( InactiveCabFlag, "InactiveCabFlag", line, "" ); + extract_value(AutomaticCabActivation, "AutomaticCabActivation", line, ""); + extract_value(InactiveCabFlag, "InactiveCabFlag", line, ""); - extract_value( StopBrakeDecc, "SBD", line, "" ); - extract_value( ReleaseParkingBySpringBrake, "ReleaseParkingBySpringBrake", line, "" ); - extract_value( ReleaseParkingBySpringBrakeWhenDoorIsOpen, "ReleaseParkingBySpringBrakeWhenDoorIsOpen", line, "" ); - extract_value( SpringBrakeCutsOffDrive, "SpringBrakeCutsOffDrive", line, ""); - extract_value( SpringBrakeDriveEmergencyVel, "SpringBrakeDriveEmergencyVel", line, ""); + extract_value(StopBrakeDecc, "SBD", line, ""); + extract_value(ReleaseParkingBySpringBrake, "ReleaseParkingBySpringBrake", line, ""); + extract_value(ReleaseParkingBySpringBrakeWhenDoorIsOpen, "ReleaseParkingBySpringBrakeWhenDoorIsOpen", line, ""); + extract_value(SpringBrakeCutsOffDrive, "SpringBrakeCutsOffDrive", line, ""); + extract_value(SpringBrakeDriveEmergencyVel, "SpringBrakeDriveEmergencyVel", line, ""); - extract_value(HideDirStatusWhenMoving, "HideDirStatusWhenMoving", line, ""); + extract_value(HideDirStatusWhenMoving, "HideDirStatusWhenMoving", line, ""); extract_value(HideDirStatusSpeed, "HideDirStatusSpeed", line, ""); extract_value(isDoubleClickForMeasureNeeded, "DCMB", line, ""); extract_value(DistanceCounterDoublePressPeriod, "DCDPP", line, ""); - extract_value(isBatteryButtonImpulse, "IBTB", line, ""); + extract_value(isBatteryButtonImpulse, "IBTB", line, ""); extract_value(shouldHoldBatteryButton, "SBBBH", line, ""); extract_value(BatteryButtonHoldTime, "BBHT", line, ""); - std::map starts { - { "Disabled", start_t::disabled }, - { "Manual", start_t::manual }, - { "Automatic", start_t::automatic }, - { "Mixed", start_t::manualwithautofallback }, - { "Battery", start_t::battery }, - { "Converter", start_t::converter }, - { "Direction", start_t::direction } }; + std::map starts{{"Disabled", start_t::disabled}, {"Manual", start_t::manual}, {"Automatic", start_t::automatic}, {"Mixed", start_t::manualwithautofallback}, + {"Battery", start_t::battery}, {"Converter", start_t::converter}, {"Direction", start_t::direction}}; - // main circuit - extract_value( MainsInitTime, "MainInitTime", line, "" ); - { - auto lookup = starts.find( extract_value( "MainStart", line ) ); - MainsStart = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // battery - { - auto lookup = starts.find( extract_value( "BatteryStart", line ) ); - BatteryStart = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // converter - { - auto lookup = starts.find( extract_value( "ConverterStart", line ) ); - ConverterStart = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - extract_value( ConverterStartDelay, "ConverterStartDelay", line, "" ); - extract_value( ConverterOverloadRelayOffWhenMainIsOff, "ConverterOverloadWhenMainIsOff", line, ( TrainType == dt_EZT ? "yes" : "no" ) ); - // compressor - { - auto lookup = starts.find( extract_value( "CompressorStart", line ) ); - CompressorStart = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // pantograph compressor - { - auto lookup = starts.find( extract_value( "PantCompressorStart", line ) ); - PantographCompressorStart = - lookup != starts.end() ? - 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, "" ); - // pantographs valve - { - auto lookup = starts.find( extract_value( "PantEPValveStart", line ) ); - PantsValve.start_type = - lookup != starts.end() ? - lookup->second : - start_t::automatic; // legacy code behaviour, there was no pantographs valve - extract_value( PantsValve.spring, "PantEPValveSpring", line, "" ); - } - // pantograph valve configuration - { - auto lookup = starts.find( extract_value( "PantValveStart", line ) ); - auto valvestarttype = - lookup != starts.end() ? - lookup->second : - start_t::manual; - auto valvespring { true }; - extract_value( valvespring, "PantValveSpring", line, "" ); - auto valvesolenoid { true }; - extract_value( valvesolenoid, "PantValveSolenoid", line, "" ); - for( auto &pantograph : Pantographs ) { - pantograph.valve.spring = valvespring; - pantograph.valve.solenoid = valvesolenoid; - pantograph.valve.start_type = valvestarttype; - } - } - // fuel pump - { - auto lookup = starts.find( extract_value( "FuelStart", line ) ); - FuelPump.start_type = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // oil pump - { - auto lookup = starts.find( extract_value( "OilStart", line ) ); - OilPump.start_type = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // water pump - { - auto lookup = starts.find( extract_value( "WaterStart", line ) ); - WaterPump.start_type = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // traction motor fans - { - auto lookup = starts.find( extract_value( "MotorBlowersStart", line ) ); - MotorBlowers[end::front].start_type = - MotorBlowers[end::rear].start_type = - lookup != starts.end() ? - lookup->second : - start_t::manual; - } - // compartment lights - { - auto lookup = starts.find( extract_value( "CompartmentLightsStart", line ) ); - CompartmentLights.start_type = - lookup != starts.end() ? - lookup->second : - start_t::automatic; // legacy behaviour - } - // ground relay - { - auto lookup = starts.find( extract_value( "GroundRelayStart", line ) ); - GroundRelayStart = ( - lookup != starts.end() ? - lookup->second : - ( TrainType == dt_EZT ? - start_t::automatic : - start_t::manual ) ); - } - // converter overload relay - { - auto lookup = starts.find( extract_value( "ConverterOverloadRelayStart", line ) ); - ConverterOverloadRelayStart = ( - lookup != starts.end() ? - lookup->second : - ( TrainType == dt_EZT ? - start_t::converter : // relay activates when converter is switched off - start_t::manual ) ); - } + // main circuit + extract_value(MainsInitTime, "MainInitTime", line, ""); + { + auto lookup = starts.find(extract_value("MainStart", line)); + MainsStart = lookup != starts.end() ? lookup->second : start_t::manual; + } + // battery + { + auto lookup = starts.find(extract_value("BatteryStart", line)); + BatteryStart = lookup != starts.end() ? lookup->second : start_t::manual; + } + // converter + { + auto lookup = starts.find(extract_value("ConverterStart", line)); + ConverterStart = lookup != starts.end() ? lookup->second : start_t::manual; + } + extract_value(ConverterStartDelay, "ConverterStartDelay", line, ""); + extract_value(ConverterOverloadRelayOffWhenMainIsOff, "ConverterOverloadWhenMainIsOff", line, (TrainType == dt_EZT ? "yes" : "no")); + // compressor + { + auto lookup = starts.find(extract_value("CompressorStart", line)); + CompressorStart = lookup != starts.end() ? lookup->second : start_t::manual; + } + // pantograph compressor + { + auto lookup = starts.find(extract_value("PantCompressorStart", line)); + PantographCompressorStart = lookup != starts.end() ? 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, ""); + // pantographs valve + { + auto lookup = starts.find(extract_value("PantEPValveStart", line)); + PantsValve.start_type = lookup != starts.end() ? lookup->second : start_t::automatic; // legacy code behaviour, there was no pantographs valve + extract_value(PantsValve.spring, "PantEPValveSpring", line, ""); + } + // pantograph valve configuration + { + auto lookup = starts.find(extract_value("PantValveStart", line)); + auto valvestarttype = lookup != starts.end() ? lookup->second : start_t::manual; + auto valvespring{true}; + extract_value(valvespring, "PantValveSpring", line, ""); + auto valvesolenoid{true}; + extract_value(valvesolenoid, "PantValveSolenoid", line, ""); + for (auto &pantograph : Pantographs) + { + pantograph.valve.spring = valvespring; + pantograph.valve.solenoid = valvesolenoid; + pantograph.valve.start_type = valvestarttype; + } + } + // fuel pump + { + auto lookup = starts.find(extract_value("FuelStart", line)); + FuelPump.start_type = lookup != starts.end() ? lookup->second : start_t::manual; + } + // oil pump + { + auto lookup = starts.find(extract_value("OilStart", line)); + OilPump.start_type = lookup != starts.end() ? lookup->second : start_t::manual; + } + // water pump + { + auto lookup = starts.find(extract_value("WaterStart", line)); + WaterPump.start_type = lookup != starts.end() ? lookup->second : start_t::manual; + } + // traction motor fans + { + auto lookup = starts.find(extract_value("MotorBlowersStart", line)); + MotorBlowers[end::front].start_type = MotorBlowers[end::rear].start_type = lookup != starts.end() ? lookup->second : start_t::manual; + } + // compartment lights + { + auto lookup = starts.find(extract_value("CompartmentLightsStart", line)); + CompartmentLights.start_type = lookup != starts.end() ? lookup->second : start_t::automatic; // legacy behaviour + } + // ground relay + { + auto lookup = starts.find(extract_value("GroundRelayStart", line)); + GroundRelayStart = (lookup != starts.end() ? lookup->second : (TrainType == dt_EZT ? start_t::automatic : start_t::manual)); + } + // converter overload relay + { + auto lookup = starts.find(extract_value("ConverterOverloadRelayStart", line)); + ConverterOverloadRelayStart = (lookup != starts.end() ? lookup->second : + (TrainType == dt_EZT ? start_t::converter : // relay activates when converter is switched off + start_t::manual)); + } } -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_Vmin, "MED_Vmin", line, "0"); @@ -10898,17 +10874,17 @@ void TMoverParameters::LoadFIZ_Blending(std::string const &line) { extract_value(MED_ED_Delay2, "MED_ScndDelayED", 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_EP_max_Vel, "EP_max_Vel", line, "0"); extract_value(DCEMUED_EP_min_Im, "EP_min_Im", line, "0"); extract_value(DCEMUED_EP_delay, "EP_delay", line, "0"); - } - -void TMoverParameters::LoadFIZ_SpringBrake(std::string const &line) { +void TMoverParameters::LoadFIZ_SpringBrake(std::string const &line) +{ double vol; extract_value(vol, "Volume", line, "1"); @@ -10931,67 +10907,71 @@ void TMoverParameters::LoadFIZ_SpringBrake(std::string const &line) { SpringBrake.IsReady = true; } -void TMoverParameters::LoadFIZ_Light( std::string const &line ) { +void TMoverParameters::LoadFIZ_Light(std::string const &line) +{ - LightPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "Light", line ) ); - LoadFIZ_PowerParamsDecode( LightPowerSource, "L", line ); + LightPowerSource.SourceType = LoadFIZ_SourceDecode(extract_value("Light", line)); + LoadFIZ_PowerParamsDecode(LightPowerSource, "L", line); - AlterLightPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "AlterLight", line ) ); - LoadFIZ_PowerParamsDecode( AlterLightPowerSource, "AlterL", line ); + AlterLightPowerSource.SourceType = LoadFIZ_SourceDecode(extract_value("AlterLight", line)); + LoadFIZ_PowerParamsDecode(AlterLightPowerSource, "AlterL", line); - extract_value( NominalVoltage, "Volt", line, "" ); - extract_value( BatteryVoltage, "LMaxVoltage", line, "" ); - NominalBatteryVoltage = BatteryVoltage; + extract_value(NominalVoltage, "Volt", line, ""); + extract_value(BatteryVoltage, "LMaxVoltage", line, ""); + NominalBatteryVoltage = BatteryVoltage; } -void TMoverParameters::LoadFIZ_Clima( std::string const &line ) { +void TMoverParameters::LoadFIZ_Clima(std::string const &line) +{ - HeatingPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "Heating", line ) ); - LoadFIZ_PowerParamsDecode( HeatingPowerSource, "H", line ); - AlterHeatPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "AlterHeating", line ) ); - LoadFIZ_PowerParamsDecode( AlterHeatPowerSource, "AlterH", line ); + HeatingPowerSource.SourceType = LoadFIZ_SourceDecode(extract_value("Heating", line)); + LoadFIZ_PowerParamsDecode(HeatingPowerSource, "H", line); + AlterHeatPowerSource.SourceType = LoadFIZ_SourceDecode(extract_value("AlterHeating", line)); + LoadFIZ_PowerParamsDecode(AlterHeatPowerSource, "AlterH", line); } -void TMoverParameters::LoadFIZ_Power( std::string const &Line ) { +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; - } + 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; + } - SystemPowerSource.SourceType = LoadFIZ_SourceDecode( extract_value( "SystemPower", Line ) ); - LoadFIZ_PowerParamsDecode( SystemPowerSource, "", Line ); + SystemPowerSource.SourceType = LoadFIZ_SourceDecode(extract_value("SystemPower", Line)); + LoadFIZ_PowerParamsDecode(SystemPowerSource, "", Line); } -void TMoverParameters::LoadFIZ_SpeedControl(std::string const &Line) { +void TMoverParameters::LoadFIZ_SpeedControl(std::string const &Line) +{ // speed control - extract_value( SpeedCtrl, "SpeedCtrl", Line, "" ); - if ((!SpeedCtrl) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo > 0)) //backward compatibility + extract_value(SpeedCtrl, "SpeedCtrl", Line, ""); + if ((!SpeedCtrl) && (EngineType == TEngineType::ElectricInductionMotor) && (ScndCtrlPosNo > 0)) // backward compatibility SpeedCtrl = true; extract_value(SpeedCtrlDelay, "SpeedCtrlDelay", Line, ""); - SpeedCtrlTypeTime = - (extract_value("SpeedCtrlType", Line) == "Time") ? - true : - false; + SpeedCtrlTypeTime = (extract_value("SpeedCtrlType", Line) == "Time") ? true : false; extract_value(SpeedCtrlAutoTurnOffFlag, "SpeedCtrlATOF", Line, ""); auto speedpresets = Split(extract_value("SpeedButtons", Line), '|'); int speed_no = 0; - for (auto const &speed : speedpresets) { + for (auto const &speed : speedpresets) + { SpeedCtrlButtons[speed_no++] = std::stod(speed); - if (speed_no > 9) break; + if (speed_no > 9) + break; } - extract_value( SpeedCtrlUnit.ManualStateOverride, "OverrideManual", Line, ""); - extract_value( SpeedCtrlUnit.BrakeIntervention, "BrakeIntervention", Line, "" ); + extract_value(SpeedCtrlUnit.ManualStateOverride, "OverrideManual", Line, ""); + extract_value(SpeedCtrlUnit.BrakeIntervention, "BrakeIntervention", Line, ""); extract_value(SpeedCtrlUnit.InitialPower, "InitPwr", Line, ""); extract_value(SpeedCtrlUnit.FullPowerVelocity, "MaxPwrVel", Line, ""); extract_value(SpeedCtrlUnit.StartVelocity, "StartVel", Line, ""); @@ -11007,384 +10987,410 @@ void TMoverParameters::LoadFIZ_SpeedControl(std::string const &Line) { extract_value(SpeedCtrlUnit.FactorIpos, "kIpos", Line, ""); extract_value(SpeedCtrlUnit.FactorIneg, "kIneg", Line, ""); extract_value(SpeedCtrlUnit.BrakeInterventionVel, "BrakeIntMaxVel", Line, ""); - extract_value(SpeedCtrlUnit.PowerUpSpeed, "PowerUpSpeed", Line, "" ); - extract_value(SpeedCtrlUnit.PowerDownSpeed, "PowerDownSpeed", Line, "" ); + extract_value(SpeedCtrlUnit.PowerUpSpeed, "PowerUpSpeed", Line, ""); + extract_value(SpeedCtrlUnit.PowerDownSpeed, "PowerDownSpeed", Line, ""); } -void TMoverParameters::LoadFIZ_Engine( std::string const &Input ) { +void TMoverParameters::LoadFIZ_Engine(std::string const &Input) +{ - EngineType = LoadFIZ_EngineDecode( extract_value( "EngineType", Input ) ); + EngineType = LoadFIZ_EngineDecode(extract_value("EngineType", Input)); - std::string transmission = extract_value( "Trans", Input ); - if( false == transmission.empty() ) { - // transmission type. moved here because more than one engine type has this entry - auto ratios = Split( transmission, ':' ); // e.g. 18:79 + std::string transmission = extract_value("Trans", Input); + if (false == transmission.empty()) + { + // transmission type. moved here because more than one engine type has this entry + auto ratios = Split(transmission, ':'); // e.g. 18:79 - if( ratios.size() != 2 ) { - ErrorLog( "Wrong transmition definition: " + transmission ); - } + if (ratios.size() != 2) + { + ErrorLog("Wrong transmition definition: " + transmission); + } - Transmision.NToothM = std::atoi( ratios[0].c_str() ); // ToothM to pierwszy czyli 18 - Transmision.NToothW = std::atoi( ratios[1].c_str() ); // ToothW to drugi parametr czyli 79 + Transmision.NToothM = std::atoi(ratios[0].c_str()); // ToothM to pierwszy czyli 18 + Transmision.NToothW = std::atoi(ratios[1].c_str()); // ToothW to drugi parametr czyli 79 - if( Transmision.NToothM > 0 ) - Transmision.Ratio = static_cast( Transmision.NToothW ) / Transmision.NToothM; - else - Transmision.Ratio = 1.0; + if (Transmision.NToothM > 0) + Transmision.Ratio = static_cast(Transmision.NToothW) / Transmision.NToothM; + else + Transmision.Ratio = 1.0; extract_value(Transmision.Efficiency, "TransEff", Input, ""); - } + } - switch( EngineType ) { + switch (EngineType) + { - case TEngineType::ElectricSeriesMotor: { + case TEngineType::ElectricSeriesMotor: + { - extract_value( NominalVoltage, "Volt", Input, "" ); - extract_value( WindingRes, "WindingRes", Input, "" ); - if( WindingRes == 0.0 ) { + extract_value(NominalVoltage, "Volt", Input, ""); + extract_value(WindingRes, "WindingRes", Input, ""); + if (WindingRes == 0.0) + { - WindingRes = 0.01; - } - extract_value( nmax, "nmax", Input, "" ); - nmax /= 60.0; - break; - } - case TEngineType::WheelsDriven: - case TEngineType::Dumb: { + WindingRes = 0.01; + } + extract_value(nmax, "nmax", Input, ""); + nmax /= 60.0; + break; + } + case TEngineType::WheelsDriven: + case TEngineType::Dumb: + { - extract_value( Ftmax, "Ftmax", Input, "" ); - break; - } - case TEngineType::DieselEngine: { + extract_value(Ftmax, "Ftmax", Input, ""); + break; + } + case TEngineType::DieselEngine: + { - extract_value( dizel_nmin, "nmin", Input, "" ); - 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 - extract_value( nmax, "nmax", Input, "" ); - nmax /= 60.0; - extract_value( dizel_nmax_cutoff, "nmax_cutoff", Input, "0.0" ); - dizel_nmax_cutoff /= 60.0; - extract_value( dizel_nreg_acc, "nreg_acc", Input, ""); - dizel_nreg_acc /= 60.0; - extract_value( dizel_AIM, "AIM", Input, "1.0" ); - extract_value( dizel_RevolutionsDecreaseRate, "RPMDecRate", Input, "" ); - - extract_value(engageupspeed, "EUS", Input, "0.5"); - extract_value(engagedownspeed, "EDS", Input, "0.9"); + extract_value(dizel_nmin, "nmin", Input, ""); + 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 + extract_value(nmax, "nmax", Input, ""); + nmax /= 60.0; + extract_value(dizel_nmax_cutoff, "nmax_cutoff", Input, "0.0"); + dizel_nmax_cutoff /= 60.0; + extract_value(dizel_nreg_acc, "nreg_acc", Input, ""); + dizel_nreg_acc /= 60.0; + extract_value(dizel_AIM, "AIM", Input, "1.0"); + extract_value(dizel_RevolutionsDecreaseRate, "RPMDecRate", Input, ""); - if( true == extract_value( AnPos, "ShuntMode", Input, "" ) ) { - //dodatkowa przekładnia dla SM03 (2Ls150) - ShuntModeAllow = true; - ShuntMode = false; - if( AnPos < 1.0 ) { - //"rozruch wysoki" ma dawać większą siłę - AnPos = 1.0 / AnPos; //im większa liczba, tym wolniej jedzie - } + extract_value(engageupspeed, "EUS", Input, "0.5"); + extract_value(engagedownspeed, "EDS", Input, "0.9"); - } - extract_value(hydro_TC, "IsTC", Input, ""); - if (true == hydro_TC) { - extract_value(hydro_TC_TMMax, "TC_TMMax", Input, ""); - extract_value(hydro_TC_CouplingPoint, "TC_CP", Input, ""); - extract_value(hydro_TC_LockupTorque, "TC_LT", Input, ""); - extract_value(hydro_TC_LockupRate, "TC_LR", Input, ""); - extract_value(hydro_TC_UnlockRate, "TC_ULR", Input, ""); - extract_value(hydro_TC_FillRateInc, "TC_FRI", Input, ""); - extract_value(hydro_TC_FillRateDec, "TC_FRD", Input, ""); - extract_value(hydro_TC_TorqueInIn, "TC_TII", Input, ""); - extract_value(hydro_TC_TorqueInOut, "TC_TIO", Input, ""); - extract_value(hydro_TC_TorqueOutOut, "TC_TOO", Input, ""); - extract_value(hydro_TC_LockupSpeed, "TC_LS", Input, ""); - extract_value(hydro_TC_UnlockSpeed, "TC_ULS", Input, ""); - extract_value(dizel_maxVelANS, "MaxVelANS", Input, ""); - - extract_value(hydro_R, "IsRetarder", Input, ""); - if (true == hydro_R) { - extract_value(hydro_R_Placement, "R_Place", Input, ""); - extract_value(hydro_R_TorqueInIn, "R_TII", Input, ""); - extract_value(hydro_R_MaxTorque, "R_MT", Input, ""); - extract_value(hydro_R_MaxPower, "R_MP", Input, ""); - extract_value(hydro_R_FillRateInc, "R_FRI", Input, ""); - extract_value(hydro_R_FillRateDec, "R_FRD", Input, ""); - extract_value(hydro_R_MinVel, "R_MinVel", Input, ""); - extract_value(hydro_R_EngageVel, "R_EngageVel", Input, ""); - extract_value(hydro_R_Clutch, "R_IsClutch", Input, ""); - extract_value(hydro_R_ClutchSpeed, "R_ClutchSpeed", Input, ""); - extract_value(hydro_R_WithIndividual, "R_WithIndividual", Input, ""); - } - } - break; - } - case TEngineType::DieselElectric: { //youBy - - extract_value( Ftmax, "Ftmax", Input, "" ); - Flat = ( extract_value( "Flat", Input ) == "1" ); - extract_value( Vhyp, "Vhyp", Input, "" ); - Vhyp /= 3.6; - extract_value( Vadd, "Vadd", Input, "" ); - Vadd /= 3.6; - extract_value( PowerCorRatio, "Cr", Input, "" ); - extract_value( RelayType, "RelayType", Input, "" ); - if( extract_value( "ShuntMode", Input ) == "1" ) { - - ShuntModeAllow = true; - ShuntMode = false; - AnPos = 0.0; - ImaxHi = 2; - ImaxLo = 1; - } - extract_value( EngineHeatingRPM, "HeatingRPM", Input, "" ); - extract_value( dizel_AIM, "AIM", Input, "1.25" ); - extract_value( dizel_RevolutionsDecreaseRate, "RPMDecRate", Input, "" ); - break; - } - case TEngineType::ElectricInductionMotor: { - - RVentnmax = 1.0; - extract_value( NominalVoltage, "Volt", Input, "" ); - - extract_value( eimc[ eimc_s_dfic ], "dfic", Input, "" ); - extract_value( eimc[ eimc_s_dfmax ], "dfmax", Input, "" ); - extract_value( eimc[ eimc_s_p ], "p", Input, "" ); - extract_value( eimc[ eimc_s_cfu ], "cfu", Input, "" ); - extract_value( eimc[ eimc_s_cim ], "cim", Input, "" ); - extract_value( eimc[ eimc_s_icif ], "icif", Input, "" ); - extract_value( eimc[ eimc_f_Uzmax ], "Uzmax", Input, "" ); - extract_value( eimc[ eimc_f_Uzh ], "Uzh", Input, "" ); - extract_value( eimc[ eimc_f_DU ], "DU", Input, "" ); - extract_value( eimc[ eimc_f_I0 ], "I0", Input, "" ); - extract_value( eimc[ eimc_f_cfu ], "fcfu", Input, "" ); - extract_value( eimc[ eimc_f_cfuH ], "fcfuH", Input, to_string(eimc[eimc_f_cfu])); - extract_value( eimc[ eimc_p_F0 ], "F0", Input, "" ); - extract_value( eimc[ eimc_p_a1 ], "a1", Input, "" ); - extract_value( eimc[ eimc_p_Pmax ], "Pmax", Input, "" ); - extract_value( eimc[ eimc_p_Fh ], "Fh", Input, "" ); - extract_value( eimc[ eimc_p_Ph ], "Ph", Input, "" ); - extract_value( eimc[ eimc_p_Vh0 ], "Vh0", Input, "" ); - extract_value( eimc[ eimc_p_Vh1 ], "Vh1", Input, "" ); - extract_value( eimc[ eimc_p_Imax ], "Imax", Input, "" ); - extract_value( eimc[ eimc_p_abed ], "abed", Input, "" ); - extract_value( eimc[ eimc_p_eped ], "edep", Input, "" ); - extract_value( EIMCLogForce, "eimclf", Input, "" ); - extract_value( InvertersNo, "InvNo", Input, "" ); - extract_value( InverterControlCouplerFlag, "InvCtrCplFlag", Input, "" ); - extract_value(Imaxrpc, "Imaxrpc", Input, ""); - extract_value(BRVto, "BRVto", Input, ""); - extract_value( Flat, "Flat", Input, ""); - - if (eimc[eimc_p_Pmax] > 0 && Power > 0 && InvertersNo == 0) { - InvertersNo = 1; - } - Inverters.resize(InvertersNo); - /*for (int i = 0; i > InvertersNo; i++) + if (true == extract_value(AnPos, "ShuntMode", Input, "")) + { + // dodatkowa przekładnia dla SM03 (2Ls150) + ShuntModeAllow = true; + ShuntMode = false; + if (AnPos < 1.0) { - inverter x; - Inverters.emplace_back(x); - }*/ - break; - } - default: { - // nothing here - } - } // engine type + //"rozruch wysoki" ma dawać większą siłę + AnPos = 1.0 / AnPos; // im większa liczba, tym wolniej jedzie + } + } + extract_value(hydro_TC, "IsTC", Input, ""); + if (true == hydro_TC) + { + extract_value(hydro_TC_TMMax, "TC_TMMax", Input, ""); + extract_value(hydro_TC_CouplingPoint, "TC_CP", Input, ""); + extract_value(hydro_TC_LockupTorque, "TC_LT", Input, ""); + extract_value(hydro_TC_LockupRate, "TC_LR", Input, ""); + extract_value(hydro_TC_UnlockRate, "TC_ULR", Input, ""); + extract_value(hydro_TC_FillRateInc, "TC_FRI", Input, ""); + extract_value(hydro_TC_FillRateDec, "TC_FRD", Input, ""); + extract_value(hydro_TC_TorqueInIn, "TC_TII", Input, ""); + extract_value(hydro_TC_TorqueInOut, "TC_TIO", Input, ""); + extract_value(hydro_TC_TorqueOutOut, "TC_TOO", Input, ""); + extract_value(hydro_TC_LockupSpeed, "TC_LS", Input, ""); + extract_value(hydro_TC_UnlockSpeed, "TC_ULS", Input, ""); + extract_value(dizel_maxVelANS, "MaxVelANS", Input, ""); - // NOTE: elements shared by both diesel engine variants; crude but, eh - if( ( EngineType == TEngineType::DieselEngine ) - || ( EngineType == TEngineType::DieselElectric ) ) { - // oil pump - extract_value( OilPump.pressure_minimum, "OilMinPressure", Input, "" ); - extract_value( OilPump.pressure_maximum, "OilMaxPressure", Input, "" ); - // engine cooling factore - extract_value( dizel_heat.kw, "HeatKW", Input, "" ); - extract_value( dizel_heat.kv, "HeatKV", Input, "" ); - extract_value( dizel_heat.kfe, "HeatKFE", Input, "" ); - extract_value( dizel_heat.kfs, "HeatKFS", Input, "" ); - extract_value( dizel_heat.kfo, "HeatKFO", Input, "" ); - extract_value( dizel_heat.kfo2, "HeatKFO2", Input, "" ); - // engine cooling systems - extract_value( dizel_heat.water.config.temp_min, "WaterMinTemperature", Input, "" ); - extract_value( dizel_heat.water.config.temp_max, "WaterMaxTemperature", Input, "" ); - extract_value( dizel_heat.water.config.temp_flow, "WaterFlowTemperature", Input, "" ); - extract_value( dizel_heat.water.config.temp_cooling, "WaterCoolingTemperature", Input, "" ); - extract_value( dizel_heat.water.config.shutters, "WaterShutters", Input, "" ); - extract_value( dizel_heat.auxiliary_water_circuit, "WaterAuxCircuit", Input, "" ); - extract_value( dizel_heat.water_aux.config.temp_min, "WaterAuxMinTemperature", Input, "" ); - extract_value( dizel_heat.water_aux.config.temp_max, "WaterAuxMaxTemperature", Input, "" ); - extract_value( dizel_heat.water_aux.config.temp_cooling, "WaterAuxCoolingTemperature", Input, "" ); - extract_value( dizel_heat.water_aux.config.shutters, "WaterAuxShutters", Input, "" ); - extract_value( dizel_heat.oil.config.temp_min, "OilMinTemperature", Input, "" ); - extract_value( dizel_heat.oil.config.temp_max, "OilMaxTemperature", Input, "" ); - extract_value( dizel_heat.engine_max_temp, "EngineMaxTemperature", Input, "" ); - extract_value( dizel_heat.fan_speed, "WaterCoolingFanSpeed", Input, "" ); - // water heater - extract_value( WaterHeater.config.temp_min, "HeaterMinTemperature", Input, "" ); - extract_value( WaterHeater.config.temp_max, "HeaterMaxTemperature", Input, "" ); + extract_value(hydro_R, "IsRetarder", Input, ""); + if (true == hydro_R) + { + extract_value(hydro_R_Placement, "R_Place", Input, ""); + extract_value(hydro_R_TorqueInIn, "R_TII", Input, ""); + extract_value(hydro_R_MaxTorque, "R_MT", Input, ""); + extract_value(hydro_R_MaxPower, "R_MP", Input, ""); + extract_value(hydro_R_FillRateInc, "R_FRI", Input, ""); + extract_value(hydro_R_FillRateDec, "R_FRD", Input, ""); + extract_value(hydro_R_MinVel, "R_MinVel", Input, ""); + extract_value(hydro_R_EngageVel, "R_EngageVel", Input, ""); + extract_value(hydro_R_Clutch, "R_IsClutch", Input, ""); + extract_value(hydro_R_ClutchSpeed, "R_ClutchSpeed", Input, ""); + extract_value(hydro_R_WithIndividual, "R_WithIndividual", Input, ""); + } + } + break; + } + case TEngineType::DieselElectric: + { // youBy + + extract_value(Ftmax, "Ftmax", Input, ""); + Flat = (extract_value("Flat", Input) == "1"); + extract_value(Vhyp, "Vhyp", Input, ""); + Vhyp /= 3.6; + extract_value(Vadd, "Vadd", Input, ""); + Vadd /= 3.6; + extract_value(PowerCorRatio, "Cr", Input, ""); + extract_value(RelayType, "RelayType", Input, ""); + if (extract_value("ShuntMode", Input) == "1") + { + + ShuntModeAllow = true; + ShuntMode = false; + AnPos = 0.0; + ImaxHi = 2; + ImaxLo = 1; + } + extract_value(EngineHeatingRPM, "HeatingRPM", Input, ""); + extract_value(dizel_AIM, "AIM", Input, "1.25"); + extract_value(dizel_RevolutionsDecreaseRate, "RPMDecRate", Input, ""); + break; + } + case TEngineType::ElectricInductionMotor: + { + + RVentnmax = 1.0; + extract_value(NominalVoltage, "Volt", Input, ""); + + extract_value(eimc[eimc_s_dfic], "dfic", Input, ""); + extract_value(eimc[eimc_s_dfmax], "dfmax", Input, ""); + extract_value(eimc[eimc_s_p], "p", Input, ""); + extract_value(eimc[eimc_s_cfu], "cfu", Input, ""); + extract_value(eimc[eimc_s_cim], "cim", Input, ""); + extract_value(eimc[eimc_s_icif], "icif", Input, ""); + extract_value(eimc[eimc_f_Uzmax], "Uzmax", Input, ""); + extract_value(eimc[eimc_f_Uzh], "Uzh", Input, ""); + extract_value(eimc[eimc_f_DU], "DU", Input, ""); + extract_value(eimc[eimc_f_I0], "I0", Input, ""); + extract_value(eimc[eimc_f_cfu], "fcfu", Input, ""); + extract_value(eimc[eimc_f_cfuH], "fcfuH", Input, to_string(eimc[eimc_f_cfu])); + extract_value(eimc[eimc_p_F0], "F0", Input, ""); + extract_value(eimc[eimc_p_a1], "a1", Input, ""); + extract_value(eimc[eimc_p_Pmax], "Pmax", Input, ""); + extract_value(eimc[eimc_p_Fh], "Fh", Input, ""); + extract_value(eimc[eimc_p_Ph], "Ph", Input, ""); + extract_value(eimc[eimc_p_Vh0], "Vh0", Input, ""); + extract_value(eimc[eimc_p_Vh1], "Vh1", Input, ""); + extract_value(eimc[eimc_p_Imax], "Imax", Input, ""); + extract_value(eimc[eimc_p_abed], "abed", Input, ""); + extract_value(eimc[eimc_p_eped], "edep", Input, ""); + extract_value(EIMCLogForce, "eimclf", Input, ""); + extract_value(InvertersNo, "InvNo", Input, ""); + extract_value(InverterControlCouplerFlag, "InvCtrCplFlag", Input, ""); + extract_value(Imaxrpc, "Imaxrpc", Input, ""); + extract_value(BRVto, "BRVto", Input, ""); + extract_value(Flat, "Flat", Input, ""); + + if (eimc[eimc_p_Pmax] > 0 && Power > 0 && InvertersNo == 0) + { + InvertersNo = 1; + } + Inverters.resize(InvertersNo); + /*for (int i = 0; i > InvertersNo; i++) + { + inverter x; + Inverters.emplace_back(x); + }*/ + break; + } + default: + { + // nothing here + } + } // engine type + + // NOTE: elements shared by both diesel engine variants; crude but, eh + if ((EngineType == TEngineType::DieselEngine) || (EngineType == TEngineType::DieselElectric)) + { + // oil pump + extract_value(OilPump.pressure_minimum, "OilMinPressure", Input, ""); + extract_value(OilPump.pressure_maximum, "OilMaxPressure", Input, ""); + // engine cooling factore + extract_value(dizel_heat.kw, "HeatKW", Input, ""); + extract_value(dizel_heat.kv, "HeatKV", Input, ""); + extract_value(dizel_heat.kfe, "HeatKFE", Input, ""); + extract_value(dizel_heat.kfs, "HeatKFS", Input, ""); + extract_value(dizel_heat.kfo, "HeatKFO", Input, ""); + extract_value(dizel_heat.kfo2, "HeatKFO2", Input, ""); + // engine cooling systems + extract_value(dizel_heat.water.config.temp_min, "WaterMinTemperature", Input, ""); + extract_value(dizel_heat.water.config.temp_max, "WaterMaxTemperature", Input, ""); + extract_value(dizel_heat.water.config.temp_flow, "WaterFlowTemperature", Input, ""); + extract_value(dizel_heat.water.config.temp_cooling, "WaterCoolingTemperature", Input, ""); + extract_value(dizel_heat.water.config.shutters, "WaterShutters", Input, ""); + extract_value(dizel_heat.auxiliary_water_circuit, "WaterAuxCircuit", Input, ""); + extract_value(dizel_heat.water_aux.config.temp_min, "WaterAuxMinTemperature", Input, ""); + extract_value(dizel_heat.water_aux.config.temp_max, "WaterAuxMaxTemperature", Input, ""); + extract_value(dizel_heat.water_aux.config.temp_cooling, "WaterAuxCoolingTemperature", Input, ""); + extract_value(dizel_heat.water_aux.config.shutters, "WaterAuxShutters", Input, ""); + extract_value(dizel_heat.oil.config.temp_min, "OilMinTemperature", Input, ""); + extract_value(dizel_heat.oil.config.temp_max, "OilMaxTemperature", Input, ""); + extract_value(dizel_heat.engine_max_temp, "EngineMaxTemperature", Input, ""); + extract_value(dizel_heat.fan_speed, "WaterCoolingFanSpeed", Input, ""); + // water heater + extract_value(WaterHeater.config.temp_min, "HeaterMinTemperature", Input, ""); + extract_value(WaterHeater.config.temp_max, "HeaterMaxTemperature", Input, ""); float pf; - extract_value( pf, "NominalCoolingPower", Input, "1235"); + extract_value(pf, "NominalCoolingPower", Input, "1235"); dizel_heat.powerfactor = 1235 / pf; - } + } - // traction motors - extract_value( MotorBlowers[ end::front ].speed, "MotorBlowersSpeed", Input, "" ); - extract_value( MotorBlowers[ end::front ].sustain_time, "MotorBlowersSustainTime", Input, "" ); - extract_value( MotorBlowers[ end::front ].min_start_velocity, "MotorBlowersStartVelocity", Input, "" ); - MotorBlowers[ end::rear ] = MotorBlowers[ end::front ]; - // pressure switch - extract_value( HasControlPressureSwitch, "PressureSwitch", Input, ( TrainType != dt_EZT ? "yes" : "no" ) ); + // traction motors + extract_value(MotorBlowers[end::front].speed, "MotorBlowersSpeed", Input, ""); + extract_value(MotorBlowers[end::front].sustain_time, "MotorBlowersSustainTime", Input, ""); + extract_value(MotorBlowers[end::front].min_start_velocity, "MotorBlowersStartVelocity", Input, ""); + MotorBlowers[end::rear] = MotorBlowers[end::front]; + // pressure switch + extract_value(HasControlPressureSwitch, "PressureSwitch", Input, (TrainType != dt_EZT ? "yes" : "no")); } -void TMoverParameters::LoadFIZ_Switches( std::string const &Input ) { +void TMoverParameters::LoadFIZ_Switches(std::string const &Input) +{ - extract_value( PantSwitchType, "Pantograph", Input, "" ); - extract_value( ConvSwitchType, "Converter", Input, "" ); - extract_value( StLinSwitchType, "MotorConnectors", Input, "" ); - // because people can't make up their minds whether it's "impulse" or "Impulse"... - PantSwitchType = ToLower( PantSwitchType ); - ConvSwitchType = ToLower( ConvSwitchType ); - StLinSwitchType = ToLower( StLinSwitchType ); - // universal reset buttons assignments - extract_value( UniversalResetButtonFlag[ 0 ], "RelayResetButton1", Input, "" ); - extract_value( UniversalResetButtonFlag[ 1 ], "RelayResetButton2", Input, "" ); - extract_value( UniversalResetButtonFlag[ 2 ], "RelayResetButton3", Input, "" ); + extract_value(PantSwitchType, "Pantograph", Input, ""); + extract_value(ConvSwitchType, "Converter", Input, ""); + extract_value(StLinSwitchType, "MotorConnectors", Input, ""); + // because people can't make up their minds whether it's "impulse" or "Impulse"... + PantSwitchType = ToLower(PantSwitchType); + ConvSwitchType = ToLower(ConvSwitchType); + StLinSwitchType = ToLower(StLinSwitchType); + // universal reset buttons assignments + extract_value(UniversalResetButtonFlag[0], "RelayResetButton1", Input, ""); + extract_value(UniversalResetButtonFlag[1], "RelayResetButton2", Input, ""); + extract_value(UniversalResetButtonFlag[2], "RelayResetButton3", Input, ""); extract_value(enableModernDimmer, "ModernDimmer", Input, ""); - // pantograph presets - { - auto &presets { PantsPreset.first }; - extract_value( presets, "PantographPresets", Input, "0|1|3|2" ); - presets.erase( - std::remove( std::begin( presets ), std::end( presets ), '|' ), - std::end( presets ) ); - } + // pantograph presets + { + auto &presets{PantsPreset.first}; + extract_value(presets, "PantographPresets", Input, "0|1|3|2"); + presets.erase(std::remove(std::begin(presets), std::end(presets), '|'), std::end(presets)); + } } -void TMoverParameters::LoadFIZ_MotorParamTable( std::string const &Input ) { +void TMoverParameters::LoadFIZ_MotorParamTable(std::string const &Input) +{ - switch( EngineType ) { + switch (EngineType) + { - case TEngineType::DieselEngine: { - - extract_value( dizel_minVelfullengage, "minVelfullengage", Input, "" ); - extract_value( dizel_engageDia, "engageDia", Input, "" ); - extract_value( dizel_engageMaxForce, "engageMaxForce", Input, "" ); - extract_value( dizel_engagefriction, "engagefriction", Input, "" ); - break; - } - default: { - // nothing here - } - } + case TEngineType::DieselEngine: + { + + extract_value(dizel_minVelfullengage, "minVelfullengage", Input, ""); + extract_value(dizel_engageDia, "engageDia", Input, ""); + extract_value(dizel_engageMaxForce, "engageMaxForce", Input, ""); + extract_value(dizel_engagefriction, "engagefriction", Input, ""); + break; + } + default: + { + // nothing here + } + } } -void TMoverParameters::LoadFIZ_Circuit( std::string const &Input ) { +void TMoverParameters::LoadFIZ_Circuit(std::string const &Input) +{ - extract_value( CircuitRes, "CircuitRes", Input, "" ); - extract_value( IminLo, "IminLo", Input, "" ); - extract_value( IminHi, "IminHi", Input, "" ); - extract_value( ImaxLo, "ImaxLo", Input, "" ); - extract_value( ImaxHi, "ImaxHi", Input, "" ); - Imin = IminLo; - Imax = ImaxLo; - extract_value( TUHEX_Sum, "TUHEX_Sum", Input, "" ); - extract_value( TUHEX_Diff, "TUHEX_Diff", Input, "" ); - extract_value( TUHEX_MaxIw, "TUHEX_MaxIw", Input, "" ); - extract_value( TUHEX_MinIw, "TUHEX_MinIw", Input, "" ); - extract_value( TUHEX_Sum1, "TUHEX_Sum1", Input, ""); - extract_value( TUHEX_Sum2, "TUHEX_Sum2", Input, "" ); - extract_value( TUHEX_Sum3, "TUHEX_Sum3", Input, "" ); - extract_value( TUHEX_Stages, "TUHEX_Stages", Input, "0" ); - + extract_value(CircuitRes, "CircuitRes", Input, ""); + extract_value(IminLo, "IminLo", Input, ""); + extract_value(IminHi, "IminHi", Input, ""); + extract_value(ImaxLo, "ImaxLo", Input, ""); + extract_value(ImaxHi, "ImaxHi", Input, ""); + Imin = IminLo; + Imax = ImaxLo; + extract_value(TUHEX_Sum, "TUHEX_Sum", Input, ""); + extract_value(TUHEX_Diff, "TUHEX_Diff", Input, ""); + extract_value(TUHEX_MaxIw, "TUHEX_MaxIw", Input, ""); + extract_value(TUHEX_MinIw, "TUHEX_MinIw", Input, ""); + extract_value(TUHEX_Sum1, "TUHEX_Sum1", Input, ""); + extract_value(TUHEX_Sum2, "TUHEX_Sum2", Input, ""); + extract_value(TUHEX_Sum3, "TUHEX_Sum3", Input, ""); + extract_value(TUHEX_Stages, "TUHEX_Stages", Input, "0"); } -void TMoverParameters::LoadFIZ_AI( std::string const &Input ) { +void TMoverParameters::LoadFIZ_AI(std::string const &Input) +{ - extract_value( AIHintPantstate, "Pantstate", Input, "" ); - extract_value( AIHintPantUpIfIdle, "IdlePantUp", Input, "" ); - extract_value( AIHintLocalBrakeAccFactor, "LocalBrakeAccFactor", Input, "" ); - + extract_value(AIHintPantstate, "Pantstate", Input, ""); + extract_value(AIHintPantUpIfIdle, "IdlePantUp", Input, ""); + extract_value(AIHintLocalBrakeAccFactor, "LocalBrakeAccFactor", Input, ""); } -void TMoverParameters::LoadFIZ_RList( std::string const &Input ) { +void TMoverParameters::LoadFIZ_RList(std::string const &Input) +{ - extract_value( RlistSize, "Size", Input, "" ); + extract_value(RlistSize, "Size", Input, ""); - auto const venttype { ToLower( extract_value( "RVent", Input ) ) }; - if( venttype == "automatic" ) { - - RVentType = 2; - } - else { + auto const venttype{ToLower(extract_value("RVent", Input))}; + if (venttype == "automatic") + { - RVentType = ( - venttype == "yes" ? - 1 : - 0 ); - } + RVentType = 2; + } + else + { - if( RVentType > 0 ) { + RVentType = (venttype == "yes" ? 1 : 0); + } - extract_value( RVentnmax, "RVentnmax", Input, "" ); - RVentnmax /= 60.0; - extract_value( RVentCutOff, "RVentCutOff", Input, "" ); - } - extract_value( RVentMinI, "RVentMinI", Input, "" ); - extract_value( RVentSpeed, "RVentSpeed", Input, "" ); - extract_value( DynamicBrakeRes, "DynBrakeRes", Input, ""); - extract_value( DynamicBrakeRes1, "DynBrakeRes1", Input, ""); - extract_value( DynamicBrakeRes2, "DynBrakeRes2", Input, ""); + if (RVentType > 0) + { + + extract_value(RVentnmax, "RVentnmax", Input, ""); + RVentnmax /= 60.0; + extract_value(RVentCutOff, "RVentCutOff", Input, ""); + } + extract_value(RVentMinI, "RVentMinI", Input, ""); + extract_value(RVentSpeed, "RVentSpeed", Input, ""); + extract_value(DynamicBrakeRes, "DynBrakeRes", Input, ""); + extract_value(DynamicBrakeRes1, "DynBrakeRes1", Input, ""); + extract_value(DynamicBrakeRes2, "DynBrakeRes2", Input, ""); } -void TMoverParameters::LoadFIZ_UCList(std::string const &Input) { - - extract_value( UniCtrlListSize, "Size", Input, "" ); - extract_value( UniCtrlIntegratedBrakeCtrl, "IntegratedBrake", Input, "" ); - extract_value( UniCtrlIntegratedLocalBrakeCtrl, "IntegratedLocBrake", Input, ""); - extract_value( UniCtrlIntegratedBrakePNCtrl, "IntegratedBrakePN", Input, "" ); +void TMoverParameters::LoadFIZ_UCList(std::string const &Input) +{ + extract_value(UniCtrlListSize, "Size", Input, ""); + extract_value(UniCtrlIntegratedBrakeCtrl, "IntegratedBrake", Input, ""); + extract_value(UniCtrlIntegratedLocalBrakeCtrl, "IntegratedLocBrake", Input, ""); + extract_value(UniCtrlIntegratedBrakePNCtrl, "IntegratedBrakePN", Input, ""); } -void TMoverParameters::LoadFIZ_DList( std::string const &Input ) { +void TMoverParameters::LoadFIZ_DList(std::string const &Input) +{ - extract_value( dizel_Mmax, "Mmax", Input, "" ); - extract_value( dizel_nMmax, "nMmax", Input, "" ); - extract_value( dizel_Mnmax, "Mnmax", Input, "" ); - extract_value( dizel_nmax, "nmax", Input, "" ); - extract_value( dizel_nominalfill, "nominalfill", Input, "" ); - extract_value( dizel_Mstand, "Mstand", Input, "" ); - extract_value( dizel_NominalFuelConsumptionRate, "NomFuelConsRate", Input, ""); + extract_value(dizel_Mmax, "Mmax", Input, ""); + extract_value(dizel_nMmax, "nMmax", Input, ""); + extract_value(dizel_Mnmax, "Mnmax", Input, ""); + extract_value(dizel_nmax, "nmax", Input, ""); + extract_value(dizel_nominalfill, "nominalfill", Input, ""); + extract_value(dizel_Mstand, "Mstand", Input, ""); + extract_value(dizel_NominalFuelConsumptionRate, "NomFuelConsRate", Input, ""); - if( dizel_nMmax == dizel_nmax ) { - // HACK: guard against cases where nMmax == nmax, leading to division by 0 in momentum calculation - dizel_nMmax = dizel_nmax - 1.0 / 60.0; - } + if (dizel_nMmax == dizel_nmax) + { + // HACK: guard against cases where nMmax == nmax, leading to division by 0 in momentum calculation + dizel_nMmax = dizel_nmax - 1.0 / 60.0; + } - //Calculation of fuel consumption coefficient for futher calculation - double dizel_max_power = dizel_nmax * (dizel_Mnmax - dizel_Mstand) * M_PI * 2 * 0.001; //power in kW - double dizel_max_energy = dizel_max_power; //energy per one hour in kWh is equal to power in kW times 1 h - double fuel_density = 850; //g/l + // Calculation of fuel consumption coefficient for futher calculation + double dizel_max_power = dizel_nmax * (dizel_Mnmax - dizel_Mstand) * M_PI * 2 * 0.001; // power in kW + double dizel_max_energy = dizel_max_power; // energy per one hour in kWh is equal to power in kW times 1 h + double fuel_density = 850; // g/l dizel_FuelConsumption = dizel_NominalFuelConsumptionRate * dizel_max_energy / fuel_density / dizel_nmax; } -void TMoverParameters::LoadFIZ_FFList( std::string const &Input ) { - extract_value( FFListSize, "Size", Input, "" ); +void TMoverParameters::LoadFIZ_FFList(std::string const &Input) +{ + extract_value(FFListSize, "Size", Input, ""); } -void TMoverParameters::LoadFIZ_FFEDList( std::string const &Input ) { - extract_value( FFEDListSize, "Size", Input, "" ); +void TMoverParameters::LoadFIZ_FFEDList(std::string const &Input) +{ + extract_value(FFEDListSize, "Size", Input, ""); } -void TMoverParameters::LoadFIZ_WiperList(std::string const &Input) +void TMoverParameters::LoadFIZ_WiperList(std::string const &Input) { extract_value(WiperListSize, "Size", Input, ""); extract_value(WiperAngle, "Angle", Input, ""); @@ -11393,188 +11399,182 @@ void TMoverParameters::LoadFIZ_WiperList(std::string const &Input) void TMoverParameters::LoadFIZ_DimmerList(std::string const &Input) { - //extract_value(modernWpierListSize, "Size", Input, ""); + // extract_value(modernWpierListSize, "Size", Input, ""); extract_value(modernDimmerCanCycle, "Cycle", Input, ""); extract_value(modernDimmerDefaultPosition, "DefaultPos", Input, ""); } -void TMoverParameters::LoadFIZ_LightsList( std::string const &Input ) { +void TMoverParameters::LoadFIZ_LightsList(std::string const &Input) +{ - extract_value( LightsPosNo, "Size", Input, "" ); - extract_value( LightsWrap, "Wrap", Input, "" ); - extract_value( LightsDefPos, "Default", Input, "" ); + extract_value(LightsPosNo, "Size", Input, ""); + extract_value(LightsWrap, "Wrap", Input, ""); + extract_value(LightsDefPos, "Default", Input, ""); } -void TMoverParameters::LoadFIZ_CompressorList(std::string const &Input) { +void TMoverParameters::LoadFIZ_CompressorList(std::string const &Input) +{ - extract_value( CompressorListPosNo, "Size", Input, "" ); - extract_value( CompressorListWrap, "Wrap", Input, "" ); - extract_value( CompressorListDefPos, "Default", Input, "" ); + extract_value(CompressorListPosNo, "Size", Input, ""); + extract_value(CompressorListWrap, "Wrap", Input, ""); + extract_value(CompressorListDefPos, "Default", Input, ""); } -void TMoverParameters::LoadFIZ_PowerParamsDecode( TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Line ) { +void TMoverParameters::LoadFIZ_PowerParamsDecode(TPowerParameters &Powerparameters, std::string const Prefix, std::string const &Line) +{ - switch( Powerparameters.SourceType ) { + switch (Powerparameters.SourceType) + { - case TPowerSource::NotDefined: - case TPowerSource::InternalSource: { - - Powerparameters.PowerType = LoadFIZ_PowerDecode( extract_value( Prefix + "PowerType", Line ) ); - break; - } - case TPowerSource::Transducer: { - - extract_value( Powerparameters.Transducer.InputVoltage, Prefix + "TransducerInputV", Line, "" ); - break; - } - case TPowerSource::Generator: { - // prime mover for the generator - auto &generatorparameters { Powerparameters.EngineGenerator }; + case TPowerSource::NotDefined: + case TPowerSource::InternalSource: + { - 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: { + Powerparameters.PowerType = LoadFIZ_PowerDecode(extract_value(Prefix + "PowerType", Line)); + break; + } + case TPowerSource::Transducer: + { - extract_value( Powerparameters.RAccumulator.MaxCapacity, Prefix + "Cap", Line, "" ); - Powerparameters.RAccumulator.RechargeSource = LoadFIZ_SourceDecode( extract_value( Prefix + "RS", Line ) ); - break; - } - case TPowerSource::CurrentCollector: { + extract_value(Powerparameters.Transducer.InputVoltage, Prefix + "TransducerInputV", Line, ""); + break; + } + case TPowerSource::Generator: + { + // prime mover for the generator + auto &generatorparameters{Powerparameters.EngineGenerator}; - auto &collectorparameters = Powerparameters.CollectorParameters; + 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: + { - collectorparameters = TCurrentCollector { 0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, 0 }; - - std::string PantType = ""; - extract_value(PantType, "PantType", Line, ""); - if (PantType == "AKP_4E") - collectorparameters.PantographType = TPantType::AKP_4E; - if (PantType.size() >= 3 && PantType.compare(0, 3, "DSA") == 0) - collectorparameters.PantographType = TPantType::DSAx; - if (PantType == "EC160" || PantType == "EC200") - collectorparameters.PantographType = TPantType::EC160_200; - if (PantType == "WBL85") - collectorparameters.PantographType = TPantType::WBL85; + extract_value(Powerparameters.RAccumulator.MaxCapacity, Prefix + "Cap", Line, ""); + Powerparameters.RAccumulator.RechargeSource = LoadFIZ_SourceDecode(extract_value(Prefix + "RS", Line)); + break; + } + case TPowerSource::CurrentCollector: + { - extract_value( collectorparameters.CollectorsNo, "CollectorsNo", Line, "" ); - extract_value( collectorparameters.MinH, "MinH", Line, "" ); - extract_value( collectorparameters.MaxH, "MaxH", Line, "" ); - extract_value( collectorparameters.CSW, "CSW", Line, "" ); //szerokość części roboczej - extract_value( collectorparameters.MaxV, "MaxVoltage", Line, "" ); - extract_value( collectorparameters.OVP, "OverVoltProt", Line, "" ); //przekaźnik nadnapięciowy - //napięcie rozłączające WS - collectorparameters.MinV = 0.5 * collectorparameters.MaxV; //gdyby parametr nie podany - extract_value( collectorparameters.MinV, "MinV", Line, "" ); - //napięcie wymagane do załączenia WS - collectorparameters.InsetV = 0.6 * collectorparameters.MaxV; //gdyby parametr nie podany - extract_value( collectorparameters.InsetV, "InsetV", Line, "" ); - //ciśnienie rozłączające WS - extract_value( collectorparameters.MinPress, "MinPress", Line, "3.5" ); //domyślnie 2 bary do załączenia WS - //maksymalne ciśnienie za reduktorem -// collectorparameters.MaxPress = 5.0 + 0.001 * ( Random( 50 ) - Random( 50 ) ); - extract_value( collectorparameters.MaxPress, "MaxPress", Line, "5.0" ); - extract_value( collectorparameters.FakePower, "FakePower", Line, "" ); - if (extract_value( collectorparameters.PhysicalLayout, "PhysicalLayout", Line, "3" )) - collectorparameters.CollectorsNo = std::min(collectorparameters.PhysicalLayout, 2); - break; - } - case TPowerSource::PowerCable: { + auto &collectorparameters = Powerparameters.CollectorParameters; - Powerparameters.RPowerCable.PowerTrans = LoadFIZ_PowerDecode( extract_value( Prefix + "PowerTrans", Line ) ); - if( Powerparameters.RPowerCable.PowerTrans == TPowerType::SteamPower ) { + collectorparameters = TCurrentCollector{0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, 0}; - extract_value( Powerparameters.RPowerCable.SteamPressure, Prefix + "SteamPress", Line, "" ); - } - break; - } - case TPowerSource::Heater: { - //jeszcze nie skonczone! - break; - } - default: - ; // nothing here - } + std::string PantType = ""; + extract_value(PantType, "PantType", Line, ""); + if (PantType == "AKP_4E") + collectorparameters.PantographType = TPantType::AKP_4E; + if (PantType.size() >= 3 && PantType.compare(0, 3, "DSA") == 0) + collectorparameters.PantographType = TPantType::DSAx; + if (PantType == "EC160" || PantType == "EC200") + collectorparameters.PantographType = TPantType::EC160_200; + if (PantType == "WBL85") + collectorparameters.PantographType = TPantType::WBL85; - if( ( Powerparameters.SourceType != TPowerSource::Heater ) - && ( Powerparameters.SourceType != TPowerSource::InternalSource ) ) { + extract_value(collectorparameters.CollectorsNo, "CollectorsNo", Line, ""); + extract_value(collectorparameters.MinH, "MinH", Line, ""); + extract_value(collectorparameters.MaxH, "MaxH", Line, ""); + extract_value(collectorparameters.CSW, "CSW", Line, ""); // szerokość części roboczej + extract_value(collectorparameters.MaxV, "MaxVoltage", Line, ""); + extract_value(collectorparameters.OVP, "OverVoltProt", Line, ""); // przekaźnik nadnapięciowy + // napięcie rozłączające WS + collectorparameters.MinV = 0.5 * collectorparameters.MaxV; // gdyby parametr nie podany + extract_value(collectorparameters.MinV, "MinV", Line, ""); + // napięcie wymagane do załączenia WS + collectorparameters.InsetV = 0.6 * collectorparameters.MaxV; // gdyby parametr nie podany + extract_value(collectorparameters.InsetV, "InsetV", Line, ""); + // ciśnienie rozłączające WS + extract_value(collectorparameters.MinPress, "MinPress", Line, "3.5"); // domyślnie 2 bary do załączenia WS + // maksymalne ciśnienie za reduktorem + // collectorparameters.MaxPress = 5.0 + 0.001 * ( Random( 50 ) - Random( 50 ) ); + extract_value(collectorparameters.MaxPress, "MaxPress", Line, "5.0"); + extract_value(collectorparameters.FakePower, "FakePower", Line, ""); + if (extract_value(collectorparameters.PhysicalLayout, "PhysicalLayout", Line, "3")) + collectorparameters.CollectorsNo = std::min(collectorparameters.PhysicalLayout, 2); + break; + } + case TPowerSource::PowerCable: + { + Powerparameters.RPowerCable.PowerTrans = LoadFIZ_PowerDecode(extract_value(Prefix + "PowerTrans", Line)); + if (Powerparameters.RPowerCable.PowerTrans == TPowerType::SteamPower) + { - extract_value( Powerparameters.MaxVoltage, Prefix + "MaxVoltage", Line, "" ); - extract_value( Powerparameters.MaxCurrent, Prefix + "MaxCurrent", Line, "" ); - extract_value( Powerparameters.IntR, Prefix + "IntR", Line, "" ); - } + extract_value(Powerparameters.RPowerCable.SteamPressure, Prefix + "SteamPress", Line, ""); + } + break; + } + case TPowerSource::Heater: + { + // jeszcze nie skonczone! + break; + } + default:; // nothing here + } + + if ((Powerparameters.SourceType != TPowerSource::Heater) && (Powerparameters.SourceType != TPowerSource::InternalSource)) + { + + extract_value(Powerparameters.MaxVoltage, Prefix + "MaxVoltage", Line, ""); + extract_value(Powerparameters.MaxCurrent, Prefix + "MaxCurrent", Line, ""); + extract_value(Powerparameters.IntR, Prefix + "IntR", Line, ""); + } } -TPowerType TMoverParameters::LoadFIZ_PowerDecode( std::string const &Power ) { +TPowerType TMoverParameters::LoadFIZ_PowerDecode(std::string const &Power) +{ - std::map powertypes{ - { "BioPower", TPowerType::BioPower }, - { "MechPower", TPowerType::MechPower }, - { "ElectricPower", TPowerType::ElectricPower }, - { "SteamPower", TPowerType::SteamPower } - }; - auto lookup = powertypes.find( Power ); - return - lookup != powertypes.end() ? - lookup->second : - TPowerType::NoPower; + std::map powertypes{ + {"BioPower", TPowerType::BioPower}, {"MechPower", TPowerType::MechPower}, {"ElectricPower", TPowerType::ElectricPower}, {"SteamPower", TPowerType::SteamPower}}; + auto lookup = powertypes.find(Power); + return lookup != powertypes.end() ? lookup->second : TPowerType::NoPower; } -TPowerSource TMoverParameters::LoadFIZ_SourceDecode( std::string const &Source ) { +TPowerSource TMoverParameters::LoadFIZ_SourceDecode(std::string const &Source) +{ - std::map powersources{ - { "Transducer", TPowerSource::Transducer }, - { "Generator", TPowerSource::Generator }, - { "Accu", TPowerSource::Accumulator }, // legacy compatibility leftover. TODO: check if we can get rid of it - { "Accumulator", TPowerSource::Accumulator }, - { "CurrentCollector", TPowerSource::CurrentCollector }, - { "PowerCable", TPowerSource::PowerCable }, - { "Heater", TPowerSource::Heater }, - { "Internal", TPowerSource::InternalSource }, - { "Main", TPowerSource::Main } - }; - auto lookup = powersources.find( Source ); - return - lookup != powersources.end() ? - lookup->second : - TPowerSource::NotDefined; + std::map powersources{{"Transducer", TPowerSource::Transducer}, {"Generator", TPowerSource::Generator}, + {"Accu", TPowerSource::Accumulator}, // legacy compatibility leftover. TODO: check if we can get rid of it + {"Accumulator", TPowerSource::Accumulator}, {"CurrentCollector", TPowerSource::CurrentCollector}, + {"PowerCable", TPowerSource::PowerCable}, {"Heater", TPowerSource::Heater}, + {"Internal", TPowerSource::InternalSource}, {"Main", TPowerSource::Main}}; + auto lookup = powersources.find(Source); + return lookup != powersources.end() ? lookup->second : TPowerSource::NotDefined; } -TEngineType TMoverParameters::LoadFIZ_EngineDecode( std::string const &Engine ) { +TEngineType TMoverParameters::LoadFIZ_EngineDecode(std::string const &Engine) +{ - std::map enginetypes { - { "ElectricSeriesMotor", TEngineType::ElectricSeriesMotor }, - { "DieselEngine", TEngineType::DieselEngine }, - { "SteamEngine", TEngineType::SteamEngine }, - { "WheelsDriven", TEngineType::WheelsDriven }, - { "Dumb", TEngineType::Dumb }, - { "DieselElectric", TEngineType::DieselElectric }, - { "DumbDE", TEngineType::DieselElectric }, - { "ElectricInductionMotor", TEngineType::ElectricInductionMotor }, - { "Main", TEngineType::Main } - }; - auto lookup = enginetypes.find( Engine ); - return - lookup != enginetypes.end() ? - lookup->second : - TEngineType::None; + std::map enginetypes{{"ElectricSeriesMotor", TEngineType::ElectricSeriesMotor}, + {"DieselEngine", TEngineType::DieselEngine}, + {"SteamEngine", TEngineType::SteamEngine}, + {"WheelsDriven", TEngineType::WheelsDriven}, + {"Dumb", TEngineType::Dumb}, + {"DieselElectric", TEngineType::DieselElectric}, + {"DumbDE", TEngineType::DieselElectric}, + {"ElectricInductionMotor", TEngineType::ElectricInductionMotor}, + {"Main", TEngineType::Main}}; + auto lookup = enginetypes.find(Engine); + return lookup != enginetypes.end() ? lookup->second : TEngineType::None; } // ************************************************************************************************* @@ -11589,320 +11589,327 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) AutoRelayFlag = (AutoRelayType == 1); - if( NominalBatteryVoltage == 0.0 ) { - BatteryStart = start_t::disabled; - } + if (NominalBatteryVoltage == 0.0) + { + BatteryStart = start_t::disabled; + } Sand = SandCapacity; - // NOTE: for diesel-powered vehicles we automatically convert legacy "main" power source to more accurate "engine" - if( ( CompressorPower == 0 ) - && ( ( EngineType == TEngineType::DieselEngine ) - || ( EngineType == TEngineType::DieselElectric ) ) ) { - CompressorPower = 3; - } + // NOTE: for diesel-powered vehicles we automatically convert legacy "main" power source to more accurate "engine" + if ((CompressorPower == 0) && ((EngineType == TEngineType::DieselEngine) || (EngineType == TEngineType::DieselElectric))) + { + CompressorPower = 3; + } // WriteLog("aa = " + AxleArangement + " " + std::string( Pos("o", AxleArangement)) ); - if( ( contains( AxleArangement, "o" ) ) && ( EngineType == TEngineType::ElectricSeriesMotor ) ) { - // test poprawnosci ilosci osi indywidualnie napedzanych - OK = ( ( RList[ 1 ].Bn * RList[ 1 ].Mn ) == NPoweredAxles ); - // WriteLogSS("aa ok", BoolToYN(OK)); - } + if ((contains(AxleArangement, "o")) && (EngineType == TEngineType::ElectricSeriesMotor)) + { + // test poprawnosci ilosci osi indywidualnie napedzanych + OK = ((RList[1].Bn * RList[1].Mn) == NPoweredAxles); + // WriteLogSS("aa ok", BoolToYN(OK)); + } if (BrakeSystem == TBrakeSystem::Individual) if (BrakeSubsystem != TBrakeSubSystem::ss_None) OK = false; //! - if( ( BrakeVVolume == 0 ) && ( MaxBrakePress[ 3 ] > 0 ) && ( BrakeSystem != TBrakeSystem::Individual ) ) { - BrakeVVolume = - MaxBrakePress[ 3 ] / - ( 5.0 - MaxBrakePress[ 3 ] ) * ( BrakeCylRadius * BrakeCylRadius * BrakeCylDist * BrakeCylNo * M_PI ) * 1000; - } - if( BrakeVVolume == 0.0 ) { - BrakeVVolume = 0.01; - } + if ((BrakeVVolume == 0) && (MaxBrakePress[3] > 0) && (BrakeSystem != TBrakeSystem::Individual)) + { + BrakeVVolume = MaxBrakePress[3] / (5.0 - MaxBrakePress[3]) * (BrakeCylRadius * BrakeCylRadius * BrakeCylDist * BrakeCylNo * M_PI) * 1000; + } + if (BrakeVVolume == 0.0) + { + BrakeVVolume = 0.01; + } // WriteLog("BVV = " + FloatToStr(BrakeVVolume)); - - switch( BrakeValve ) { - case TBrakeValve::W: - case TBrakeValve::K: - { - WriteLog( "XBT W, K" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - if( MBPM < 2 ) // jesli przystawka wazaca - Hamulec->SetLP( 0, MaxBrakePress[ 3 ], 0 ); - else - Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); - break; - } - case TBrakeValve::KE: - { - WriteLog( "XBT WKE" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - Hamulec->SetRM( RapidMult ); - if( MBPM < 2 ) // jesli przystawka wazaca - Hamulec->SetLP( 0, MaxBrakePress[ 3 ], 0 ); - else - Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); - break; - } - case TBrakeValve::NESt3: - case TBrakeValve::ESt3: - case TBrakeValve::ESt3AL2: - case TBrakeValve::ESt4: - { - WriteLog( "XBT NESt3, ESt3, ESt3AL2, ESt4" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - static_cast( Hamulec.get() )->SetSize( BrakeValveSize, BrakeValveParams ); - if( MBPM < 2 ) // jesli przystawka wazaca - Hamulec->SetLP( 0, MaxBrakePress[ 3 ], 0 ); - else - Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); - break; - } - case TBrakeValve::LSt: - { - WriteLog( "XBT LSt" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - Hamulec->SetRM( RapidMult ); - break; - } - case TBrakeValve::EStED: - { - WriteLog( "XBT EStED" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - Hamulec->SetRM( RapidMult ); - if( MBPM < 2 ) { - //jesli przystawka wazaca - Hamulec->SetLP( 0, MaxBrakePress[ 3 ], 0 ); - } - else { - Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); - } - break; - } - case TBrakeValve::EP2: - { - WriteLog( "XBT EP2" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - Hamulec->SetLP( Mass, MBPM, MaxBrakePress[ 1 ] ); - break; - } - case TBrakeValve::EP1: + switch (BrakeValve) + { + case TBrakeValve::W: + case TBrakeValve::K: + { + WriteLog("XBT W, K"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + if (MBPM < 2) // jesli przystawka wazaca + Hamulec->SetLP(0, MaxBrakePress[3], 0); + else + Hamulec->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case TBrakeValve::KE: + { + WriteLog("XBT WKE"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + Hamulec->SetRM(RapidMult); + if (MBPM < 2) // jesli przystawka wazaca + Hamulec->SetLP(0, MaxBrakePress[3], 0); + else + Hamulec->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case TBrakeValve::NESt3: + case TBrakeValve::ESt3: + case TBrakeValve::ESt3AL2: + case TBrakeValve::ESt4: + { + WriteLog("XBT NESt3, ESt3, ESt3AL2, ESt4"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + static_cast(Hamulec.get())->SetSize(BrakeValveSize, BrakeValveParams); + if (MBPM < 2) // jesli przystawka wazaca + Hamulec->SetLP(0, MaxBrakePress[3], 0); + else + Hamulec->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case TBrakeValve::LSt: + { + WriteLog("XBT LSt"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + Hamulec->SetRM(RapidMult); + break; + } + case TBrakeValve::EStED: + { + WriteLog("XBT EStED"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + Hamulec->SetRM(RapidMult); + if (MBPM < 2) { - WriteLog("XBT EP1"); - Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); - Hamulec->SetLP( Mass, MBPM, MaxBrakePress[1] ); - Hamulec->SetRM( RapidMult ); - break; + // jesli przystawka wazaca + Hamulec->SetLP(0, MaxBrakePress[3], 0); } - case TBrakeValve::CV1: - { - WriteLog( "XBT CV1" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - break; - } - case TBrakeValve::CV1_L_TR: - { - WriteLog( "XBT CV1_L_T" ); - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - break; - } - default: - Hamulec = std::make_shared( MaxBrakePress[ 3 ], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA ); - } + else + { + Hamulec->SetLP(Mass, MBPM, MaxBrakePress[1]); + } + break; + } + case TBrakeValve::EP2: + { + WriteLog("XBT EP2"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + Hamulec->SetLP(Mass, MBPM, MaxBrakePress[1]); + break; + } + case TBrakeValve::EP1: + { + WriteLog("XBT EP1"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + Hamulec->SetLP(Mass, MBPM, MaxBrakePress[1]); + Hamulec->SetRM(RapidMult); + break; + } + case TBrakeValve::CV1: + { + WriteLog("XBT CV1"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + break; + } + case TBrakeValve::CV1_L_TR: + { + WriteLog("XBT CV1_L_T"); + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + break; + } + default: + Hamulec = std::make_shared(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA); + } - Hamulec->SetASBP( MaxBrakePress[ 4 ] ); - Hamulec->SetRV( RapidVel ); + Hamulec->SetASBP(MaxBrakePress[4]); + Hamulec->SetRV(RapidVel); - switch( BrakeHandle ) { - case TBrakeHandle::FV4a: - Handle = std::make_shared(); - break; - case TBrakeHandle::MHZ_EN57: - case TBrakeHandle::MHZ_K8P: - Handle = std::make_shared(); - break; - case TBrakeHandle::FVel6: - Handle = std::make_shared(); - break; - case TBrakeHandle::FVE408: - Handle = std::make_shared(); - break; - case TBrakeHandle::testH: - Handle = std::make_shared(); - break; - case TBrakeHandle::M394: - Handle = std::make_shared(); - break; - case TBrakeHandle::Knorr: - Handle = std::make_shared(); - break; - case TBrakeHandle::St113: - Handle = std::make_shared(); - break; - case TBrakeHandle::MHZ_K5P: - Handle = std::make_shared(); - break; - case TBrakeHandle::MHZ_6P: - Handle = std::make_shared(); - break; - default: - Handle = std::make_shared(); - } + switch (BrakeHandle) + { + case TBrakeHandle::FV4a: + Handle = std::make_shared(); + break; + case TBrakeHandle::MHZ_EN57: + case TBrakeHandle::MHZ_K8P: + Handle = std::make_shared(); + break; + case TBrakeHandle::FVel6: + Handle = std::make_shared(); + break; + case TBrakeHandle::FVE408: + Handle = std::make_shared(); + break; + case TBrakeHandle::testH: + Handle = std::make_shared(); + break; + case TBrakeHandle::M394: + Handle = std::make_shared(); + break; + case TBrakeHandle::Knorr: + Handle = std::make_shared(); + break; + case TBrakeHandle::St113: + Handle = std::make_shared(); + break; + case TBrakeHandle::MHZ_K5P: + Handle = std::make_shared(); + break; + case TBrakeHandle::MHZ_6P: + Handle = std::make_shared(); + break; + default: + Handle = std::make_shared(); + } Handle->SetParams(Handle_AutomaticOverload, Handle_ManualOverload, Handle_GenericDoubleParameter1, Handle_GenericDoubleParameter2, Handle_OverloadMaxPressure, Handle_OverloadPressureDecrease); - switch( BrakeLocHandle ) { - case TBrakeHandle::FD1: - { - LocHandle = std::make_shared(); - LocHandle->Init( MaxBrakePress[ 0 ] ); - if( TrainType == dt_EZT ) { + switch (BrakeLocHandle) + { + case TBrakeHandle::FD1: + { + LocHandle = std::make_shared(); + LocHandle->Init(MaxBrakePress[0]); + if (TrainType == dt_EZT) + { - dynamic_cast(LocHandle.get())->SetSpeed( 3.5 ); - } - break; - } - case TBrakeHandle::Knorr: - { - LocHandle = std::make_shared(); - LocHandle->Init( MaxBrakePress[ 0 ] ); - break; - } - default: - LocHandle = std::make_shared(); - } + dynamic_cast(LocHandle.get())->SetSpeed(3.5); + } + break; + } + case TBrakeHandle::Knorr: + { + LocHandle = std::make_shared(); + LocHandle->Init(MaxBrakePress[0]); + break; + } + default: + LocHandle = std::make_shared(); + } - if ( ( true == TestFlag( BrakeDelays, bdelay_G ) ) - && ( ( false == TestFlag(BrakeDelays, bdelay_R ) ) - || ( Power > 1.0 ) ) ) // ustalanie srednicy przewodu glownego (lokomotywa lub napędowy + if ((true == TestFlag(BrakeDelays, bdelay_G)) && ((false == TestFlag(BrakeDelays, bdelay_R)) || (Power > 1.0))) // ustalanie srednicy przewodu glownego (lokomotywa lub napędowy Spg = 0.792; else Spg = 0.507; - // WriteLog("SPG = " + FloatToStr(Spg)); + // WriteLog("SPG = " + FloatToStr(Spg)); - Pipe = std::make_shared(); - Pipe2 = std::make_shared(); // zabezpieczenie, bo sie PG wywala... :( - Pipe->CreateCap( ( std::max( Dim.L, 14.0 ) + 0.5 ) * Spg * 1 ); // dlugosc x przekroj x odejscia i takie tam - Pipe2->CreateCap( ( std::max( Dim.L, 14.0 ) + 0.5 ) * Spg * 1 ); + Pipe = std::make_shared(); + Pipe2 = std::make_shared(); // zabezpieczenie, bo sie PG wywala... :( + Pipe->CreateCap((std::max(Dim.L, 14.0) + 0.5) * Spg * 1); // dlugosc x przekroj x odejscia i takie tam + Pipe2->CreateCap((std::max(Dim.L, 14.0) + 0.5) * Spg * 1); if (!SpringBrake.Cylinder) { SpringBrake.Cylinder = std::make_shared(); SpringBrake.Cylinder->CreateCap(1); } - if( LightsPosNo > 0 ) - LightsPos = LightsDefPos; + if (LightsPosNo > 0) + LightsPos = LightsDefPos; - // set default wiper switch position + // set default wiper switch position wiperSwitchPos = WiperDefaultPos; if (CompressorListPosNo > 0) CompressorListPos = CompressorListDefPos; - // 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; - } + // 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 - { - WriteLog( "Ready to depart" ); - CompressedVolume = VeselVolume * MinCompressor * ( 9.8 ) / 10.0; - ScndPipePress = ( - VeselVolume > 0.0 ? CompressedVolume / VeselVolume : - ( Couplers[ end::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 : - ( Couplers[ end::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.0 : - 0.0 ); - PipePress = CntrlPipePress; - BrakePress = 0.0; - LocalBrakePosA = 0.0; - if( CabActive == 0 ) - BrakeCtrlPos = static_cast( Handle->GetPos( bh_NP ) ); - else - BrakeCtrlPos = static_cast( Handle->GetPos( bh_RP ) ); -/* - // NOTE: disabled and left up to the driver, if there's any - MainSwitch( false ); - PantFront( true ); - PantRear( true ); - MainSwitch( true ); -*/ - DirActive = 0; // Dir; //nastawnik kierunkowy - musi być ustawiane osobno! - DirAbsolute = DirActive * CabActive; // kierunek jazdy względem sprzęgów - LimPipePress = CntrlPipePress; + // checking ready flag + // to dac potem do init + if (ReadyFlag) // gotowy do drogi + { + WriteLog("Ready to depart"); + CompressedVolume = VeselVolume * MinCompressor * (9.8) / 10.0; + ScndPipePress = (VeselVolume > 0.0 ? CompressedVolume / VeselVolume : + (Couplers[end::front].AllowedFlag & coupling::mainhose) != 0 ? 5.0 : + (Couplers[end::rear].AllowedFlag & coupling::mainhose) != 0 ? 5.0 : + 0.0); + PipePress = CntrlPipePress; + BrakePress = 0.0; + LocalBrakePosA = 0.0; + if (CabActive == 0) + BrakeCtrlPos = static_cast(Handle->GetPos(bh_NP)); + else + BrakeCtrlPos = static_cast(Handle->GetPos(bh_RP)); + /* + // NOTE: disabled and left up to the driver, if there's any + MainSwitch( false ); + PantFront( true ); + PantRear( true ); + MainSwitch( true ); + */ + DirActive = 0; // Dir; //nastawnik kierunkowy - musi być ustawiane osobno! + DirAbsolute = DirActive * CabActive; // kierunek jazdy względem sprzęgów + LimPipePress = CntrlPipePress; - Battery = ( BatteryStart != start_t::disabled ); - } - else { // zahamowany} - WriteLog( "Braked" ); - Volume = BrakeVVolume * MaxBrakePress[ 3 ]; - CompressedVolume = VeselVolume * MinCompressor * 0.55; -/* - ScndPipePress = 5.1; -*/ - ScndPipePress = ( - VeselVolume > 0.0 ? CompressedVolume / VeselVolume : - ( Couplers[ end::front ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 : - ( Couplers[ end::rear ].AllowedFlag & coupling::mainhose ) != 0 ? 5.1 : - 0.0 ); - PipePress = LowPipePress; - PipeBrakePress = MaxBrakePress[ 3 ] * 0.5; - BrakePress = MaxBrakePress[ 3 ] * 0.5; - LocalBrakePosA = 0.0; - BrakeCtrlPos = static_cast( Handle->GetPos( bh_NP ) ); - LimPipePress = LowPipePress; - if( ( LocalBrake == TLocalBrake::ManualBrake ) - || ( MBrake == true ) ) { - IncManualBrakeLevel( ManualBrakePosNo ); - } - if( SpringBrake.MaxBrakeForce > 0.0 ) { - SpringBrake.Activate = true; - } - } + Battery = (BatteryStart != start_t::disabled); + } + else + { // zahamowany} + WriteLog("Braked"); + Volume = BrakeVVolume * MaxBrakePress[3]; + CompressedVolume = VeselVolume * MinCompressor * 0.55; + /* + ScndPipePress = 5.1; + */ + ScndPipePress = (VeselVolume > 0.0 ? CompressedVolume / VeselVolume : + (Couplers[end::front].AllowedFlag & coupling::mainhose) != 0 ? 5.1 : + (Couplers[end::rear].AllowedFlag & coupling::mainhose) != 0 ? 5.1 : + 0.0); + PipePress = LowPipePress; + PipeBrakePress = MaxBrakePress[3] * 0.5; + BrakePress = MaxBrakePress[3] * 0.5; + LocalBrakePosA = 0.0; + BrakeCtrlPos = static_cast(Handle->GetPos(bh_NP)); + LimPipePress = LowPipePress; + if ((LocalBrake == TLocalBrake::ManualBrake) || (MBrake == true)) + { + IncManualBrakeLevel(ManualBrakePosNo); + } + if (SpringBrake.MaxBrakeForce > 0.0) + { + SpringBrake.Activate = true; + } + } - ActFlowSpeed = 0.0; - BrakeCtrlPosR = BrakeCtrlPos; + ActFlowSpeed = 0.0; + BrakeCtrlPosR = BrakeCtrlPos; - if( BrakeLocHandle == TBrakeHandle::Knorr ) - LocalBrakePosA = 0.5; + if (BrakeLocHandle == TBrakeHandle::Knorr) + LocalBrakePosA = 0.5; - Pipe->CreatePress( PipePress ); - Pipe2->CreatePress( ScndPipePress ); - Pipe->Act(); - Pipe2->Act(); + Pipe->CreatePress(PipePress); + Pipe2->CreatePress(ScndPipePress); + Pipe->Act(); + Pipe2->Act(); - EqvtPipePress = PipePress; + EqvtPipePress = PipePress; - Handle->Init( PipePress ); + Handle->Init(PipePress); - ComputeConstans(); + ComputeConstans(); - if( LoadFlag > 0 ) { + if (LoadFlag > 0) + { - if( LoadAmount < MaxLoad * 0.45 ) { - IncBrakeMult(); - IncBrakeMult(); - DecBrakeMult(); // TODO: przeinesiono do mover.cpp - if( LoadAmount < MaxLoad * 0.35 ) - DecBrakeMult(); - } - else { - IncBrakeMult(); // TODO: przeinesiono do mover.cpp - if( LoadAmount >= MaxLoad * 0.55 ) - IncBrakeMult(); - } - } + if (LoadAmount < MaxLoad * 0.45) + { + IncBrakeMult(); + IncBrakeMult(); + DecBrakeMult(); // TODO: przeinesiono do mover.cpp + if (LoadAmount < MaxLoad * 0.35) + DecBrakeMult(); + } + else + { + IncBrakeMult(); // TODO: przeinesiono do mover.cpp + if (LoadAmount >= MaxLoad * 0.55) + IncBrakeMult(); + } + } // taki mini automat - powinno byc ladnie dobrze :) BrakeDelayFlag = bdelay_P; @@ -11910,18 +11917,18 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) BrakeDelayFlag = bdelay_G; if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G))) BrakeDelayFlag = bdelay_R; -/* -// disabled, as test mode is used in specific situations and not really a default - if (BrakeOpModes & bom_PS) - BrakeOpModeFlag = bom_PS; - else -*/ - BrakeOpModeFlag = bom_PN; + /* + // disabled, as test mode is used in specific situations and not really a default + if (BrakeOpModes & bom_PS) + BrakeOpModeFlag = bom_PS; + else + */ + BrakeOpModeFlag = bom_PN; // yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)% - int DefBrakeTable[8] = { 15, 4, 25, 25, 13, 3, 12, 2 }; + int DefBrakeTable[8] = {15, 4, 25, 25, 13, 3, 12, 2}; - for( b = 1; b < 4; b++ ) + for (b = 1; b < 4; b++) { if (BrakeDelay[b] == 0) BrakeDelay[b] = DefBrakeTable[b]; @@ -11929,27 +11936,31 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) } Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag); -/* - ScndPipePress = Compressor; -*/ + /* + ScndPipePress = Compressor; + */ // WriteLogSS("OK=", BoolTo10(OK)); // WriteLog(""); - if( EIMCtrlType == 3 ) { - for( auto idx = 0; idx < MainCtrlPosNo; ++idx ) { - if( UniCtrlList[ idx ].MaxCtrlVal > 0.0 ) { - UniCtrlNoPowerPos = std::max( 0, ( idx - 1 ) ); - break; - } - } - } - - // security system - // by default place the magnet in the vehicle centre - if( SecuritySystem.MagnetLocation == 0 ) { - SecuritySystem.MagnetLocation = Dim.L / 2 - 0.5; - } - SecuritySystem.MagnetLocation = clamp( SecuritySystem.MagnetLocation, 0.0, Dim.L ); + if (EIMCtrlType == 3) + { + for (auto idx = 0; idx < MainCtrlPosNo; ++idx) + { + if (UniCtrlList[idx].MaxCtrlVal > 0.0) + { + UniCtrlNoPowerPos = std::max(0, (idx - 1)); + break; + } + } + } + + // security system + // by default place the magnet in the vehicle centre + if (SecuritySystem.MagnetLocation == 0) + { + SecuritySystem.MagnetLocation = Dim.L / 2 - 0.5; + } + SecuritySystem.MagnetLocation = clamp(SecuritySystem.MagnetLocation, 0.0, Dim.L); return OK; } @@ -11958,16 +11969,15 @@ bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir) // Q: 20160714 // Wstawia komendę z parametrem, od sprzęgu i w lokalizacji do pojazdu // ************************************************************************************************* -void TMoverParameters::PutCommand(std::string NewCommand, double NewValue1, double NewValue2, - const TLocation &NewLocation) +void TMoverParameters::PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation) { - CommandLast = NewCommand; // zapamiętanie komendy + CommandLast = NewCommand; // zapamiętanie komendy - CommandIn.Command = NewCommand; - CommandIn.Value1 = NewValue1; - CommandIn.Value2 = NewValue2; - CommandIn.Location = NewLocation; - // czy uruchomic tu RunInternalCommand? nie wiem + CommandIn.Command = NewCommand; + CommandIn.Value1 = NewValue1; + CommandIn.Value2 = NewValue2; + CommandIn.Location = NewLocation; + // czy uruchomic tu RunInternalCommand? nie wiem } // ************************************************************************************************* @@ -11976,8 +11986,8 @@ void TMoverParameters::PutCommand(std::string NewCommand, double NewValue1, doub // ************************************************************************************************* double TMoverParameters::GetExternalCommand(std::string &Command) { - Command = CommandOut; - return ValueOut; + Command = CommandOut; + return ValueOut; } // ************************************************************************************************* @@ -11986,55 +11996,56 @@ double TMoverParameters::GetExternalCommand(std::string &Command) // ************************************************************************************************* bool TMoverParameters::SetInternalCommand(std::string NewCommand, double NewValue1, double NewValue2, int const Couplertype) { - bool SIC; - if( ( CommandIn.Command == NewCommand ) - && ( CommandIn.Value1 == NewValue1 ) - && ( CommandIn.Value2 == NewValue2 ) - && ( CommandIn.Coupling == Couplertype ) ) - SIC = false; - else - { - CommandIn.Command = NewCommand; - CommandIn.Value1 = NewValue1; - CommandIn.Value2 = NewValue2; - CommandIn.Coupling = Couplertype; - SIC = true; - LastLoadChangeTime = 0; // zerowanie czasu (roz)ładowania - } + bool SIC; + if ((CommandIn.Command == NewCommand) && (CommandIn.Value1 == NewValue1) && (CommandIn.Value2 == NewValue2) && (CommandIn.Coupling == Couplertype)) + SIC = false; + else + { + CommandIn.Command = NewCommand; + CommandIn.Value1 = NewValue1; + CommandIn.Value2 = NewValue2; + CommandIn.Coupling = Couplertype; + SIC = true; + LastLoadChangeTime = 0; // zerowanie czasu (roz)ładowania + } - return SIC; + return SIC; } // ************************************************************************************************* // Q: 20160714 // wysyłanie komendy w kierunku dir (1=przód, -1=tył) do kolejnego pojazdu (jednego) // ************************************************************************************************* -bool TMoverParameters::SendCtrlToNext( std::string const CtrlCommand, double const ctrlvalue, double const dir, int const Couplertype ) { - bool OK; - int d; // numer sprzęgu w kierunku którego wysyłamy +bool TMoverParameters::SendCtrlToNext(std::string const CtrlCommand, double const ctrlvalue, double const dir, int const Couplertype) +{ + bool OK; + int d; // numer sprzęgu w kierunku którego wysyłamy - // Ra: był problem z propagacją, jeśli w składzie jest pojazd wstawiony odwrotnie - // Ra: problem jest również, jeśli AI będzie na końcu składu - OK = true; // ( dir != 0 ); // experimentally disabled - d = ( 1 + static_cast(Sign( dir )) ) / 2; // dir=-1=>d=0, dir=1=>d=1 - wysyłanie tylko w tył - if( OK ) { - // musi być wybrana niezerowa kabina - if( ( Couplers[ d ].Connected != nullptr ) - && ( TestFlag( Couplers[ d ].CouplingFlag, Couplertype ) ) ) { + // Ra: był problem z propagacją, jeśli w składzie jest pojazd wstawiony odwrotnie + // Ra: problem jest również, jeśli AI będzie na końcu składu + OK = true; // ( dir != 0 ); // experimentally disabled + d = (1 + static_cast(Sign(dir))) / 2; // dir=-1=>d=0, dir=1=>d=1 - wysyłanie tylko w tył + if (OK) + { + // musi być wybrana niezerowa kabina + if ((Couplers[d].Connected != nullptr) && (TestFlag(Couplers[d].CouplingFlag, Couplertype))) + { - if( Couplers[ d ].ConnectedNr != d ) { - // jeśli ten nastpęny jest zgodny z aktualnym - if( Couplers[ d ].Connected->SetInternalCommand( CtrlCommand, ctrlvalue, dir, Couplertype ) ) - OK = ( Couplers[ d ].Connected->RunInternalCommand() && OK ); // tu jest rekurencja - } - else { - // jeśli następny jest ustawiony przeciwnie, zmieniamy kierunek - if( Couplers[ d ].Connected->SetInternalCommand( CtrlCommand, ctrlvalue, -dir, Couplertype ) ) - OK = ( Couplers[ d ].Connected->RunInternalCommand() && OK ); // tu jest rekurencja - } - } - } - return OK; + if (Couplers[d].ConnectedNr != d) + { + // jeśli ten nastpęny jest zgodny z aktualnym + if (Couplers[d].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, dir, Couplertype)) + OK = (Couplers[d].Connected->RunInternalCommand() && OK); // tu jest rekurencja + } + else + { + // jeśli następny jest ustawiony przeciwnie, zmieniamy kierunek + if (Couplers[d].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, -dir, Couplertype)) + OK = (Couplers[d].Connected->RunInternalCommand() && OK); // tu jest rekurencja + } + } + } + return OK; } // ************************************************************************************************* @@ -12048,31 +12059,34 @@ bool TMoverParameters::SendCtrlToNext( std::string const CtrlCommand, double con // Komenda musi być zdefiniowana tutaj, a jeśli się wywołuje funkcję, to ona nie może // sama przesyłać do kolejnych pojazdów. Należy też się zastanowić, czy dla uzyskania // jakiejś zmiany (np. IncMainCtrl) lepiej wywołać funkcję, czy od razu wysłać komendę. -bool TMoverParameters::RunCommand( std::string Command, double CValue1, double CValue2, int const Couplertype ) +bool TMoverParameters::RunCommand(std::string Command, double CValue1, double CValue2, int const Couplertype) { - bool OK { false }; + bool OK{false}; if (Command == "MainCtrl") { - if( MainCtrlPosNo >= floor( CValue1 ) ) { - MainCtrlPos = static_cast( floor( CValue1 ) ); - if( DelayCtrlFlag ) { - if( ( LastRelayTime >= InitialCtrlDelay ) && ( MainCtrlPos == 1 ) ) - LastRelayTime = 0; - } - else if( LastRelayTime > CtrlDelay ) - LastRelayTime = 0; - } + if (MainCtrlPosNo >= floor(CValue1)) + { + MainCtrlPos = static_cast(floor(CValue1)); + if (DelayCtrlFlag) + { + if ((LastRelayTime >= InitialCtrlDelay) && (MainCtrlPos == 1)) + LastRelayTime = 0; + } + else if (LastRelayTime > CtrlDelay) + LastRelayTime = 0; + } OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "ScndCtrl") { - if( ScndCtrlPosNo >= floor( CValue1 ) ) { - ScndCtrlPos = static_cast( floor( CValue1 ) ); - if( LastRelayTime > CtrlDelay ) - LastRelayTime = 0; - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + if (ScndCtrlPosNo >= floor(CValue1)) + { + ScndCtrlPos = static_cast(floor(CValue1)); + if (LastRelayTime > CtrlDelay) + LastRelayTime = 0; + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } /* else if command='BrakeCtrl' then begin @@ -12103,182 +12117,210 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C DynamicBrakeEMUStatus = true; // fBrakeCtrlPos:=BrakeCtrlPos; //to powinnno być w jednym miejscu, aktualnie w C++!!! BrakePressureActual = BrakePressureTable[BrakeCtrlPos]; - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } // youby - odluzniacz hamulcow, przyda sie else if (Command == "BrakeReleaser") { OK = BrakeReleaser(Round(CValue1)); // samo się przesyła dalej - // OK:=SendCtrlToNext(command,CValue1,CValue2); //to robiło kaskadę 2^n + // OK:=SendCtrlToNext(command,CValue1,CValue2); //to robiło kaskadę 2^n } - else if( Command == "WaterPumpBreakerSwitch" ) { -/* - if( FuelPump.start_type != start::automatic ) { - // automatic fuel pump ignores 'manual' state commands -*/ - WaterPump.breaker = ( CValue1 == 1 ); -/* - } -*/ - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "WaterPumpSwitch" ) { - - if( WaterPump.start_type != start_t::battery ) { - // automatic fuel pump ignores 'manual' state commands - WaterPump.is_enabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "WaterPumpSwitchOff" ) { - - if( WaterPump.start_type != start_t::battery ) { - // automatic fuel pump ignores 'manual' state commands - WaterPump.is_disabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "WaterHeaterBreakerSwitch" ) { -/* - if( FuelPump.start_type != start::automatic ) { - // automatic fuel pump ignores 'manual' state commands -*/ - WaterHeater.breaker = ( CValue1 == 1 ); -/* - } -*/ - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "WaterHeaterSwitch" ) { -/* - if( FuelPump.start_type != start::automatic ) { - // automatic fuel pump ignores 'manual' state commands -*/ - WaterHeater.is_enabled = ( CValue1 == 1 ); -/* - } -*/ - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "WaterCircuitsLinkSwitch" ) { - if( true == dizel_heat.auxiliary_water_circuit ) { - // can only link circuits if the vehicle has more than one of them - WaterCircuitsLink = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "FuelPumpSwitch") { - if( FuelPump.start_type != start_t::automatic ) { - // automatic fuel pump ignores 'manual' state commands - FuelPump.is_enabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "FuelPumpSwitchOff") { - if( FuelPump.start_type != start_t::automatic ) { - // automatic fuel pump ignores 'manual' state commands - FuelPump.is_disabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "OilPumpSwitch") { - if( OilPump.start_type != start_t::automatic ) { - // automatic pump ignores 'manual' state commands - OilPump.is_enabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "OilPumpSwitchOff") { - if( OilPump.start_type != start_t::automatic ) { - // automatic pump ignores 'manual' state commands - OilPump.is_disabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "MotorBlowersFrontSwitch" ) { - if( ( MotorBlowers[ end::front ].start_type != start_t::manual ) - && ( MotorBlowers[ end::front ].start_type != start_t::manualwithautofallback ) ) { - // automatic device ignores 'manual' state commands - MotorBlowers[end::front].is_enabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "MotorBlowersFrontSwitchOff" ) { - if( ( MotorBlowers[ end::front ].start_type != start_t::manual ) - && ( MotorBlowers[ end::front ].start_type != start_t::manualwithautofallback ) ) { - // automatic device ignores 'manual' state commands - MotorBlowers[end::front].is_disabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "MotorBlowersRearSwitch" ) { - if( ( MotorBlowers[ end::rear ].start_type != start_t::manual ) - && ( MotorBlowers[ end::rear ].start_type != start_t::manualwithautofallback ) ) { - // automatic device ignores 'manual' state commands - MotorBlowers[end::rear].is_enabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "MotorBlowersRearSwitchOff" ) { - if( ( MotorBlowers[ end::rear ].start_type != start_t::manual ) - && ( MotorBlowers[ end::rear ].start_type != start_t::manualwithautofallback ) ) { - // automatic device ignores 'manual' state commands - MotorBlowers[end::rear].is_disabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "CompartmentLightsSwitch" ) { - - if( CompartmentLights.start_type != start_t::automatic ) { - // automatic lights ignore 'manual' state commands - CompartmentLights.is_enabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "CompartmentLightsSwitchOff" ) { - - if( CompartmentLights.start_type != start_t::automatic ) { - // automatic lights ignore 'manual' state commands - CompartmentLights.is_disabled = ( CValue1 == 1 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "MainSwitch") + else if (Command == "WaterPumpBreakerSwitch") { - MainSwitch_( CValue1 > 0.0 ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + /* + if( FuelPump.start_type != start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + */ + WaterPump.breaker = (CValue1 == 1); + /* + } + */ + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } - else if (Command == "HeatingSwitch") + else if (Command == "WaterPumpSwitch") { - HeatingSwitch_( CValue1 > 0.0 ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + + if (WaterPump.start_type != start_t::battery) + { + // automatic fuel pump ignores 'manual' state commands + WaterPump.is_enabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "WaterPumpSwitchOff") + { + + if (WaterPump.start_type != start_t::battery) + { + // automatic fuel pump ignores 'manual' state commands + WaterPump.is_disabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "WaterHeaterBreakerSwitch") + { + /* + if( FuelPump.start_type != start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + */ + WaterHeater.breaker = (CValue1 == 1); + /* + } + */ + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "WaterHeaterSwitch") + { + /* + if( FuelPump.start_type != start::automatic ) { + // automatic fuel pump ignores 'manual' state commands + */ + WaterHeater.is_enabled = (CValue1 == 1); + /* + } + */ + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "WaterCircuitsLinkSwitch") + { + if (true == dizel_heat.auxiliary_water_circuit) + { + // can only link circuits if the vehicle has more than one of them + WaterCircuitsLink = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "FuelPumpSwitch") + { + if (FuelPump.start_type != start_t::automatic) + { + // automatic fuel pump ignores 'manual' state commands + FuelPump.is_enabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "FuelPumpSwitchOff") + { + if (FuelPump.start_type != start_t::automatic) + { + // automatic fuel pump ignores 'manual' state commands + FuelPump.is_disabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "OilPumpSwitch") + { + if (OilPump.start_type != start_t::automatic) + { + // automatic pump ignores 'manual' state commands + OilPump.is_enabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "OilPumpSwitchOff") + { + if (OilPump.start_type != start_t::automatic) + { + // automatic pump ignores 'manual' state commands + OilPump.is_disabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "MotorBlowersFrontSwitch") + { + if ((MotorBlowers[end::front].start_type != start_t::manual) && (MotorBlowers[end::front].start_type != start_t::manualwithautofallback)) + { + // automatic device ignores 'manual' state commands + MotorBlowers[end::front].is_enabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "MotorBlowersFrontSwitchOff") + { + if ((MotorBlowers[end::front].start_type != start_t::manual) && (MotorBlowers[end::front].start_type != start_t::manualwithautofallback)) + { + // automatic device ignores 'manual' state commands + MotorBlowers[end::front].is_disabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "MotorBlowersRearSwitch") + { + if ((MotorBlowers[end::rear].start_type != start_t::manual) && (MotorBlowers[end::rear].start_type != start_t::manualwithautofallback)) + { + // automatic device ignores 'manual' state commands + MotorBlowers[end::rear].is_enabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "MotorBlowersRearSwitchOff") + { + if ((MotorBlowers[end::rear].start_type != start_t::manual) && (MotorBlowers[end::rear].start_type != start_t::manualwithautofallback)) + { + // automatic device ignores 'manual' state commands + MotorBlowers[end::rear].is_disabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "CompartmentLightsSwitch") + { + + if (CompartmentLights.start_type != start_t::automatic) + { + // automatic lights ignore 'manual' state commands + CompartmentLights.is_enabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "CompartmentLightsSwitchOff") + { + + if (CompartmentLights.start_type != start_t::automatic) + { + // automatic lights ignore 'manual' state commands + CompartmentLights.is_disabled = (CValue1 == 1); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "MainSwitch") + { + MainSwitch_(CValue1 > 0.0); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "HeatingSwitch") + { + HeatingSwitch_(CValue1 > 0.0); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "Direction") { DirActive = static_cast(floor(CValue1)); DirAbsolute = DirActive * CabActive; - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "CabActivisation") { // OK:=Power>0.01; switch (static_cast(CValue1 * CValue2)) { // CValue2 ma zmieniany znak przy niezgodności sprzęgów - case 1: { - CabActive = 1; - break; - } - case -1: { - CabActive = -1; - break; - } - default:{ - CabActive = 0; // gdy CValue1==0 - break; - } + case 1: + { + CabActive = 1; + break; + } + case -1: + { + CabActive = -1; + break; + } + default: + { + CabActive = 0; // gdy CValue1==0 + break; + } } DirAbsolute = DirActive * CabActive; CabMaster = false; - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "AutoRelaySwitch") { @@ -12286,159 +12328,162 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C AutoRelayFlag = true; else AutoRelayFlag = false; - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "RelayReset") { - RelayReset( CValue1, range_t::local ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + RelayReset(CValue1, range_t::local); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "ConverterSwitch") /*NBMX*/ { - if( ConverterStart == start_t::manual ) { - ConverterAllow = ( CValue1 > 0.0 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + if (ConverterStart == start_t::manual) + { + ConverterAllow = (CValue1 > 0.0); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "BatterySwitch") /*NBMX*/ - { - if( BatteryStart == start_t::manual ) { - Battery = ( CValue1 > 0.0 ); - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - // else if command='EpFuseSwitch' then {NBMX} - // begin - // if (CValue1=1) then EpFuse:=true - // else if (CValue1=0) then EpFuse:=false; - // OK:=SendCtrlToNext(command,CValue1,CValue2); - // end - else if (Command == "CompressorSwitch") /*NBMX*/ { - CompressorSwitch( ( CValue1 == 1 ), range_t::local ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + if (BatteryStart == start_t::manual) + { + Battery = (CValue1 > 0.0); + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } - else if( Command == "CompressorPreset" ) { - CompressorListPos = clamp( static_cast( CValue1 ), 0, CompressorListPosNo ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "DoorPermit") { + // else if command='EpFuseSwitch' then {NBMX} + // begin + // if (CValue1=1) then EpFuse:=true + // else if (CValue1=0) then EpFuse:=false; + // OK:=SendCtrlToNext(command,CValue1,CValue2); + // end + else if (Command == "CompressorSwitch") /*NBMX*/ + { + CompressorSwitch((CValue1 == 1), range_t::local); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "CompressorPreset") + { + CompressorListPos = clamp(static_cast(CValue1), 0, CompressorListPosNo); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "DoorPermit") + { - auto const left { CValue2 > 0 ? 1 : 2 }; - auto const right { 3 - left }; + auto const left{CValue2 > 0 ? 1 : 2}; + auto const right{3 - left}; - if( std::abs( static_cast( CValue1 ) ) & right ) { - PermitDoors_( side::right, ( CValue1 > 0 ) ); - } - if( std::abs( static_cast( CValue1 ) ) & left ) { - PermitDoors_( side::left, ( CValue1 > 0 ) ); - } + if (std::abs(static_cast(CValue1)) & right) + { + PermitDoors_(side::right, (CValue1 > 0)); + } + if (std::abs(static_cast(CValue1)) & left) + { + PermitDoors_(side::left, (CValue1 > 0)); + } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "DoorOpen") /*NBMX*/ { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów - if( ( Doors.open_control == control_t::conductor ) - || ( Doors.open_control == control_t::driver ) - || ( Doors.open_control == control_t::mixed ) ) { - // ignore remote command if the door is only operated locally - if( Power24vIsAvailable || Power110vIsAvailable ) { + if ((Doors.open_control == control_t::conductor) || (Doors.open_control == control_t::driver) || (Doors.open_control == control_t::mixed)) + { + // ignore remote command if the door is only operated locally + if (Power24vIsAvailable || Power110vIsAvailable) + { - auto const left{ CValue2 > 0 ? 1 : 2 }; - auto const right { 3 - left }; + auto const left{CValue2 > 0 ? 1 : 2}; + auto const right{3 - left}; - if( static_cast( CValue1 ) & right ) { - Doors.instances[ side::right ].remote_open = true; - Doors.instances[ side::right ].remote_close = false; - } - if( static_cast( CValue1 ) & left ) { - Doors.instances[ side::left ].remote_open = true; - Doors.instances[ side::left ].remote_close = false; - } - } - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + if (static_cast(CValue1) & right) + { + Doors.instances[side::right].remote_open = true; + Doors.instances[side::right].remote_close = false; + } + if (static_cast(CValue1) & left) + { + Doors.instances[side::left].remote_open = true; + Doors.instances[side::left].remote_close = false; + } + } + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "DoorClose") /*NBMX*/ { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów - if( ( Doors.close_control == control_t::conductor ) - || ( Doors.close_control == control_t::driver ) - || ( Doors.close_control == control_t::mixed ) ) { - // ignore remote command if the door is only operated locally - if( Power24vIsAvailable || Power110vIsAvailable ) { + if ((Doors.close_control == control_t::conductor) || (Doors.close_control == control_t::driver) || (Doors.close_control == control_t::mixed)) + { + // ignore remote command if the door is only operated locally + if (Power24vIsAvailable || Power110vIsAvailable) + { - auto const left{ CValue2 > 0 ? 1 : 2 }; - auto const right { 3 - left }; + auto const left{CValue2 > 0 ? 1 : 2}; + auto const right{3 - left}; - if( static_cast( CValue1 ) & right ) { - Doors.instances[ side::right ].remote_close = true; - Doors.instances[ side::right ].remote_open = false; - } - if( static_cast( CValue1 ) & left ) { - Doors.instances[ side::left ].remote_close = true; - Doors.instances[ side::left ].remote_open = false; - } - } - } - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + if (static_cast(CValue1) & right) + { + Doors.instances[side::right].remote_close = true; + Doors.instances[side::right].remote_open = false; + } + if (static_cast(CValue1) & left) + { + Doors.instances[side::left].remote_close = true; + Doors.instances[side::left].remote_open = false; + } + } + } + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } - else if( Command == "DoorLock" ) { - Doors.lock_enabled = ( - CValue1 == 1 ? - true : - false ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "DoorStep" ) { - Doors.step_enabled = ( - CValue1 == 1 ? - true : - false ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "DoorMode" ) { - Doors.remote_only = ( - CValue1 == 1 ? - true : - false ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "DepartureSignal" ) { - DepartureSignal = ( - CValue1 == 1 ? - true : - false ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "PantValve") //Winger 160204 + else if (Command == "DoorLock") + { + Doors.lock_enabled = (CValue1 == 1 ? true : false); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "DoorStep") + { + Doors.step_enabled = (CValue1 == 1 ? true : false); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "DoorMode") + { + Doors.remote_only = (CValue1 == 1 ? true : false); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "DepartureSignal") + { + DepartureSignal = (CValue1 == 1 ? true : false); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "PantValve") // Winger 160204 { // Ra: uwzględnić trzeba jeszcze zgodność sprzęgów - auto const inputend { ( static_cast( CValue1 ) & 0x80 ) != 0 ? 1 : 0 }; - auto const inputcab { ( static_cast( CValue1 ) & 0x40 ) != 0 ? 1 : 0 }; - auto const inputoperation { static_cast( CValue1 ) & ~( 0x80 | 0x40 ) }; - auto const noswap { ( TrainType == dt_EZT ) || ( TrainType == dt_ET41 ) }; - auto swap { - ( false == noswap ) - && ( TestFlag( Couplers[ ( CValue2 == -1 ? end::rear : end::front ) ].CouplingFlag, coupling::control ) ) }; - auto const reversed { inputcab != ( CabActive != -1 ? 1 : 0 ) }; - if( reversed ) { swap = !swap; } // TODO: check whether this part has RL equivalent - OperatePantographValve( - static_cast( swap ? 1 - inputend : inputend ), - static_cast( inputoperation ), - range_t::local ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + auto const inputend{(static_cast(CValue1) & 0x80) != 0 ? 1 : 0}; + auto const inputcab{(static_cast(CValue1) & 0x40) != 0 ? 1 : 0}; + auto const inputoperation{static_cast(CValue1) & ~(0x80 | 0x40)}; + auto const noswap{(TrainType == dt_EZT) || (TrainType == dt_ET41)}; + auto swap{(false == noswap) && (TestFlag(Couplers[(CValue2 == -1 ? end::rear : end::front)].CouplingFlag, coupling::control))}; + auto const reversed{inputcab != (CabActive != -1 ? 1 : 0)}; + if (reversed) + { + swap = !swap; + } // TODO: check whether this part has RL equivalent + OperatePantographValve(static_cast(swap ? 1 - inputend : inputend), static_cast(inputoperation), range_t::local); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "PantsValve") + { + OperatePantographsValve(static_cast(static_cast(CValue1)), range_t::local); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "PantAllDown") + { + DropAllPantographs(CValue1 == 1, range_t::local); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); + } + else if (Command == "MaxCurrentSwitch") + { + MaxCurrentSwitch(CValue1 == 1, range_t::local); + OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } - else if( Command == "PantsValve" ) { - OperatePantographsValve( static_cast( static_cast( CValue1 ) ), range_t::local ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if( Command == "PantAllDown" ) { - DropAllPantographs( CValue1 == 1, range_t::local ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } - else if (Command == "MaxCurrentSwitch") { - MaxCurrentSwitch( CValue1 == 1, range_t::local ); - OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); - } else if (Command == "MinCurrentSwitch") { OK = MinCurrentSwitch(CValue1 == 1); @@ -12460,19 +12505,21 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C } else if (Command == "BrakeDelay") { - auto const brakesetting = static_cast( std::floor( CValue1 ) ); - if( true == Hamulec->SetBDF( brakesetting ) ) { - BrakeDelayFlag = brakesetting; - OK = true; - } - else { - OK = false; - } - SendCtrlToNext( Command, CValue1, CValue2, Couplertype ); + auto const brakesetting = static_cast(std::floor(CValue1)); + if (true == Hamulec->SetBDF(brakesetting)) + { + BrakeDelayFlag = brakesetting; + OK = true; + } + else + { + OK = false; + } + SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "Sandbox") { - OK = Sandbox( CValue1 == 1, range_t::local ); + OK = Sandbox(CValue1 == 1, range_t::local); } else if (Command == "CabSignal") /*SHP,Indusi*/ { // Ra: to powinno działać tylko w członie obsadzonym @@ -12481,49 +12528,49 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C OK = true; // true, gdy można usunąć komendę } /*naladunek/rozladunek*/ - // TODO: have these commands leverage load exchange system instead - // TODO: CValue1 defines amount to load/unload - else if ( issection( "Load=", Command ) ) + // TODO: have these commands leverage load exchange system instead + // TODO: CValue1 defines amount to load/unload + else if (issection("Load=", Command)) { OK = false; // będzie powtarzane aż się załaduje - if( ( Vel < 0.1 ) // tolerance margin for small vehicle movements in the consist - && ( MaxLoad > 0 ) - && ( LoadAmount < MaxLoad * ( 1.0 + OverLoadFactor ) ) - && ( Distance( Loc, CommandIn.Location, Dim, Dim ) < ( CValue2 > 1.0 ? CValue2 : 10.0 ) ) ) { // ten peron/rampa + if ((Vel < 0.1) // tolerance margin for small vehicle movements in the consist + && (MaxLoad > 0) && (LoadAmount < MaxLoad * (1.0 + OverLoadFactor)) && (Distance(Loc, CommandIn.Location, Dim, Dim) < (CValue2 > 1.0 ? CValue2 : 10.0))) + { // ten peron/rampa - auto const loadname { ToLower( extract_value( "Load", Command ) ) }; - if( LoadAmount == 0.f ) { - AssignLoad( loadname ); - } - OK = LoadingDone( - LoadSpeed, - loadname ); // zmienia LoadStatus - } - else { - // no loading can be done if conditions aren't met - LastLoadChangeTime = 0.0; - } + auto const loadname{ToLower(extract_value("Load", Command))}; + if (LoadAmount == 0.f) + { + AssignLoad(loadname); + } + OK = LoadingDone(LoadSpeed, + loadname); // zmienia LoadStatus + } + else + { + // no loading can be done if conditions aren't met + LastLoadChangeTime = 0.0; + } } - else if( issection( "UnLoad=", Command ) ) + else if (issection("UnLoad=", Command)) { OK = false; // będzie powtarzane aż się rozładuje - if( ( Vel < 0.1 ) // tolerance margin for small vehicle movements in the consist - && ( LoadAmount > 0 ) // czy jest co rozladowac? - && ( Distance( Loc, CommandIn.Location, Dim, Dim ) < ( CValue2 > 1.0 ? CValue2 : 10.0 ) ) ) { // ten peron - /*mozna to rozladowac*/ - OK = LoadingDone( - -1.f * LoadSpeed, - ToLower( extract_value( "UnLoad", Command ) ) ); - } - else { - // no loading can be done if conditions aren't met - LastLoadChangeTime = 0.0; - } - } + if ((Vel < 0.1) // tolerance margin for small vehicle movements in the consist + && (LoadAmount > 0) // czy jest co rozladowac? + && (Distance(Loc, CommandIn.Location, Dim, Dim) < (CValue2 > 1.0 ? CValue2 : 10.0))) + { // ten peron + /*mozna to rozladowac*/ + OK = LoadingDone(-1.f * LoadSpeed, ToLower(extract_value("UnLoad", Command))); + } + else + { + // no loading can be done if conditions aren't met + LastLoadChangeTime = 0.0; + } + } else if (Command == "SpeedCntrl") { - if ((EngineType == TEngineType::ElectricInductionMotor)||(SpeedCtrl)) - SpeedCtrlValue = static_cast(round(CValue1)); + if ((EngineType == TEngineType::ElectricInductionMotor) || (SpeedCtrl)) + SpeedCtrlValue = static_cast(round(CValue1)); OK = SendCtrlToNext(Command, CValue1, CValue2, Couplertype); } else if (Command == "SpeedCtrlUnit.Parking") @@ -12551,26 +12598,27 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C // ************************************************************************************************* bool TMoverParameters::RunInternalCommand() { - bool OK; + bool OK; - if (!CommandIn.Command.empty()) - { - OK = RunCommand( CommandIn.Command, CommandIn.Value1, CommandIn.Value2, CommandIn.Coupling ); - if (OK) { + if (!CommandIn.Command.empty()) + { + OK = RunCommand(CommandIn.Command, CommandIn.Value1, CommandIn.Value2, CommandIn.Coupling); + if (OK) + { - CommandIn.Command.clear(); // kasowanie bo rozkaz wykonany - CommandIn.Value1 = 0; - CommandIn.Value2 = 0; - CommandIn.Coupling = 0; - CommandIn.Location.X = 0; - CommandIn.Location.Y = 0; - CommandIn.Location.Z = 0; - switch_physics( true ); - } - } - else - OK = false; - return OK; + CommandIn.Command.clear(); // kasowanie bo rozkaz wykonany + CommandIn.Value1 = 0; + CommandIn.Value2 = 0; + CommandIn.Coupling = 0; + CommandIn.Location.X = 0; + CommandIn.Location.Y = 0; + CommandIn.Location.Z = 0; + switch_physics(true); + } + } + else + OK = false; + return OK; } // ************************************************************************************************* @@ -12579,59 +12627,62 @@ bool TMoverParameters::RunInternalCommand() // ************************************************************************************************* double TMoverParameters::ShowCurrentP(int AmpN) const { - int b, Bn; - bool Grupowy; + int b, Bn; + bool Grupowy; - // ClearPendingExceptions; - Grupowy = ((DelayCtrlFlag) && (TrainType == dt_ET22)); // przerzucanie walu grupowego w ET22; - Bn = RList[MainCtrlActualPos].Bn; // ile równoległych gałęzi silników + // ClearPendingExceptions; + Grupowy = ((DelayCtrlFlag) && (TrainType == dt_ET22)); // przerzucanie walu grupowego w ET22; + Bn = RList[MainCtrlActualPos].Bn; // ile równoległych gałęzi silników - if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) - Bn = DynamicBrakeAmpmeters; - if (Power > 0.01) - { - if (AmpN > 0) // podać prąd w gałęzi - { - if ((Bn < AmpN) || ((Grupowy) && (AmpN == Bn - 1))) - return 0; - else // normalne podawanie pradu - return floor(abs(Im)); - } - else // podać całkowity - return floor(abs(Itot)); - } - else // pobor pradu jezeli niema mocy - { - int current = 0; - for (b = 0; b < 2; b++) - // with Couplers[b] do - if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) - if (Couplers[b].Connected->Power > 0.01) - current = static_cast(Couplers[b].Connected->ShowCurrent(AmpN)); - return current; - } + if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag)) + Bn = DynamicBrakeAmpmeters; + if (Power > 0.01) + { + if (AmpN > 0) // podać prąd w gałęzi + { + if ((Bn < AmpN) || ((Grupowy) && (AmpN == Bn - 1))) + return 0; + else // normalne podawanie pradu + return floor(abs(Im)); + } + else // podać całkowity + return floor(abs(Itot)); + } + else // pobor pradu jezeli niema mocy + { + int current = 0; + for (b = 0; b < 2; b++) + // with Couplers[b] do + if (TestFlag(Couplers[b].CouplingFlag, coupling::control)) + if (Couplers[b].Connected->Power > 0.01) + current = static_cast(Couplers[b].Connected->ShowCurrent(AmpN)); + return current; + } } -bool TMoverParameters::reload_FIZ() { +bool TMoverParameters::reload_FIZ() +{ WriteLog("[DEV] Reloading FIZ for " + Name); - // pause simulation + // pause simulation Global.iPause |= 0b1000; bool result = LoadFIZ(chkPath); - if (result == true) - { + if (result == true) + { // jesli sie udalo przeladowac FIZ Global.iPause &= 0b0111; WriteLog("[DEV] FIZ reloaded for " + Name); - } - else { - // failed to reload - exit simulator + } + else + { + // failed to reload - exit simulator ErrorLog("[DEV] Failed to reload fiz for vehicle " + Name); - } + } return true; } -namespace simulation { +namespace simulation +{ weights_table Weights; -} // simulation +} // namespace simulation diff --git a/McZapkie/hamulce.cpp b/McZapkie/hamulce.cpp index 35538eea..6eb33eb7 100644 --- a/McZapkie/hamulce.cpp +++ b/McZapkie/hamulce.cpp @@ -23,8 +23,8 @@ Copyright (C) 2007-2014 Maciej Cierniak static double const DPL = 0.25; double const TFV4aM::pos_table[11] = {-2, 6, -1, 0, -2, 1, 4, 6, 0, 0, 0}; double const TMHZ_EN57::pos_table[11] = {-1, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0}; -double const TMHZ_K5P::pos_table[11] = { -1, 3, -1, 0, 1, 1, 2, 3, 0, 0, 0 }; -double const TMHZ_6P::pos_table[11] = { -1, 4, -1, 0, 2, 2, 3, 4, 0, 0, 0 }; +double const TMHZ_K5P::pos_table[11] = {-1, 3, -1, 0, 1, 1, 2, 3, 0, 0, 0}; +double const TMHZ_6P::pos_table[11] = {-1, 4, -1, 0, 2, 2, 3, 4, 0, 0, 0}; double const TM394::pos_table[11] = {-1, 5, -1, 0, 1, 2, 4, 5, 0, 0, 0}; double const TH14K1::BPT_K[6][2] = {{10, 0}, {4, 1}, {0, 1}, {4, 0}, {4, -1}, {15, -1}}; double const TH14K1::pos_table[11] = {-1, 4, -1, 0, 1, 2, 3, 4, 0, 0, 0}; @@ -32,108 +32,170 @@ double const TSt113::BPT_K[6][2] = {{10, 0}, {4, 1}, {0, 1}, {4, 0}, {4, -1}, {1 double const TSt113::BEP_K[7] = {0, -1, 1, 0, 0, 0, 0}; double const TSt113::pos_table[11] = {-1, 5, -1, 0, 2, 3, 4, 5, 0, 0, 1}; double const TFVel6::pos_table[11] = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1}; -double const TFVE408::pos_table[11] = { 0, 10, 0, 0, 10, 7, 8, 9, 0, 1, 5 }; +double const TFVE408::pos_table[11] = {0, 10, 0, 0, 10, 7, 8, 9, 0, 1, 5}; +/// +/// Pressure-ratio helper used by reservoir filling/emptying integrators. +/// Returns the dimensionless driving term (P2 - P1) / (1.13 * PH - PL), +/// where PH/PL are the absolute high/low pressures (with a small safety margin), +/// signed in the direction of P1 -> P2. +/// +/// Source pressure [bar]. +/// Destination pressure [bar]. +/// Dimensionless flow driver (positive when P2 > P1). double PR(double P1, double P2) { - double PH = Max0R(P1, P2) + 0.1; - double PL = P1 + P2 - PH + 0.2; - return (P2 - P1) / (1.13 * PH - PL); + double PH = Max0R(P1, P2) + 0.1; + double PL = P1 + P2 - PH + 0.2; + return (P2 - P1) / (1.13 * PH - PL); } +/// +/// Legacy pneumatic flow function. Kept for reference; superseded by . +/// +/// Source pressure [bar]. +/// Destination pressure [bar]. +/// Effective orifice cross-section. +/// Volumetric flow rate (signed). double PF_old(double P1, double P2, double S) { - double PH = Max0R(P1, P2) + 1; - double PL = P1 + P2 - PH + 2; - if (PH - PL < 0.0001) - return 0; - else if ((PH - PL) < 0.05) - return 20 * (PH - PL) * (PH + 1) * 222 * S * (P2 - P1) / (1.13 * PH - PL); - else - return (PH + 1) * 222 * S * (P2 - P1) / (1.13 * PH - PL); + double PH = Max0R(P1, P2) + 1; + double PL = P1 + P2 - PH + 2; + if (PH - PL < 0.0001) + return 0; + else if ((PH - PL) < 0.05) + return 20 * (PH - PL) * (PH + 1) * 222 * S * (P2 - P1) / (1.13 * PH - PL); + else + return (PH + 1) * 222 * S * (P2 - P1) / (1.13 * PH - PL); } -double PF( double const P1, double const P2, double const S, double const DP ) +/// +/// Pneumatic flow rate from one pressure to another through an orifice of area S. +/// Distinguishes choked (PL/PH below 0.5) from subsonic flow and softens the +/// curve near zero pressure delta using a DP-wide ramp to keep the integrator stable. +/// +/// Source pressure [bar]. +/// Destination pressure [bar]. +/// Effective orifice cross-section. +/// Soft-clip pressure delta — softens the response for tiny PH-PL differences (default 0.25). +/// Volumetric flow rate (signed; positive when P2 > P1). +double PF(double const P1, double const P2, double const S, double const DP) { - double const PH = std::max(P1, P2) + 1.0; // wyzsze cisnienie absolutne - double const PL = P1 + P2 - PH + 2.0; // nizsze cisnienie absolutne - double const sg = PL / PH; // bezwymiarowy stosunek cisnien - double const FM = PH * 197.0 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem - if (sg > 0.5) // jesli ponizej stosunku krytycznego - if ((PH - PL) < DP) // niewielka roznica cisnien - return (1.0 - sg) / DPL * FM * 2.0 * std::sqrt((DP) * (PH - DP)); - // return 1/DPL*(PH-PL)*fm*2*SQRT((sg)*(1-sg)); - else - return FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); - else // powyzej stosunku krytycznego - return FM; + double const PH = std::max(P1, P2) + 1.0; // wyzsze cisnienie absolutne + double const PL = P1 + P2 - PH + 2.0; // nizsze cisnienie absolutne + double const sg = PL / PH; // bezwymiarowy stosunek cisnien + double const FM = PH * 197.0 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem + if (sg > 0.5) // jesli ponizej stosunku krytycznego + if ((PH - PL) < DP) // niewielka roznica cisnien + return (1.0 - sg) / DPL * FM * 2.0 * std::sqrt((DP) * (PH - DP)); + // return 1/DPL*(PH-PL)*fm*2*SQRT((sg)*(1-sg)); + else + return FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); + else // powyzej stosunku krytycznego + return FM; } -double PF1( double const P1, double const P2, double const S ) +/// +/// Variant of that uses the dimensionless pressure ratio (sg) +/// for the soft-clip threshold instead of an absolute pressure delta. +/// +/// Source pressure [bar]. +/// Destination pressure [bar]. +/// Effective orifice cross-section. +/// Volumetric flow rate (signed). +double PF1(double const P1, double const P2, double const S) { - static double const DPS = 0.001; + static double const DPS = 0.001; - double const PH = std::max(P1, P2) + 1.0; // wyzsze cisnienie absolutne - double const PL = P1 + P2 - PH + 2.0; // nizsze cisnienie absolutne - double const sg = PL / PH; // bezwymiarowy stosunek cisnien - double const FM = PH * 197.0 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem - if (sg > 0.5) // jesli ponizej stosunku krytycznego - if (sg < DPS) // niewielka roznica cisnien - return (1.0 - sg) / DPS * FM * 2.0 * std::sqrt((DPS) * (1.0 - DPS)); - else - return FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); - else // powyzej stosunku krytycznego - return FM; + double const PH = std::max(P1, P2) + 1.0; // wyzsze cisnienie absolutne + double const PL = P1 + P2 - PH + 2.0; // nizsze cisnienie absolutne + double const sg = PL / PH; // bezwymiarowy stosunek cisnien + double const FM = PH * 197.0 * S * Sign(P2 - P1); // najwyzszy mozliwy przeplyw, wraz z kierunkiem + if (sg > 0.5) // jesli ponizej stosunku krytycznego + if (sg < DPS) // niewielka roznica cisnien + return (1.0 - sg) / DPS * FM * 2.0 * std::sqrt((DPS) * (1.0 - DPS)); + else + return FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); + else // powyzej stosunku krytycznego + return FM; } -double PFVa( double PH, double PL, double const S, double LIM, double const DP ) +/// +/// Filling valve flow: flows from PH to PL until PL reaches LIM. The valve +/// throttles smoothly as PL approaches LIM (within DP of the target). +/// Returns 0 once PL is already >= LIM. +/// +/// High-pressure source [bar]. +/// Low-pressure side that is being filled [bar]. +/// Effective orifice cross-section. +/// Target pressure for PL [bar] — flow stops once PL reaches LIM. +/// Throttling distance from LIM (default 0.1). +/// Flow rate from PH to PL (positive into PL). +double PFVa(double PH, double PL, double const S, double LIM, double const DP) // zawor napelniajacy z PH do PL, PL do LIM { - if (LIM > PL) - { - LIM = LIM + 1; - PH = PH + 1; // wyzsze cisnienie absolutne - PL = PL + 1; // nizsze cisnienie absolutne - double sg = std::min( 1.0, PL / PH ); // bezwymiarowy stosunek cisnien. NOTE: sg is capped at 1 to prevent calculations from going awry. TODO, TBD: log these as errors? - double FM = PH * 197 * S; // najwyzszy mozliwy przeplyw, wraz z kierunkiem - if ((LIM - PL) < DP) - FM = FM * (LIM - PL) / DP; // jesli jestesmy przy nastawieniu, to zawor sie przymyka - if ((sg > 0.5)) // jesli ponizej stosunku krytycznego - if ((PH - PL) < DPL) // niewielka roznica cisnien - return (PH - PL) / DPL * FM * 2 * std::sqrt((sg) * (1 - sg)); // BUG: (1-sg) can be < 0, leading to sqrt(-x) - else - return FM * 2 * std::sqrt( (sg) * ( 1 - sg ) ); // BUG: (1-sg) can be < 0, leading to sqrt(-x) - else // powyzej stosunku krytycznego - return FM; - } - else - return 0; + if (LIM > PL) + { + LIM = LIM + 1; + PH = PH + 1; // wyzsze cisnienie absolutne + PL = PL + 1; // nizsze cisnienie absolutne + double sg = std::min(1.0, PL / PH); // bezwymiarowy stosunek cisnien. NOTE: sg is capped at 1 to prevent calculations from going awry. TODO, TBD: log these as errors? + double FM = PH * 197 * S; // najwyzszy mozliwy przeplyw, wraz z kierunkiem + if ((LIM - PL) < DP) + FM = FM * (LIM - PL) / DP; // jesli jestesmy przy nastawieniu, to zawor sie przymyka + if ((sg > 0.5)) // jesli ponizej stosunku krytycznego + if ((PH - PL) < DPL) // niewielka roznica cisnien + return (PH - PL) / DPL * FM * 2 * std::sqrt((sg) * (1 - sg)); // BUG: (1-sg) can be < 0, leading to sqrt(-x) + else + return FM * 2 * std::sqrt((sg) * (1 - sg)); // BUG: (1-sg) can be < 0, leading to sqrt(-x) + else // powyzej stosunku krytycznego + return FM; + } + else + return 0; } -double PFVd( double PH, double PL, double const S, double LIM, double const DP ) +/// +/// Venting valve flow: flows from PH to PL until PH falls to LIM. The valve +/// throttles smoothly as PH approaches LIM. Returns 0 once PH <= LIM. +/// +/// High-pressure side that is being vented [bar]. +/// Low-pressure destination [bar]. +/// Effective orifice cross-section. +/// Lower bound for PH [bar] — flow stops once PH falls to LIM. +/// Throttling distance from LIM (default 0.1). +/// Flow rate from PH to PL. +double PFVd(double PH, double PL, double const S, double LIM, double const DP) // zawor wypuszczajacy z PH do PL, PH do LIM { - if (LIM < PH) - { - LIM = LIM + 1; - PH = PH + 1.0; // wyzsze cisnienie absolutne - PL = PL + 1.0; // nizsze cisnienie absolutne - double sg = std::min( 1.0, PL / PH ); // bezwymiarowy stosunek cisnien - double FM = PH * 197.0 * S; // najwyzszy mozliwy przeplyw, wraz z kierunkiem - if ((PH - LIM) < 0.1) - FM = FM * (PH - LIM) / DP; // jesli jestesmy przy nastawieniu, to zawor sie przymyka - if ((sg > 0.5)) // jesli ponizej stosunku krytycznego - if ((PH - PL) < DPL) // niewielka roznica cisnien - return (PH - PL) / DPL * FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); - else - return FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); - else // powyzej stosunku krytycznego - return FM; - } - else - return 0; + if (LIM < PH) + { + LIM = LIM + 1; + PH = PH + 1.0; // wyzsze cisnienie absolutne + PL = PL + 1.0; // nizsze cisnienie absolutne + double sg = std::min(1.0, PL / PH); // bezwymiarowy stosunek cisnien + double FM = PH * 197.0 * S; // najwyzszy mozliwy przeplyw, wraz z kierunkiem + if ((PH - LIM) < 0.1) + FM = FM * (PH - LIM) / DP; // jesli jestesmy przy nastawieniu, to zawor sie przymyka + if ((sg > 0.5)) // jesli ponizej stosunku krytycznego + if ((PH - PL) < DPL) // niewielka roznica cisnien + return (PH - PL) / DPL * FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); + else + return FM * 2.0 * std::sqrt((sg) * (1.0 - sg)); + else // powyzej stosunku krytycznego + return FM; + } + else + return 0; } +/// +/// Returns true when a continuous handle position falls into a unit-wide +/// detent centred on i_pos (i.e. pos is in (i_pos - 0.5, i_pos + 0.5]). +/// +/// Continuous handle position. +/// Detent centre to compare against. +/// True if pos is within ±0.5 of i_pos. bool is_EQ(double pos, double i_pos) { return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); @@ -141,44 +203,75 @@ bool is_EQ(double pos, double i_pos) //---ZBIORNIKI--- +/// +/// Returns absolute (atmospheric) pressure inside the reservoir as 0.1 * Vol / Cap. +/// +/// Absolute pressure value. double TReservoir::pa() { - return 0.1 * Vol / Cap; + return 0.1 * Vol / Cap; } +/// +/// Returns gauge pressure inside the reservoir as Vol / Cap. +/// +/// Pressure in bar. double TReservoir::P() { - return Vol / Cap; + return Vol / Cap; } +/// +/// Accumulates a flow delta into the pending volume change for the current step. +/// The change is applied to Vol on the next call to . +/// +/// Flow delta (positive = into reservoir, negative = out). void TReservoir::Flow(double dv) { - dVol = dVol + dv; + dVol = dVol + dv; } +/// +/// Commits the pending flow accumulated by to Vol +/// (clamping it to non-negative) and resets the pending delta to zero. +/// void TReservoir::Act() { - Vol = std::max( 0.0, Vol + dVol ); - dVol = 0; + Vol = std::max(0.0, Vol + dVol); + dVol = 0; } +/// +/// Sets the reservoir capacity in liters. +/// +/// Capacity in liters. void TReservoir::CreateCap(double Capacity) { - Cap = Capacity; + Cap = Capacity; } +/// +/// Initialises the reservoir to a given pressure (Vol = Cap * Press) +/// and clears any pending flow. +/// +/// Initial pressure in bar. void TReservoir::CreatePress(double Press) { - Vol = Cap * Press; - dVol = 0; + Vol = Cap * Press; + dVol = 0; } //---SILOWNIK--- +/// +/// Returns the absolute pressure inside the brake cylinder +/// (gauge pressure from scaled to atm). +/// +/// Absolute brake-cylinder pressure. double TBrakeCyl::pa() // var VtoC: real; { - // VtoC:=Vol/Cap; - return P() * 0.1; + // VtoC:=Vol/Cap; + return P() * 0.1; } /* NOWSZA WERSJA - maksymalne ciśnienie to ok. 4,75 bar, co powoduje @@ -194,23 +287,30 @@ begin end; */ //(* STARA WERSJA +/// +/// Returns the gauge pressure inside the brake cylinder using the legacy +/// piston-stroke pressure curve: a low-pressure dead-volume region (VtoC < VS), +/// a linear stroke region, and a saturated region once the piston is fully extended. +/// Includes a div-by-zero guard for vehicles with incomplete definitions. +/// +/// Cylinder pressure in bar. double TBrakeCyl::P() { - static double const VS = 0.005; - static double const pS = 0.05; - static double const VD = 1.10; - static double const cD = 1; - static double const pD = VD - cD; + static double const VS = 0.005; + static double const pS = 0.05; + static double const VD = 1.10; + static double const cD = 1; + static double const pD = VD - cD; - double VtoC = ( Cap > 0.0 ? Vol / Cap : 0.0 ); // stosunek cisnienia do objetosci. - // Added div/0 trap for vehicles with incomplete definitions (cars etc) - // P:=VtoC; - if (VtoC < VS) - return VtoC * pS / VS; // objetosc szkodliwa - else if (VtoC > VD) - return VtoC - cD; // caly silownik; - else - return pS + (VtoC - VS) / (VD - VS) * (pD - pS); // wysuwanie tloka + double VtoC = (Cap > 0.0 ? Vol / Cap : 0.0); // stosunek cisnienia do objetosci. + // Added div/0 trap for vehicles with incomplete definitions (cars etc) + // P:=VtoC; + if (VtoC < VS) + return VtoC * pS / VS; // objetosc szkodliwa + else if (VtoC > VD) + return VtoC - cD; // caly silownik; + else + return pS + (VtoC - VS) / (VD - VS) * (pD - pS); // wysuwanie tloka } //*) //---HAMULEC--- @@ -242,1331 +342,1666 @@ begin end ; */ -TBrake::TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, - int i_mat, int i_ba, int i_nbpa) +/// +/// Constructs the brake unit: stores parameters, creates the cylinder / +/// auxiliary reservoir / valve pre-chamber, sizes them for the requested +/// 14"-relative scale, and instantiates the friction-material model based on +/// the friction-pair id (with the magnetic-rail flag bp_MHS masked off). +/// +/// Maximum brake cylinder pressure [bar]. +/// Brake cylinder radius [m]. +/// Brake cylinder working stroke [m]. +/// Auxiliary reservoir capacity [l]. +/// Number of brake cylinders. +/// Available brake delay positions (bdelay_* bitmask). +/// Friction material id (bp_* constant, optionally OR'ed with bp_MHS). +/// Number of braked axles. +/// Number of blocks per axle. +TBrake::TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) { - // inherited:: Create; - MaxBP = i_mbp; - BCN = i_bcn; - BCM = 1; - BCA = i_bcn * i_bcr * i_bcr * M_PI; - BA = i_ba; - NBpA = i_nbpa; - BrakeDelays = i_BD; - BrakeDelayFlag = bdelay_P; - // 210.88 - // SizeBR:=i_bcn*i_bcr*i_bcr*i_bcd*40.17*MaxBP/(5-MaxBP); //objetosc ZP w stosunku do cylindra - // 14" i cisnienia 4.2 atm - SizeBR = i_brc * 0.0128; - SizeBC = i_bcn * i_bcr * i_bcr * i_bcd * 210.88 * MaxBP / - 4.2; // objetosc CH w stosunku do cylindra 14" i cisnienia 4.2 atm + // inherited:: Create; + MaxBP = i_mbp; + BCN = i_bcn; + BCM = 1; + BCA = i_bcn * i_bcr * i_bcr * M_PI; + BA = i_ba; + NBpA = i_nbpa; + BrakeDelays = i_BD; + BrakeDelayFlag = bdelay_P; + // 210.88 + // SizeBR:=i_bcn*i_bcr*i_bcr*i_bcd*40.17*MaxBP/(5-MaxBP); //objetosc ZP w stosunku do cylindra + // 14" i cisnienia 4.2 atm + SizeBR = i_brc * 0.0128; + SizeBC = i_bcn * i_bcr * i_bcr * i_bcd * 210.88 * MaxBP / 4.2; // objetosc CH w stosunku do cylindra 14" i cisnienia 4.2 atm - BrakeCyl = std::make_shared(); - BrakeRes = std::make_shared(); - ValveRes = std::make_shared(); + BrakeCyl = std::make_shared(); + BrakeRes = std::make_shared(); + ValveRes = std::make_shared(); - // tworzenie zbiornikow - BrakeCyl->CreateCap(i_bcd * BCA * 1000); - BrakeRes->CreateCap(i_brc); - ValveRes->CreateCap(0.25); + // tworzenie zbiornikow + BrakeCyl->CreateCap(i_bcd * BCA * 1000); + BrakeRes->CreateCap(i_brc); + ValveRes->CreateCap(0.25); - // materialy cierne - i_mat = i_mat & (255 - bp_MHS); - switch (i_mat) - { - case bp_P10Bg: - FM = std::make_shared(); - break; - case bp_P10Bgu: - FM = std::make_shared(); - break; - case bp_FR513: - FM = std::make_shared(); - break; - case bp_FR510: - FM = std::make_shared(); - break; - case bp_Cosid: - FM = std::make_shared(); - break; - case bp_P10yBg: - FM = std::make_shared(); - break; - case bp_P10yBgu: - FM = std::make_shared(); - break; - case bp_D1: - FM = std::make_shared(); - break; - case bp_D2: - FM = std::make_shared(); - break; - default: // domyslnie - FM = std::make_shared(); - } + // materialy cierne + i_mat = i_mat & (255 - bp_MHS); + switch (i_mat) + { + case bp_P10Bg: + FM = std::make_shared(); + break; + case bp_P10Bgu: + FM = std::make_shared(); + break; + case bp_FR513: + FM = std::make_shared(); + break; + case bp_FR510: + FM = std::make_shared(); + break; + case bp_Cosid: + FM = std::make_shared(); + break; + case bp_P10yBg: + FM = std::make_shared(); + break; + case bp_P10yBgu: + FM = std::make_shared(); + break; + case bp_D1: + FM = std::make_shared(); + break; + case bp_D2: + FM = std::make_shared(); + break; + default: // domyslnie + FM = std::make_shared(); + } } +/// +/// Default brake initialisation — only stores the requested delay flag. +/// Derived classes typically override to also pre-charge the reservoirs. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial brake cylinder pressure [bar]. +/// Initial brake delay flag. // inicjalizacja hamulca (stan poczatkowy) -void TBrake::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +void TBrake::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - BrakeDelayFlag = BDF; + BrakeDelayFlag = BDF; } +/// +/// Returns the friction coefficient between the blocks and the wheel/disc by +/// delegating to the friction-material model (note: arguments are forwarded +/// in (N, Vel) order to match the friction-material API). +/// +/// Vehicle velocity. +/// Normal force on the block. +/// Friction coefficient. // pobranie wspolczynnika tarcia materialu -double TBrake::GetFC( double const Vel, double const N ) +double TBrake::GetFC(double const Vel, double const N) { - return FM->GetFC(N, Vel); + return FM->GetFC(N, Vel); } +/// Returns the gauge pressure inside the brake cylinder. // cisnienie cylindra hamulcowego double TBrake::GetBCP() { - return BrakeCyl->P(); + return BrakeCyl->P(); } +/// Default ED reference pressure — 0 unless overridden by EP09-style distributors. // ciśnienie sterujące hamowaniem elektro-dynamicznym double TBrake::GetEDBCP() { - return 0; + return 0; } +/// Returns the auxiliary reservoir (ZP) pressure. // cisnienie zbiornika pomocniczego double TBrake::GetBRP() { - return BrakeRes->P(); + return BrakeRes->P(); } +/// Returns the valve pre-chamber pressure. // cisnienie komory wstepnej double TBrake::GetVRP() { - return ValveRes->P(); + return ValveRes->P(); } +/// +/// Default control-reservoir pressure: forwards to the auxiliary reservoir. +/// Distributors with a real ZS override this to return CntrlRes->P(). +/// // cisnienie zbiornika sterujacego double TBrake::GetCRP() { - return GetBRP(); + return GetBRP(); } +/// +/// Default per-step distributor advance — commits any pending flows on the +/// reservoirs and reports zero brake-pipe exchange. Concrete distributors override. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// 0 in the default implementation. // przeplyw z przewodu glowneg -double TBrake::GetPF( double const PP, double const dt, double const Vel ) +double TBrake::GetPF(double const PP, double const dt, double const Vel) { - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - return 0; + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + return 0; } +/// +/// Default high-pressure inflow — 0 (no replenishment from the main line). +/// Distributors with a high-pressure feed override this. +/// // przeplyw z przewodu zasilajacego -double TBrake::GetHPFlow( double const HP, double const dt ) +double TBrake::GetHPFlow(double const HP, double const dt) { - return 0; + return 0; } +/// +/// Returns the piston force from the cylinder pressure (BCA * 100 * P). +/// double TBrake::GetBCF() { - return BCA * 100 * BrakeCyl->P(); + return BCA * 100 * BrakeCyl->P(); } -bool TBrake::SetBDF( int const nBDF ) +/// +/// Sets the brake delay flag (G/P/R/M) only if the requested mode is +/// supported by the vehicle (bit set in BrakeDelays) and differs from the +/// current setting. +/// +/// Requested delay flag (bdelay_*). +/// True on accepted change, false otherwise. +bool TBrake::SetBDF(int const nBDF) { - if (((nBDF & BrakeDelays) == nBDF) && (nBDF != BrakeDelayFlag)) - { - BrakeDelayFlag = nBDF; - return true; - } - else - return false; + if (((nBDF & BrakeDelays) == nBDF) && (nBDF != BrakeDelayFlag)) + { + BrakeDelayFlag = nBDF; + return true; + } + else + return false; } -void TBrake::Releaser( int const state ) +/// Sets or clears the releaser flag in BrakeStatus. +/// 1 to engage, 0 to disengage. +void TBrake::Releaser(int const state) { - BrakeStatus = (BrakeStatus & ~b_rls) | ( state * b_rls ); + BrakeStatus = (BrakeStatus & ~b_rls) | (state * b_rls); } -bool TBrake::Releaser() const { - - return ( ( BrakeStatus & b_rls ) == b_rls ); -} - -void TBrake::SetEPS( double const nEPS ) +/// Returns true if the releaser flag is currently set in BrakeStatus. +bool TBrake::Releaser() const { + + return ((BrakeStatus & b_rls) == b_rls); } -void TBrake::ASB( int const state ) +/// +/// Default EP-state setter — no-op. Overridden by distributors that +/// support the EP brake (TWest, TEStEP1/2, ...). +/// +/// EP intensity. +void TBrake::SetEPS(double const nEPS) {} + +/// +/// Sets the anti-slip brake state flags. Bit 1 of +/// drives b_asb (hold), bit 0 drives b_asb_unbrake (release). +/// +/// Two-bit ASB request. +void TBrake::ASB(int const state) { // 255-b_asb(32) - BrakeStatus = (BrakeStatus & ~b_asb) | ( (state / 2) * b_asb ); - BrakeStatus = (BrakeStatus & ~b_asb_unbrake) | ( (state % 2) * b_asb_unbrake); + BrakeStatus = (BrakeStatus & ~b_asb) | ((state / 2) * b_asb); + BrakeStatus = (BrakeStatus & ~b_asb_unbrake) | ((state % 2) * b_asb_unbrake); } +/// Returns the raw BrakeStatus bitfield. int TBrake::GetStatus() { - return BrakeStatus; + return BrakeStatus; } +/// +/// Returns the accumulated SoundFlag bitfield and clears it, +/// so that each event is reported only once. +/// int TBrake::GetSoundFlag() { - int result = SoundFlag; - SoundFlag = 0; - return result; + int result = SoundFlag; + SoundFlag = 0; + return result; } -void TBrake::SetASBP( double const Press ) +/// Sets the anti-slip brake target pressure. +/// Pressure [bar]. +void TBrake::SetASBP(double const Press) { - ASBP = Press; + ASBP = Press; } +/// +/// Vents the valve pre-chamber and the auxiliary reservoir to zero +/// (for vehicle reset / decoupling). Derived classes also clear their extra reservoirs. +/// void TBrake::ForceEmptiness() { - ValveRes->CreatePress(0); - BrakeRes->CreatePress(0); + ValveRes->CreatePress(0); + BrakeRes->CreatePress(0); - ValveRes->Act(); - BrakeRes->Act(); + ValveRes->Act(); + BrakeRes->Act(); } +/// +/// Bleeds a fraction of the air from the auxiliary reservoir and a tiny +/// fraction from the valve pre-chamber to simulate distributed leaks. +/// Note: experimental — currently limited to these two reservoirs. +/// +/// Fraction of pressure to bleed (0..1). // removes specified amount of air from the reservoirs // NOTE: experimental feature, for now limited only to brake reservoir -void TBrake::ForceLeak( double const Amount ) { +void TBrake::ForceLeak(double const Amount) +{ - BrakeRes->Flow( -Amount * BrakeRes->P() ); - ValveRes->Flow( -Amount * ValveRes->P() * 0.01 ); // this reservoir has hard coded, tiny capacity compared to other parts + BrakeRes->Flow(-Amount * BrakeRes->P()); + ValveRes->Flow(-Amount * ValveRes->P() * 0.01); // this reservoir has hard coded, tiny capacity compared to other parts - BrakeRes->Act(); - ValveRes->Act(); + BrakeRes->Act(); + ValveRes->Act(); } //---WESTINGHOUSE--- -void TWest::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the Westinghouse distributor: pre-charges the valve pre-chamber +/// to PP, the brake cylinder to BP, and the auxiliary reservoir to a midpoint +/// between PP and HPP. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TWest::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TBrake::Init(PP, HPP, LPP, BP, BDF); - ValveRes->CreatePress(PP); - BrakeCyl->CreatePress(BP); - BrakeRes->CreatePress(PP / 2 + HPP / 2); - // BrakeStatus:=3*int(BP>0.1); + TBrake::Init(PP, HPP, LPP, BP, BDF); + ValveRes->CreatePress(PP); + BrakeCyl->CreatePress(BP); + BrakeRes->CreatePress(PP / 2 + HPP / 2); + // BrakeStatus:=3*int(BP>0.1); } -double TWest::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step Westinghouse distributor advance. Drives the b_on/b_hld state +/// machine from the auxiliary-reservoir vs. valve-pre-chamber differential, +/// integrates the auxiliary brake (DCV) and the EP brake against LBP, and +/// computes the resulting flows between brake pipe / pre-chamber / auxiliary +/// reservoir / brake cylinder. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TWest::GetPF(double const PP, double const dt, double const Vel) { - double dv; - double dV1; - double VVP; - double BVP; - double CVP; - double BCP; - double temp; + double dv; + double dV1; + double VVP; + double BVP; + double CVP; + double BCP; + double temp; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - CVP = BrakeCyl->P(); - BCP = BrakeCyl->P(); + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + CVP = BrakeCyl->P(); + BCP = BrakeCyl->P(); - if ((BrakeStatus & b_hld) == b_hld) - if ((VVP + 0.03 < BVP)) - BrakeStatus |= b_on; - else if ((VVP > BVP + 0.1)) - BrakeStatus &= ~(b_on | b_hld); - else if ((VVP > BVP)) - BrakeStatus &= ~b_on; - else - ; - else if ((VVP + 0.25 < BVP)) - BrakeStatus |= (b_on | b_hld); + if ((BrakeStatus & b_hld) == b_hld) + if ((VVP + 0.03 < BVP)) + BrakeStatus |= b_on; + else if ((VVP > BVP + 0.1)) + BrakeStatus &= ~(b_on | b_hld); + else if ((VVP > BVP)) + BrakeStatus &= ~b_on; + else + ; + else if ((VVP + 0.25 < BVP)) + BrakeStatus |= (b_on | b_hld); - if (((BrakeStatus & b_hld) == b_off) && (!DCV)) - dv = PF(0, CVP, 0.0068 * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); + if (((BrakeStatus & b_hld) == b_off) && (!DCV)) + dv = PF(0, CVP, 0.0068 * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); - if ((BCP > LBP + 0.01) && (DCV)) - dv = PF(0, CVP, 0.1 * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); - - if ((BrakeStatus & b_rls) == b_rls) //odluzniacz + if ((BCP > LBP + 0.01) && (DCV)) dv = PF(0, CVP, 0.1 * SizeBC) * dt; else dv = 0; BrakeCyl->Flow(-dv); - // hamulec EP - temp = BVP * int(EPS > 0); - dv = PF(temp, LBP, 0.0015) * dt * EPS * EPS * int(LBP * EPS < MaxBP * LoadC); - LBP = LBP - dv; - dv = 0; + if ((BrakeStatus & b_rls) == b_rls) // odluzniacz + dv = PF(0, CVP, 0.1 * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); - // przeplyw ZP <-> silowniki - if (((BrakeStatus & b_on) == b_on) && ((TareBP < 0.1) || (BCP < MaxBP * LoadC))) - if ((BVP > LBP)) - { - DCV = false; - dv = PF(BVP, CVP, 0.017 * SizeBC) * dt; - } - else - dv = 0; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); - if ((DCV)) - dVP = PF(LBP, BCP, 0.01 * SizeBC) * dt; - else - dVP = 0; - BrakeCyl->Flow(-dVP); - if ((dVP > 0)) - dVP = 0; - // przeplyw ZP <-> rozdzielacz - if (((BrakeStatus & b_hld) == b_off)) - dv = PF(BVP, VVP, 0.0011 * SizeBR) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dv * 0.95; - ValveRes->Flow(-0.05 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01 * SizeBR) * dt; - ValveRes->Flow(-dv); + // hamulec EP + temp = BVP * int(EPS > 0); + dv = PF(temp, LBP, 0.0015) * dt * EPS * EPS * int(LBP * EPS < MaxBP * LoadC); + LBP = LBP - dv; + dv = 0; - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - return dv - dV1; + // przeplyw ZP <-> silowniki + if (((BrakeStatus & b_on) == b_on) && ((TareBP < 0.1) || (BCP < MaxBP * LoadC))) + if ((BVP > LBP)) + { + DCV = false; + dv = PF(BVP, CVP, 0.017 * SizeBC) * dt; + } + else + dv = 0; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); + if ((DCV)) + dVP = PF(LBP, BCP, 0.01 * SizeBC) * dt; + else + dVP = 0; + BrakeCyl->Flow(-dVP); + if ((dVP > 0)) + dVP = 0; + // przeplyw ZP <-> rozdzielacz + if (((BrakeStatus & b_hld) == b_off)) + dv = PF(BVP, VVP, 0.0011 * SizeBR) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dv * 0.95; + ValveRes->Flow(-0.05 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01 * SizeBR) * dt; + ValveRes->Flow(-dv); + + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + return dv - dV1; } -double TWest::GetHPFlow( double const HP, double const dt ) +/// +/// Returns the high-pressure inflow accumulated by the previous GetPF call +/// (the dVP variable) — used by the host to bookkeep main-reservoir consumption. +/// +double TWest::GetHPFlow(double const HP, double const dt) { - return dVP; + return dVP; } -void TWest::SetLBP( double const P ) +/// +/// Sets the auxiliary brake target pressure. If P exceeds the current +/// cylinder pressure, the double check valve (DCV) is engaged so that LBP +/// drives the cylinder. +/// +/// Auxiliary brake pressure [bar]. +void TWest::SetLBP(double const P) { - LBP = P; - if (P > BrakeCyl->P()) - // begin - DCV = true; - // end - // else - // LBP:=P; + LBP = P; + if (P > BrakeCyl->P()) + // begin + DCV = true; + // end + // else + // LBP:=P; } -void TWest::SetEPS( double const nEPS ) +/// +/// Sets the EP intensity. A positive value engages the DCV; a zero value +/// while the previous EPS was non-zero latches LBP from the cylinder +/// (or clears it when below a threshold), modelling EP-release hysteresis. +/// +/// New EP intensity. +void TWest::SetEPS(double const nEPS) { - double BCP; + double BCP; - BCP = BrakeCyl->P(); - if (nEPS > 0) - DCV = true; - else if (nEPS == 0) - { - if ((EPS != 0)) - { - if ((LBP > 0.4)) - LBP = BrakeCyl->P(); - if ((LBP < 0.15)) - LBP = 0; - } - } - EPS = nEPS; + BCP = BrakeCyl->P(); + if (nEPS > 0) + DCV = true; + else if (nEPS == 0) + { + if ((EPS != 0)) + { + if ((LBP > 0.4)) + LBP = BrakeCyl->P(); + if ((LBP < 0.15)) + LBP = 0; + } + } + EPS = nEPS; } -void TWest::PLC( double const mass ) +/// +/// Recomputes the load-weighing coefficient LoadC from the current vehicle +/// mass: linear interpolation between TareBP/MaxBP for masses in [TareM, LoadM], +/// and 1.0 for masses at or above LoadM. +/// +/// Current vehicle mass. +void TWest::PLC(double const mass) { - LoadC = 1 + - int(mass < LoadM) * - ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); + LoadC = 1 + int(mass < LoadM) * ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); } -void TWest::SetLP( double const TM, double const LM, double const TBP ) +/// +/// Stores the load-weighing parameters: tare mass, loaded mass and the +/// cylinder pressure that should be reached for the tare mass. +/// +/// Tare (empty) mass. +/// Loaded mass. +/// Tare-mass cylinder pressure. +void TWest::SetLP(double const TM, double const LM, double const TBP) { - TareM = TM; - LoadM = LM; - TareBP = TBP; + TareM = TM; + LoadM = LM; + TareBP = TBP; } //---OERLIKON EST4--- -void TESt::CheckReleaser( double const dt ) +/// +/// Implements the releaser logic: while engaged, vents the control reservoir +/// (CntrlRes) toward the lower of valve pre-chamber / auxiliary reservoir +/// (with a 0.05 bar margin); disengages once CntrlRes has fallen below VVP. +/// +/// Time step [s]. +void TESt::CheckReleaser(double const dt) { - double VVP = std::min(ValveRes->P(), BrakeRes->P() + 0.05); - double CVP = CntrlRes->P() - 0.0; + double VVP = std::min(ValveRes->P(), BrakeRes->P() + 0.05); + double CVP = CntrlRes->P() - 0.0; - // odluzniacz - if ((BrakeStatus & b_rls) == b_rls) - if ((CVP - VVP < 0)) - BrakeStatus &= ~b_rls; - else - { - CntrlRes->Flow(+PF(CVP, 0, 0.1) * dt); - } + // odluzniacz + if ((BrakeStatus & b_rls) == b_rls) + if ((CVP - VVP < 0)) + BrakeStatus &= ~b_rls; + else + { + CntrlRes->Flow(+PF(CVP, 0, 0.1) * dt); + } } -void TESt::CheckState( double const BCP, double &dV1 ) { - - double const VVP { ValveRes->P() }; - double const BVP { BrakeRes->P() }; - double const CVP { CntrlRes->P() }; - - // sprawdzanie stanu - if( BCP > 0.25 ) { - - if( ( BrakeStatus & b_hld ) == b_hld ) { - - if( ( VVP + 0.003 + BCP / BVM ) < CVP ) { - // hamowanie stopniowe - BrakeStatus |= b_on; - } - else { - if( ( VVP + BCP / BVM ) > CVP ) { - // zatrzymanie napelaniania - BrakeStatus &= ~b_on; - } - if( ( VVP - 0.003 + ( BCP - 0.1 ) / BVM ) > CVP ) { - // luzowanie - BrakeStatus &= ~( b_on | b_hld ); - } - } - } - else { - - if( ( VVP + BCP / BVM < CVP ) - && ( ( CVP - VVP ) * BVM > 0.25 ) ) { - // zatrzymanie luzowanie - BrakeStatus |= b_hld; - } - } - } - else { - - if( VVP + 0.1 < CVP ) { - // poczatek hamowania - if( ( BrakeStatus & b_hld ) == 0 ) { - // przyspieszacz - ValveRes->CreatePress( 0.02 * VVP ); - SoundFlag |= sf_Acc; - ValveRes->Act(); - } - BrakeStatus |= ( b_on | b_hld ); - } - } - - if( ( BrakeStatus & b_hld ) == 0 ) { - SoundFlag |= sf_CylU; - } -} - -double TESt::CVs( double const BP ) +/// +/// Drives the BrakeStatus state machine (b_on / b_hld) of the ESt main slide +/// valve from the current valve pre-chamber, brake cylinder and control +/// reservoir pressures. Triggers the accelerator (sf_Acc) at the start of +/// braking and the cylinder-vent sound flag (sf_CylU) on release. +/// +/// Brake cylinder (or impulse-chamber) pressure. +/// In/out brake-pipe flow correction (unused in this base impl). +void TESt::CheckState(double const BCP, double &dV1) { - double VVP; - double BVP; - double CVP; - BVP = BrakeRes->P(); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); + double const VVP{ValveRes->P()}; + double const BVP{BrakeRes->P()}; + double const CVP{CntrlRes->P()}; - // przeplyw ZS <-> PG - if ((VVP < CVP - 0.12) || (BVP < CVP - 0.3) || (BP > 0.4)) - return 0; - else if ((VVP > CVP + 0.4)) - if ((BVP > CVP + 0.2)) - return 0.23; - else - return 0.05; - else if ((BVP > CVP - 0.1)) - return 1; - else - return 0.3; + // sprawdzanie stanu + if (BCP > 0.25) + { + + if ((BrakeStatus & b_hld) == b_hld) + { + + if ((VVP + 0.003 + BCP / BVM) < CVP) + { + // hamowanie stopniowe + BrakeStatus |= b_on; + } + else + { + if ((VVP + BCP / BVM) > CVP) + { + // zatrzymanie napelaniania + BrakeStatus &= ~b_on; + } + if ((VVP - 0.003 + (BCP - 0.1) / BVM) > CVP) + { + // luzowanie + BrakeStatus &= ~(b_on | b_hld); + } + } + } + else + { + + if ((VVP + BCP / BVM < CVP) && ((CVP - VVP) * BVM > 0.25)) + { + // zatrzymanie luzowanie + BrakeStatus |= b_hld; + } + } + } + else + { + + if (VVP + 0.1 < CVP) + { + // poczatek hamowania + if ((BrakeStatus & b_hld) == 0) + { + // przyspieszacz + ValveRes->CreatePress(0.02 * VVP); + SoundFlag |= sf_Acc; + ValveRes->Act(); + } + BrakeStatus |= (b_on | b_hld); + } + } + + if ((BrakeStatus & b_hld) == 0) + { + SoundFlag |= sf_CylU; + } } -double TESt::BVs( double const BCP ) +/// +/// Returns the dimensionless opening factor of the ZS-filling slide valve +/// (control reservoir <-> brake pipe) for the current pre-chamber/auxiliary +/// reservoir state and brake-cylinder pressure. +/// +/// Brake cylinder (or impulse) pressure. +/// Opening coefficient (0 closed, 1 fully open). +double TESt::CVs(double const BP) { - double VVP; - double BVP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); + BVP = BrakeRes->P(); + CVP = CntrlRes->P(); + VVP = ValveRes->P(); - // przeplyw ZP <-> rozdzielacz - if ((BVP < CVP - 0.3)) - return 0.6; - else if ((BCP < 0.5)) - if ((VVP > CVP + 0.4)) - return 0.1; - else - return 0.3; - else - return 0; + // przeplyw ZS <-> PG + if ((VVP < CVP - 0.12) || (BVP < CVP - 0.3) || (BP > 0.4)) + return 0; + else if ((VVP > CVP + 0.4)) + if ((BVP > CVP + 0.2)) + return 0.23; + else + return 0.05; + else if ((BVP > CVP - 0.1)) + return 1; + else + return 0.3; } -double TESt::GetPF( double const PP, double const dt, double const Vel ) +/// +/// Returns the dimensionless opening factor of the ZP-filling slide valve +/// (auxiliary reservoir <-> valve pre-chamber) as a function of brake +/// cylinder pressure, distinguishing initial filling, lap and full-pressure regions. +/// +/// Brake cylinder pressure. +/// Opening coefficient. +double TESt::BVs(double const BCP) { - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - BCP = BrakeCyl->P(); - CVP = CntrlRes->P() - 0.0; + BVP = BrakeRes->P(); + CVP = CntrlRes->P(); + VVP = ValveRes->P(); - dv = 0; - dV1 = 0; - - // sprawdzanie stanu - CheckState(BCP, dV1); - CheckReleaser(dt); - - CVP = CntrlRes->P(); - VVP = ValveRes->P(); - // przeplyw ZS <-> PG - temp = CVs(BCP); - dv = PF(CVP, VVP, 0.0015 * temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; - - // luzowanie - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.0058 * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); - - // przeplyw ZP <-> silowniki - if ((BrakeStatus & b_on) == b_on) - dv = PF(BVP, BCP, 0.016 * SizeBC) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); - - // przeplyw ZP <-> rozdzielacz - temp = BVs(BCP); - // if(BrakeStatus and b_hld)=b_off then - if ((VVP - 0.05 > BVP)) - dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dV1 + dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01) * dt; - ValveRes->Flow(-dv); - - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return dv - dV1; + // przeplyw ZP <-> rozdzielacz + if ((BVP < CVP - 0.3)) + return 0.6; + else if ((BCP < 0.5)) + if ((VVP > CVP + 0.4)) + return 0.1; + else + return 0.3; + else + return 0; } -void TESt::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// One-step Oerlikon ESt distributor advance: runs CheckState/CheckReleaser, +/// integrates the ZS <-> PG, ZP <-> cylinder, ZP <-> pre-chamber and +/// PG <-> pre-chamber flows, and returns the net brake-pipe exchange. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TESt::GetPF(double const PP, double const dt, double const Vel) { - TBrake::Init(PP, HPP, LPP, BP, BDF); - ValveRes->CreatePress(PP); - BrakeCyl->CreatePress(BP); - BrakeRes->CreatePress(PP); - CntrlRes->CreateCap(15); - CntrlRes->CreatePress(HPP); - BrakeStatus = b_off; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; - BVM = 1.0 / (HPP - LPP) * MaxBP; + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + BCP = BrakeCyl->P(); + CVP = CntrlRes->P() - 0.0; - BrakeDelayFlag = BDF; + dv = 0; + dV1 = 0; + + // sprawdzanie stanu + CheckState(BCP, dV1); + CheckReleaser(dt); + + CVP = CntrlRes->P(); + VVP = ValveRes->P(); + // przeplyw ZS <-> PG + temp = CVs(BCP); + dv = PF(CVP, VVP, 0.0015 * temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; + + // luzowanie + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.0058 * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); + + // przeplyw ZP <-> silowniki + if ((BrakeStatus & b_on) == b_on) + dv = PF(BVP, BCP, 0.016 * SizeBC) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); + + // przeplyw ZP <-> rozdzielacz + temp = BVs(BCP); + // if(BrakeStatus and b_hld)=b_off then + if ((VVP - 0.05 > BVP)) + dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dV1 + dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01) * dt; + ValveRes->Flow(-dv); + + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return dv - dV1; } -void TESt::EStParams( double const i_crc ) +/// +/// Initialises the ESt distributor: pre-charges valve / brake / control +/// reservoirs (the ZS is sized at 15 l), clears BrakeStatus and computes the +/// brake-pipe to brake-cylinder transmission ratio (BVM = MaxBP / (HPP-LPP)). +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TESt::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { + TBrake::Init(PP, HPP, LPP, BP, BDF); + ValveRes->CreatePress(PP); + BrakeCyl->CreatePress(BP); + BrakeRes->CreatePress(PP); + CntrlRes->CreateCap(15); + CntrlRes->CreatePress(HPP); + BrakeStatus = b_off; + + BVM = 1.0 / (HPP - LPP) * MaxBP; + + BrakeDelayFlag = BDF; } +/// +/// Stub for setting ESt-specific characteristic parameters; reserved for +/// derived variants and currently a no-op. +/// +/// Characteristic value. +void TESt::EStParams(double const i_crc) {} + +/// Returns the control reservoir (ZS) pressure. double TESt::GetCRP() { - return CntrlRes->P(); + return CntrlRes->P(); } -void TESt::ForceEmptiness() { +/// +/// Vents the valve, brake and control reservoirs to zero +/// (used on vehicle reset / decoupling). +/// +void TESt::ForceEmptiness() +{ - ValveRes->CreatePress( 0 ); - BrakeRes->CreatePress( 0 ); - CntrlRes->CreatePress( 0 ); + ValveRes->CreatePress(0); + BrakeRes->CreatePress(0); + CntrlRes->CreatePress(0); - ValveRes->Act(); - BrakeRes->Act(); - CntrlRes->Act(); + ValveRes->Act(); + BrakeRes->Act(); + CntrlRes->Act(); } //---EP2--- -void TEStEP2::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the EP2-equipped distributor: chains TLSt::Init, sizes the +/// 1-litre impulse chamber (ImplsRes), pre-charges it to BP, sets the +/// auxiliary reservoir to PP and locks the brake delay to P. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag (overridden to P). +void TEStEP2::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TLSt::Init(PP, HPP, LPP, BP, BDF); - ImplsRes->CreateCap(1); - ImplsRes->CreatePress(BP); + TLSt::Init(PP, HPP, LPP, BP, BDF); + ImplsRes->CreateCap(1); + ImplsRes->CreatePress(BP); - BrakeRes->CreatePress(PP); + BrakeRes->CreatePress(PP); - BrakeDelayFlag = bdelay_P; - BrakeDelays = bdelay_P; + BrakeDelayFlag = bdelay_P; + BrakeDelays = bdelay_P; } -double TEStEP2::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for the ESt + EP2 combination. Drives the +/// pneumatic state machine via the impulse chamber, runs the EP brake +/// integrator () and computes the cylinder fill/release +/// against the higher of the impulse-chamber and EP-driven LBP target. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TEStEP2::GetPF(double const PP, double const dt, double const Vel) { - double result; - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; + double result; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - BCP = ImplsRes->P(); - CVP = CntrlRes->P(); // 110115 - konsultacje warszawa1 + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + BCP = ImplsRes->P(); + CVP = CntrlRes->P(); // 110115 - konsultacje warszawa1 - dv = 0; - dV1 = 0; + dv = 0; + dV1 = 0; - // odluzniacz - CheckReleaser(dt); + // odluzniacz + CheckReleaser(dt); - // sprawdzanie stanu - if (((BrakeStatus & b_hld) == b_hld) && (BCP > 0.25)) - if ((VVP + 0.003 + BCP / BVM < CVP - 0.12)) - BrakeStatus |= b_on; // hamowanie stopniowe; - else if ((VVP - 0.003 + BCP / BVM > CVP - 0.12)) - BrakeStatus &= ~(b_on | b_hld); // luzowanie; - else if ((VVP + BCP / BVM > CVP - 0.12)) - BrakeStatus &= ~b_on; // zatrzymanie napelaniania; - else - ; - else if ((VVP + 0.10 < CVP - 0.12) && (BCP < 0.25)) // poczatek hamowania - { - // if ((BrakeStatus & 1) == 0) - //{ - // // ValveRes.CreatePress(0.5*VVP); //110115 - konsultacje warszawa1 - // // SoundFlag:=SoundFlag or sf_Acc; - // // ValveRes.Act; - //} - BrakeStatus |= (b_on | b_hld); - } - else if ((VVP + BCP / BVM < CVP - 0.12) && (BCP > 0.25)) // zatrzymanie luzowanie - BrakeStatus |= b_hld; + // sprawdzanie stanu + if (((BrakeStatus & b_hld) == b_hld) && (BCP > 0.25)) + if ((VVP + 0.003 + BCP / BVM < CVP - 0.12)) + BrakeStatus |= b_on; // hamowanie stopniowe; + else if ((VVP - 0.003 + BCP / BVM > CVP - 0.12)) + BrakeStatus &= ~(b_on | b_hld); // luzowanie; + else if ((VVP + BCP / BVM > CVP - 0.12)) + BrakeStatus &= ~b_on; // zatrzymanie napelaniania; + else + ; + else if ((VVP + 0.10 < CVP - 0.12) && (BCP < 0.25)) // poczatek hamowania + { + // if ((BrakeStatus & 1) == 0) + //{ + // // ValveRes.CreatePress(0.5*VVP); //110115 - konsultacje warszawa1 + // // SoundFlag:=SoundFlag or sf_Acc; + // // ValveRes.Act; + //} + BrakeStatus |= (b_on | b_hld); + } + else if ((VVP + BCP / BVM < CVP - 0.12) && (BCP > 0.25)) // zatrzymanie luzowanie + BrakeStatus |= b_hld; - if( ( BrakeStatus & b_hld ) == 0 ) { - SoundFlag |= sf_CylU; - } + if ((BrakeStatus & b_hld) == 0) + { + SoundFlag |= sf_CylU; + } - // przeplyw ZS <-> PG - if ((BVP < CVP - 0.2) || (BrakeStatus != b_off) || (BCP > 0.25)) - temp = 0; - else if ((VVP > CVP + 0.4)) - temp = 0.1; - else - temp = 0.5; + // przeplyw ZS <-> PG + if ((BVP < CVP - 0.2) || (BrakeStatus != b_off) || (BCP > 0.25)) + temp = 0; + else if ((VVP > CVP + 0.4)) + temp = 0.1; + else + temp = 0.5; - dv = PF(CVP, VVP, 0.0015 * temp / 1.8) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + dv = PF(CVP, VVP, 0.0015 * temp / 1.8) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // hamulec EP + // hamulec EP EPCalc(dt); - // luzowanie KI - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.00083) * dt; - else - dv = 0; - ImplsRes->Flow(-dv); - // przeplyw ZP <-> KI - if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP * LoadC)) - dv = PF(BVP, BCP, 0.0006) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - ImplsRes->Flow(-dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01 * SizeBR) * dt; - ValveRes->Flow(-dv); + // luzowanie KI + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.00083) * dt; + else + dv = 0; + ImplsRes->Flow(-dv); + // przeplyw ZP <-> KI + if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP * LoadC)) + dv = PF(BVP, BCP, 0.0006) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + ImplsRes->Flow(-dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01 * SizeBR) * dt; + ValveRes->Flow(-dv); - result = dv - dV1; + result = dv - dV1; - temp = Max0R(BCP, LBP); + temp = Max0R(BCP, LBP); - if ((ImplsRes->P() > LBP + 0.01)) - LBP = 0; + if ((ImplsRes->P() > LBP + 0.01)) + LBP = 0; - // luzowanie CH - if ((BrakeCyl->P() > temp + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.05)) - dv = PF(0, BrakeCyl->P(), 0.25 * SizeBC * (0.01 + (BrakeCyl->P() - temp))) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); - // przeplyw ZP <-> CH - if ((BrakeCyl->P() < temp - 0.005) && (Max0R(ImplsRes->P(), 8 * LBP) > 0.10) && - (Max0R(BCP, LBP) < MaxBP * LoadC)) - dv = PF(BVP, BrakeCyl->P(), 0.35 * SizeBC * (0.01 - (BrakeCyl->P() - temp))) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); + // luzowanie CH + if ((BrakeCyl->P() > temp + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.05)) + dv = PF(0, BrakeCyl->P(), 0.25 * SizeBC * (0.01 + (BrakeCyl->P() - temp))) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); + // przeplyw ZP <-> CH + if ((BrakeCyl->P() < temp - 0.005) && (Max0R(ImplsRes->P(), 8 * LBP) > 0.10) && (Max0R(BCP, LBP) < MaxBP * LoadC)) + dv = PF(BVP, BrakeCyl->P(), 0.35 * SizeBC * (0.01 - (BrakeCyl->P() - temp))) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); - ImplsRes->Act(); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return result; + ImplsRes->Act(); + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return result; } -void TEStEP2::PLC( double const mass ) +/// +/// Recomputes the load-weighing coefficient LoadC for the current vehicle +/// mass (linear between TareBP/MaxBP for TareM..LoadM, capped at 1.0). +/// +/// Current vehicle mass. +void TEStEP2::PLC(double const mass) { - LoadC = 1 + - int(mass < LoadM) * - ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); + LoadC = 1 + int(mass < LoadM) * ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); } -void TEStEP2::SetEPS( double const nEPS ) +/// +/// Sets the EP intensity. When the EP is energised and the pneumatic cylinder +/// pressure exceeds the EP target, latches the EP target up to the cylinder +/// pressure to avoid releasing the pneumatic brake while EP is active. +/// +/// New EP intensity. +void TEStEP2::SetEPS(double const nEPS) { - EPS = nEPS; - if ((EPS > 0) && (LBP + 0.01 < BrakeCyl->P())) - LBP = BrakeCyl->P(); + EPS = nEPS; + if ((EPS > 0) && (LBP + 0.01 < BrakeCyl->P())) + LBP = BrakeCyl->P(); } -void TEStEP2::SetLP( double const TM, double const LM, double const TBP ) +/// Stores the load-weighing parameters. +/// Tare (empty) mass. +/// Loaded mass. +/// Tare-mass cylinder pressure. +void TEStEP2::SetLP(double const TM, double const LM, double const TBP) { - TareM = TM; - LoadM = LM; - TareBP = TBP; + TareM = TM; + LoadM = LM; + TareBP = TBP; } +/// +/// EP2 EP-flow integrator: drives LBP toward the auxiliary-reservoir pressure +/// when EPS > 0 (apply) or toward 0 when EPS < 0 (release), with a +/// quadratic-in-EPS rate and a load-weighing-aware ceiling at MaxBP * LoadC. +/// +/// Time step [s]. void TEStEP2::EPCalc(double dt) { double temp = BrakeRes->P() * int(EPS > 0); - double dv = PF(temp, LBP, 0.00053 + 0.00060 * int(EPS < 0)) * dt * EPS * EPS * - int(LBP * EPS < MaxBP * LoadC); + double dv = PF(temp, LBP, 0.00053 + 0.00060 * int(EPS < 0)) * dt * EPS * EPS * int(LBP * EPS < MaxBP * LoadC); LBP = LBP - dv; } - +/// +/// EP1 (proportional) EP-flow integrator: interprets the fractional part of +/// EPS as a continuous EP target and drives LBP toward MaxBP * LoadC * frac +/// (clamped to the auxiliary reservoir pressure), softening the valve +/// opening with a clamped error term S. +/// +/// Time step [s]. void TEStEP1::EPCalc(double dt) { - double temp = EPS - std::floor(EPS); //część ułamkowa jest hamulcem EP - double LBPLim = Min0R(MaxBP * LoadC * temp, BrakeRes->P()); //do czego dążymy - double S = 10 * clamp(LBPLim - LBP, -0.1, 0.1); //przymykanie zaworku - double dv = PF(( S > 0 ? BrakeRes->P() : 0 ), LBP, abs(S)*(0.00053 + 0.00060 * int(S < 0))) * dt; //przepływ + double temp = EPS - std::floor(EPS); // część ułamkowa jest hamulcem EP + double LBPLim = Min0R(MaxBP * LoadC * temp, BrakeRes->P()); // do czego dążymy + double S = 10 * clamp(LBPLim - LBP, -0.1, 0.1); // przymykanie zaworku + double dv = PF((S > 0 ? BrakeRes->P() : 0), LBP, abs(S) * (0.00053 + 0.00060 * int(S < 0))) * dt; // przepływ LBP = LBP - dv; } -void TEStEP1::SetEPS( double const nEPS ) +/// +/// Stores the EP intensity for the EP1 (proportional) variant. +/// The fractional part is read by as the proportional set-point. +/// +/// EP intensity. +void TEStEP1::SetEPS(double const nEPS) { - EPS = nEPS; + EPS = nEPS; } //---EST3-- -double TESt3::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for ESt3. Identical structure to TESt::GetPF +/// but with G/P-dependent fill/release curves on the brake cylinder +/// (slower fill/faster release on the goods setting at low cylinder pressures). +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TESt3::GetPF(double const PP, double const dt, double const Vel) { - double BVP{ BrakeRes->P() }; - double VVP{ ValveRes->P() }; - double BCP{ BrakeCyl->P() }; - double CVP{ CntrlRes->P() - 0.0 }; + double BVP{BrakeRes->P()}; + double VVP{ValveRes->P()}; + double BCP{BrakeCyl->P()}; + double CVP{CntrlRes->P() - 0.0}; - double dv{ 0.0 }; - double dV1{ 0.0 }; + double dv{0.0}; + double dV1{0.0}; - // sprawdzanie stanu - CheckState(BCP, dV1); - CheckReleaser(dt); + // sprawdzanie stanu + CheckState(BCP, dV1); + CheckReleaser(dt); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); - // przeplyw ZS <-> PG - double temp = CVs(BCP); - dv = PF(CVP, VVP, 0.0015 * temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + CVP = CntrlRes->P(); + VVP = ValveRes->P(); + // przeplyw ZS <-> PG + double temp = CVs(BCP); + dv = PF(CVP, VVP, 0.0015 * temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // luzowanie - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.0042 * (1.37 - (BrakeDelayFlag == bdelay_G ? 1.0 : 0.0)) * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); - // przeplyw ZP <-> silowniki - if ((BrakeStatus & b_on) == b_on) - dv = PF( - BVP, - BCP, - 0.017 * - ( 1.00 + ( ((BCP < 0.58) && (BrakeDelayFlag == bdelay_G)) ? 1.0 : 0.0 ) ) * - ( 1.13 - ( ((BCP > 0.60) && (BrakeDelayFlag == bdelay_G)) ? 1.0 : 0.0 ) ) * SizeBC - ) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); - // przeplyw ZP <-> rozdzielacz - temp = BVs(BCP); - if ((VVP - 0.05 > BVP)) - dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 += dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01) * dt; - ValveRes->Flow(-dv); + // luzowanie + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.0042 * (1.37 - (BrakeDelayFlag == bdelay_G ? 1.0 : 0.0)) * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); + // przeplyw ZP <-> silowniki + if ((BrakeStatus & b_on) == b_on) + dv = PF(BVP, BCP, 0.017 * (1.00 + (((BCP < 0.58) && (BrakeDelayFlag == bdelay_G)) ? 1.0 : 0.0)) * (1.13 - (((BCP > 0.60) && (BrakeDelayFlag == bdelay_G)) ? 1.0 : 0.0)) * SizeBC) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); + // przeplyw ZP <-> rozdzielacz + temp = BVs(BCP); + if ((VVP - 0.05 > BVP)) + dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 += dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01) * dt; + ValveRes->Flow(-dv); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return dv - dV1; + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return dv - dV1; } //---EST4-RAPID--- -double TESt4R::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for ESt4 with the rapid (R) step. Updates the +/// hysteretic RapidStatus latch from speed (R bit set, > 70 km/h or +/// hysteresis above 55 km/h), smooths the rapid coefficient (RapidTemp) and +/// computes the cylinder fill/vent against the impulse-chamber pressure. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TESt4R::GetPF(double const PP, double const dt, double const Vel) { - double result; - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; + double result; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - BCP = ImplsRes->P(); - CVP = CntrlRes->P(); + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + BCP = ImplsRes->P(); + CVP = CntrlRes->P(); - dv = 0; - dV1 = 0; + dv = 0; + dV1 = 0; - // sprawdzanie stanu - CheckState(BCP, dV1); - CheckReleaser(dt); + // sprawdzanie stanu + CheckState(BCP, dV1); + CheckReleaser(dt); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); - // przeplyw ZS <-> PG - temp = CVs(BCP); - dv = PF(CVP, VVP, 0.0015 * temp / 1.8) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + CVP = CntrlRes->P(); + VVP = ValveRes->P(); + // przeplyw ZS <-> PG + temp = CVs(BCP); + dv = PF(CVP, VVP, 0.0015 * temp / 1.8) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // luzowanie KI - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.00037 * 1.14 * 15 / 19) * dt; - else - dv = 0; - ImplsRes->Flow(-dv); - // przeplyw ZP <-> KI - if ((BrakeStatus & b_on) == b_on) - dv = PF(BVP, BCP, 0.0014) * dt; - else - dv = 0; - // BrakeRes->Flow(dV); - ImplsRes->Flow(-dv); - // przeplyw ZP <-> rozdzielacz - temp = BVs(BCP); - if ((BVP < VVP - 0.05)) // or((PPFlow(dv); - dV1 = dV1 + dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01 * SizeBR) * dt; - ValveRes->Flow(-dv); + // luzowanie KI + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.00037 * 1.14 * 15 / 19) * dt; + else + dv = 0; + ImplsRes->Flow(-dv); + // przeplyw ZP <-> KI + if ((BrakeStatus & b_on) == b_on) + dv = PF(BVP, BCP, 0.0014) * dt; + else + dv = 0; + // BrakeRes->Flow(dV); + ImplsRes->Flow(-dv); + // przeplyw ZP <-> rozdzielacz + temp = BVs(BCP); + if ((BVP < VVP - 0.05)) // or((PPFlow(dv); + dV1 = dV1 + dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01 * SizeBR) * dt; + ValveRes->Flow(-dv); - result = dv - dV1; + result = dv - dV1; - RapidStatus = ( BrakeDelayFlag == bdelay_R ) - && ( ( ( Vel > 55 ) && ( RapidStatus == true ) ) - || ( Vel > 70 ) ); + RapidStatus = (BrakeDelayFlag == bdelay_R) && (((Vel > 55) && (RapidStatus == true)) || (Vel > 70)); - RapidTemp = RapidTemp + (0.9 * int(RapidStatus) - RapidTemp) * dt / 2; - temp = 1.9 - RapidTemp; - if (((BrakeStatus & b_asb) == b_asb)) - temp = 1000; - // luzowanie CH - if ((BrakeCyl->P() * temp > ImplsRes->P() + 0.005) || (ImplsRes->P() < 0.25)) - if (((BrakeStatus & b_asb) == b_asb)) - dv = PFVd(BrakeCyl->P(), 0, 0.115 * SizeBC * 4, ImplsRes->P() / temp) * dt; - else - dv = PFVd(BrakeCyl->P(), 0, 0.115 * SizeBC, ImplsRes->P() / temp) * dt; - // dV:=PF(0,BrakeCyl.P,0.115*sizeBC/2)*dt - // dV:=PFVd(BrakeCyl.P,0,0.015*sizeBC/2,ImplsRes.P/temp)*dt - else - dv = 0; - BrakeCyl->Flow(-dv); - // przeplyw ZP <-> CH - if ((BrakeCyl->P() * temp < ImplsRes->P() - 0.005) && (ImplsRes->P() > 0.3)) - // dV:=PFVa(BVP,BrakeCyl.P,0.020*sizeBC,ImplsRes.P/temp)*dt - dv = PFVa(BVP, BrakeCyl->P(), 0.60 * SizeBC, ImplsRes->P() / temp) * dt; - else - dv = 0; - BrakeRes->Flow(-dv); - BrakeCyl->Flow(+dv); + RapidTemp = RapidTemp + (0.9 * int(RapidStatus) - RapidTemp) * dt / 2; + temp = 1.9 - RapidTemp; + if (((BrakeStatus & b_asb) == b_asb)) + temp = 1000; + // luzowanie CH + if ((BrakeCyl->P() * temp > ImplsRes->P() + 0.005) || (ImplsRes->P() < 0.25)) + if (((BrakeStatus & b_asb) == b_asb)) + dv = PFVd(BrakeCyl->P(), 0, 0.115 * SizeBC * 4, ImplsRes->P() / temp) * dt; + else + dv = PFVd(BrakeCyl->P(), 0, 0.115 * SizeBC, ImplsRes->P() / temp) * dt; + // dV:=PF(0,BrakeCyl.P,0.115*sizeBC/2)*dt + // dV:=PFVd(BrakeCyl.P,0,0.015*sizeBC/2,ImplsRes.P/temp)*dt + else + dv = 0; + BrakeCyl->Flow(-dv); + // przeplyw ZP <-> CH + if ((BrakeCyl->P() * temp < ImplsRes->P() - 0.005) && (ImplsRes->P() > 0.3)) + // dV:=PFVa(BVP,BrakeCyl.P,0.020*sizeBC,ImplsRes.P/temp)*dt + dv = PFVa(BVP, BrakeCyl->P(), 0.60 * SizeBC, ImplsRes->P() / temp) * dt; + else + dv = 0; + BrakeRes->Flow(-dv); + BrakeCyl->Flow(+dv); - ImplsRes->Act(); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return result; + ImplsRes->Act(); + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return result; } -void TESt4R::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the ESt4R: chains TESt::Init, sizes the impulse chamber to 1 l +/// and pre-charges it to BP, then selects the rapid (R) brake delay. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag (overridden to R). +void TESt4R::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TESt::Init(PP, HPP, LPP, BP, BDF); - ImplsRes->CreateCap(1); - ImplsRes->CreatePress(BP); + TESt::Init(PP, HPP, LPP, BP, BDF); + ImplsRes->CreateCap(1); + ImplsRes->CreatePress(BP); - BrakeDelayFlag = bdelay_R; + BrakeDelayFlag = bdelay_R; } //---EST3/AL2--- -double TESt3AL2::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for ESt3 with AL2 load-weighing equipment. +/// Drives the impulse chamber (KI) with G/P-dependent flow rates and feeds +/// the load relay output (BrakeCyl pressure scaled by LoadC) to the cylinder. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TESt3AL2::GetPF(double const PP, double const dt, double const Vel) { - double result; - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; + double result; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - BCP = ImplsRes->P(); - CVP = CntrlRes->P() - 0.0; + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + BCP = ImplsRes->P(); + CVP = CntrlRes->P() - 0.0; - dv = 0; - dV1 = 0; + dv = 0; + dV1 = 0; - // sprawdzanie stanu - CheckState(BCP, dV1); - CheckReleaser(dt); + // sprawdzanie stanu + CheckState(BCP, dV1); + CheckReleaser(dt); - VVP = ValveRes->P(); - // przeplyw ZS <-> PG - temp = CVs(BCP); - dv = PF(CVP, VVP, 0.0015 * temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + VVP = ValveRes->P(); + // przeplyw ZS <-> PG + temp = CVs(BCP); + dv = PF(CVP, VVP, 0.0015 * temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // luzowanie KI - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.00017 * (1.37 - int(BrakeDelayFlag == bdelay_G))) * dt; - else - dv = 0; - ImplsRes->Flow(-dv); - // przeplyw ZP <-> KI - if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP)) - dv = PF(BVP, BCP, - 0.0008 * (1 + int((BCP < 0.58) && (BrakeDelayFlag == bdelay_G))) * - (1.13 - int((BCP > 0.6) && (BrakeDelayFlag == bdelay_G)))) * - dt; - else - dv = 0; - BrakeRes->Flow(dv); - ImplsRes->Flow(-dv); - // przeplyw ZP <-> rozdzielacz - temp = BVs(BCP); - if ((VVP - 0.05 > BVP)) - dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dV1 + dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01) * dt; - ValveRes->Flow(-dv); - result = dv - dV1; + // luzowanie KI + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.00017 * (1.37 - int(BrakeDelayFlag == bdelay_G))) * dt; + else + dv = 0; + ImplsRes->Flow(-dv); + // przeplyw ZP <-> KI + if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP)) + dv = PF(BVP, BCP, 0.0008 * (1 + int((BCP < 0.58) && (BrakeDelayFlag == bdelay_G))) * (1.13 - int((BCP > 0.6) && (BrakeDelayFlag == bdelay_G)))) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + ImplsRes->Flow(-dv); + // przeplyw ZP <-> rozdzielacz + temp = BVs(BCP); + if ((VVP - 0.05 > BVP)) + dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dV1 + dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01) * dt; + ValveRes->Flow(-dv); + result = dv - dV1; - // luzowanie CH - if ((BrakeCyl->P() > ImplsRes->P() * LoadC + 0.005) || (ImplsRes->P() < 0.15)) - dv = PF(0, BrakeCyl->P(), 0.015 * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); + // luzowanie CH + if ((BrakeCyl->P() > ImplsRes->P() * LoadC + 0.005) || (ImplsRes->P() < 0.15)) + dv = PF(0, BrakeCyl->P(), 0.015 * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); - // przeplyw ZP <-> CH - if ((BrakeCyl->P() < ImplsRes->P() * LoadC - 0.005) && (ImplsRes->P() > 0.15)) - dv = PF(BVP, BrakeCyl->P(), 0.020 * SizeBC) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); + // przeplyw ZP <-> CH + if ((BrakeCyl->P() < ImplsRes->P() * LoadC - 0.005) && (ImplsRes->P() > 0.15)) + dv = PF(BVP, BrakeCyl->P(), 0.020 * SizeBC) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); - ImplsRes->Act(); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return result; + ImplsRes->Act(); + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return result; } -void TESt3AL2::PLC( double const mass ) +/// Recomputes the load-weighing coefficient LoadC for the current mass. +/// Current vehicle mass. +void TESt3AL2::PLC(double const mass) { - LoadC = 1 + - int(mass < LoadM) * - ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); + LoadC = 1 + int(mass < LoadM) * ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); } -void TESt3AL2::SetLP( double const TM, double const LM, double const TBP ) +/// Stores the load-weighing parameters (TareM, LoadM, TareBP). +/// Tare (empty) mass. +/// Loaded mass. +/// Tare-mass cylinder pressure. +void TESt3AL2::SetLP(double const TM, double const LM, double const TBP) { - TareM = TM; - LoadM = LM; - TareBP = TBP; + TareM = TM; + LoadM = LM; + TareBP = TBP; } -void TESt3AL2::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises ESt3/AL2: chains TESt::Init and sizes the impulse chamber +/// (KI) to 1 l, pre-charging it to BP. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TESt3AL2::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TESt::Init(PP, HPP, LPP, BP, BDF); - ImplsRes->CreateCap(1); - ImplsRes->CreatePress(BP); + TESt::Init(PP, HPP, LPP, BP, BDF); + ImplsRes->CreateCap(1); + ImplsRes->CreatePress(BP); } //---LSt--- -double TLSt::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for LSt: locomotive variant of ESt4R. +/// Re-implements the state machine inline (with the universal-button releaser), +/// drives the impulse chamber from CVP/VVP via PF1, applies a smoothed +/// rapid-step (RM) above a velocity threshold, factors in the ED brake +/// release (EDFlag) and the auxiliary brake LBP through a double check valve, +/// and supports the anti-slip release path (b_asb_unbrake / ASBP). +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TLSt::GetPF(double const PP, double const dt, double const Vel) { - double result; + double result; - // ValveRes.CreatePress(LBP); - // LBP:=0; + // ValveRes.CreatePress(LBP); + // LBP:=0; - double const BVP{ BrakeRes->P() }; - double const VVP{ ValveRes->P() }; - double const BCP{ ImplsRes->P() }; - double const CVP{ CntrlRes->P() }; + double const BVP{BrakeRes->P()}; + double const VVP{ValveRes->P()}; + double const BCP{ImplsRes->P()}; + double const CVP{CntrlRes->P()}; - double dV{ 0.0 }; - double dV1{ 0.0 }; + double dV{0.0}; + double dV1{0.0}; - // sprawdzanie stanu - // NOTE: partial copypaste from checkstate() of base class - // TODO: clean inheritance for checkstate() and checkreleaser() and reuse these instead of manual copypaste - if( ( ( BrakeStatus & b_hld ) == b_hld ) && ( BCP > 0.25 ) ) { - if( ( VVP + 0.003 + BCP / BVM < CVP ) ) { - // hamowanie stopniowe - BrakeStatus |= b_on; - } - else if( ( VVP - 0.003 + ( BCP - 0.1 ) / BVM > CVP ) ) { - // luzowanie - BrakeStatus &= ~( b_on | b_hld ); - } - else if( ( VVP + BCP / BVM > CVP ) ) { - // zatrzymanie napelaniania - BrakeStatus &= ~b_on; - } - } - else if ((VVP + 0.10 < CVP) && (BCP < 0.25)) { - // poczatek hamowania - if ((BrakeStatus & b_hld) == b_off) - { - SoundFlag |= sf_Acc; - } - BrakeStatus |= (b_on | b_hld); - } - else if( ( VVP + ( BCP - 0.1 ) / BVM < CVP ) - && ( ( CVP - VVP ) * BVM > 0.25 ) - && ( BCP > 0.25 ) ) { - // zatrzymanie luzowanie - BrakeStatus |= b_hld; - } - if( ( BrakeStatus & b_hld ) == 0 ) { - SoundFlag |= sf_CylU; - } - // equivalent of checkreleaser() in the base class? - bool is_releasing = ( ( BrakeStatus & b_rls) - || ( UniversalFlag & TUniversalBrake::ub_Release ) ); - if ( is_releasing ) { - if( CVP < 0.0 ) { - BrakeStatus &= ~b_rls; - } - else - { // 008 - dV = PF1( CVP, BCP, 0.024 ) * dt; - CntrlRes->Flow( dV ); - } - } + // sprawdzanie stanu + // NOTE: partial copypaste from checkstate() of base class + // TODO: clean inheritance for checkstate() and checkreleaser() and reuse these instead of manual copypaste + if (((BrakeStatus & b_hld) == b_hld) && (BCP > 0.25)) + { + if ((VVP + 0.003 + BCP / BVM < CVP)) + { + // hamowanie stopniowe + BrakeStatus |= b_on; + } + else if ((VVP - 0.003 + (BCP - 0.1) / BVM > CVP)) + { + // luzowanie + BrakeStatus &= ~(b_on | b_hld); + } + else if ((VVP + BCP / BVM > CVP)) + { + // zatrzymanie napelaniania + BrakeStatus &= ~b_on; + } + } + else if ((VVP + 0.10 < CVP) && (BCP < 0.25)) + { + // poczatek hamowania + if ((BrakeStatus & b_hld) == b_off) + { + SoundFlag |= sf_Acc; + } + BrakeStatus |= (b_on | b_hld); + } + else if ((VVP + (BCP - 0.1) / BVM < CVP) && ((CVP - VVP) * BVM > 0.25) && (BCP > 0.25)) + { + // zatrzymanie luzowanie + BrakeStatus |= b_hld; + } + if ((BrakeStatus & b_hld) == 0) + { + SoundFlag |= sf_CylU; + } + // equivalent of checkreleaser() in the base class? + bool is_releasing = ((BrakeStatus & b_rls) || (UniversalFlag & TUniversalBrake::ub_Release)); + if (is_releasing) + { + if (CVP < 0.0) + { + BrakeStatus &= ~b_rls; + } + else + { // 008 + dV = PF1(CVP, BCP, 0.024) * dt; + CntrlRes->Flow(dV); + } + } - // przeplyw ZS <-> PG - double temp; - if (((CVP - BCP) * BVM > 0.5)) - temp = 0.0; - else if ((VVP > CVP + 0.4)) - temp = 0.5; - else - temp = 0.5; + // przeplyw ZS <-> PG + double temp; + if (((CVP - BCP) * BVM > 0.5)) + temp = 0.0; + else if ((VVP > CVP + 0.4)) + temp = 0.5; + else + temp = 0.5; - dV = PF1(CVP, VVP, 0.0015 * temp / 1.8 / 2) * dt; - CntrlRes->Flow(+dV); - ValveRes->Flow(-0.04 * dV); - dV1 = dV1 - 0.96 * dV; + dV = PF1(CVP, VVP, 0.0015 * temp / 1.8 / 2) * dt; + CntrlRes->Flow(+dV); + ValveRes->Flow(-0.04 * dV); + dV1 = dV1 - 0.96 * dV; - // luzowanie KI {G} - // if VVP>BCP then - // dV:=PF(VVP,BCP,0.00004)*dt - // else if (CVP-BCP)<1.5 then - // dV:=PF(VVP,BCP,0.00020*(1.33-int((CVP-BCP)*BVM>0.65)))*dt - // else dV:=0; 0.00025 P - /*P*/ - if( VVP > BCP ) { - dV = - PF( VVP, BCP, - 0.00043 * ( 1.5 - ( - true == ( ( ( CVP - BCP ) * BVM > 1.0 ) - && ( BrakeDelayFlag == bdelay_G ) ) ? - 1.0 : - 0.0 ) ), - 0.1 ) - * dt; - } - else if( ( CVP - BCP ) < 1.5 ) { - dV = PF( VVP, BCP, - 0.001472 * ( 1.36 - ( - true == ( ( ( CVP - BCP ) * BVM > 1.0 ) - && ( BrakeDelayFlag == bdelay_G ) ) ? - 1.0 : - 0.0 ) ), - 0.1 ) - * dt; - } - else { - dV = 0; - } + // luzowanie KI {G} + // if VVP>BCP then + // dV:=PF(VVP,BCP,0.00004)*dt + // else if (CVP-BCP)<1.5 then + // dV:=PF(VVP,BCP,0.00020*(1.33-int((CVP-BCP)*BVM>0.65)))*dt + // else dV:=0; 0.00025 P + /*P*/ + if (VVP > BCP) + { + dV = PF(VVP, BCP, 0.00043 * (1.5 - (true == (((CVP - BCP) * BVM > 1.0) && (BrakeDelayFlag == bdelay_G)) ? 1.0 : 0.0)), 0.1) * dt; + } + else if ((CVP - BCP) < 1.5) + { + dV = PF(VVP, BCP, 0.001472 * (1.36 - (true == (((CVP - BCP) * BVM > 1.0) && (BrakeDelayFlag == bdelay_G)) ? 1.0 : 0.0)), 0.1) * dt; + } + else + { + dV = 0; + } - ImplsRes->Flow(-dV); - ValveRes->Flow(+dV); - // przeplyw PG <-> rozdzielacz - dV = PF(PP, VVP, 0.01, 0.1) * dt; - ValveRes->Flow(-dV); + ImplsRes->Flow(-dV); + ValveRes->Flow(+dV); + // przeplyw PG <-> rozdzielacz + dV = PF(PP, VVP, 0.01, 0.1) * dt; + ValveRes->Flow(-dV); - result = dV - dV1; + result = dV - dV1; - // if Vel>55 then temp:=0.72 else - // temp:=1;{R} - // cisnienie PP - RapidTemp = - RapidTemp + (RM * int((Vel > 55) && (BrakeDelayFlag == bdelay_R)) - RapidTemp) * dt / 2; - temp = 1 - RapidTemp; - if (EDFlag > 0.2) - temp = 10000; + // if Vel>55 then temp:=0.72 else + // temp:=1;{R} + // cisnienie PP + RapidTemp = RapidTemp + (RM * int((Vel > 55) && (BrakeDelayFlag == bdelay_R)) - RapidTemp) * dt / 2; + temp = 1 - RapidTemp; + if (EDFlag > 0.2) + temp = 10000; double tempasb = 0; - if ( ( (UniversalFlag & TUniversalBrake::ub_AntiSlipBrake) > 0) - || ( (BrakeStatus & b_asb_unbrake) == b_asb_unbrake ) ) + if (((UniversalFlag & TUniversalBrake::ub_AntiSlipBrake) > 0) || ((BrakeStatus & b_asb_unbrake) == b_asb_unbrake)) tempasb = ASBP; - // powtarzacz — podwojny zawor zwrotny - temp = Max0R( ( (CVP - BCP) * BVM + tempasb ) / temp, LBP ); - // luzowanie CH - if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28)) - // dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt - // dV:=PF(0,BrakeCyl->P(),0.005*3*sizeBC)*dt - dV = PFVd(BrakeCyl->P(), 0, 0.005 * 7 * SizeBC, temp) * dt; - else - dV = 0; - BrakeCyl->Flow(-dV); - // przeplyw ZP <-> CH - if ((BrakeCyl->P() < temp - 0.005) && (temp > 0.29)) - // dV:=PF(BVP,BrakeCyl->P(),0.002*3*sizeBC*2)*dt - dV = -PFVa(BVP, BrakeCyl->P(), 0.002 * 7 * SizeBC * 2, temp) * dt; - else - dV = 0; - BrakeRes->Flow(dV); - BrakeCyl->Flow(-dV); + // powtarzacz — podwojny zawor zwrotny + temp = Max0R(((CVP - BCP) * BVM + tempasb) / temp, LBP); + // luzowanie CH + if ((BrakeCyl->P() > temp + 0.005) || (temp < 0.28)) + // dV:=PF(0,BrakeCyl->P(),0.0015*3*sizeBC)*dt + // dV:=PF(0,BrakeCyl->P(),0.005*3*sizeBC)*dt + dV = PFVd(BrakeCyl->P(), 0, 0.005 * 7 * SizeBC, temp) * dt; + else + dV = 0; + BrakeCyl->Flow(-dV); + // przeplyw ZP <-> CH + if ((BrakeCyl->P() < temp - 0.005) && (temp > 0.29)) + // dV:=PF(BVP,BrakeCyl->P(),0.002*3*sizeBC*2)*dt + dV = -PFVa(BVP, BrakeCyl->P(), 0.002 * 7 * SizeBC * 2, temp) * dt; + else + dV = 0; + BrakeRes->Flow(dV); + BrakeCyl->Flow(-dV); - ImplsRes->Act(); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - // LBP:=ValveRes->P(); - // ValveRes.CreatePress(ImplsRes->P()); - return result; + ImplsRes->Act(); + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + // LBP:=ValveRes->P(); + // ValveRes.CreatePress(ImplsRes->P()); + return result; } -void TLSt::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the LSt: chains TESt4R::Init, resizes the valve pre-chamber +/// (1 l) and impulse chamber (8 l) for locomotive use, pre-charges +/// pressures, clears the ED-release flag. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TLSt::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TESt4R::Init(PP, HPP, LPP, BP, BDF); - ValveRes->CreateCap(1); - ImplsRes->CreateCap(8); - ImplsRes->CreatePress(PP); - BrakeRes->CreatePress(8); - ValveRes->CreatePress(PP); + TESt4R::Init(PP, HPP, LPP, BP, BDF); + ValveRes->CreateCap(1); + ImplsRes->CreateCap(8); + ImplsRes->CreatePress(PP); + BrakeRes->CreatePress(8); + ValveRes->CreatePress(PP); - EDFlag = 0; + EDFlag = 0; - BrakeDelayFlag = BDF; + BrakeDelayFlag = BDF; } -void TLSt::SetLBP( double const P ) +/// Sets the auxiliary (local) brake target pressure feeding the DCV. +/// Auxiliary brake pressure [bar]. +void TLSt::SetLBP(double const P) { - LBP = P; + LBP = P; } +/// +/// Returns the brake-cylinder reference pressure used by the ED brake +/// controller: (CVP - BCP) * BVM, where BCP is the impulse-chamber pressure. +/// double TLSt::GetEDBCP() { - double CVP; - double BCP; + double CVP; + double BCP; - CVP = CntrlRes->P(); - BCP = ImplsRes->P(); - return (CVP - BCP) * BVM; + CVP = CntrlRes->P(); + BCP = ImplsRes->P(); + return (CVP - BCP) * BVM; } -void TLSt::SetED( double const EDstate ) +/// Sets the ED brake state (intensity, 0..1) used to relax the pneumatic brake. +/// ED intensity. +void TLSt::SetED(double const EDstate) { - EDFlag = EDstate; + EDFlag = EDstate; } -void TLSt::SetRM( double const RMR ) +/// Sets the rapid-step ratio. RM = 1 - RMR (so RMR=0 disables, RMR>0 enables). +/// Reduction ratio. +void TLSt::SetRM(double const RMR) { - RM = 1 - RMR; + RM = 1 - RMR; } -double TLSt::GetHPFlow( double const HP, double const dt ) +/// +/// High-pressure replenishment: takes air only when the source pressure is +/// higher than the auxiliary reservoir, returning a non-positive flow that +/// is added back to BrakeRes. +/// +/// High-pressure source [bar]. +/// Time step [s] (folded into the orifice term in this implementation). +/// Inflow into BrakeRes (negative). +double TLSt::GetHPFlow(double const HP, double const dt) { - double dv; + double dv; - dv = Min0R(PF(HP, BrakeRes->P(), 0.01 * dt), 0); - BrakeRes->Flow(-dv); - return dv; + dv = Min0R(PF(HP, BrakeRes->P(), 0.01 * dt), 0); + BrakeRes->Flow(-dv); + return dv; } //---EStED--- -double TEStED::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for EStED (the EP09 "ESt + ED" valve). +/// Adds the intermediate reservoir (Miedzypoj), the closing-valve memory +/// (Zamykajacy), the accelerator-block latch (Przys_blok), nozzle-tuned +/// flows for ZP/ZS filling and the rapid-step / ED-release / anti-slip +/// path on top of the ESt pneumatics. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TEStED::GetPF(double const PP, double const dt, double const Vel) { - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; - double MPP; - double nastG; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; + double MPP; + double nastG; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - BCP = ImplsRes->P(); - CVP = CntrlRes->P() - 0.0; - MPP = Miedzypoj->P(); - dV1 = 0; + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + BCP = ImplsRes->P(); + CVP = CntrlRes->P() - 0.0; + MPP = Miedzypoj->P(); + dV1 = 0; - nastG = (BrakeDelayFlag & bdelay_G); + nastG = (BrakeDelayFlag & bdelay_G); - // sprawdzanie stanu - if ((BCP < 0.25) && (VVP + 0.08 > CVP)) - Przys_blok = false; + // sprawdzanie stanu + if ((BCP < 0.25) && (VVP + 0.08 > CVP)) + Przys_blok = false; - // sprawdzanie stanu - if ((VVP + 0.002 + BCP / BVM < CVP - 0.05) && (Przys_blok)) - BrakeStatus |= (b_on | b_hld); // hamowanie stopniowe; - else if ((VVP - 0.002 + (BCP - 0.1) / BVM > CVP - 0.05)) - BrakeStatus &= ~(b_on | b_hld); // luzowanie; - else if ((VVP + BCP / BVM > CVP - 0.05)) - BrakeStatus &= ~b_on; // zatrzymanie napelaniania; - else if ((VVP + (BCP - 0.1) / BVM < CVP - 0.05) && (BCP > 0.25)) // zatrzymanie luzowania - BrakeStatus |= b_hld; + // sprawdzanie stanu + if ((VVP + 0.002 + BCP / BVM < CVP - 0.05) && (Przys_blok)) + BrakeStatus |= (b_on | b_hld); // hamowanie stopniowe; + else if ((VVP - 0.002 + (BCP - 0.1) / BVM > CVP - 0.05)) + BrakeStatus &= ~(b_on | b_hld); // luzowanie; + else if ((VVP + BCP / BVM > CVP - 0.05)) + BrakeStatus &= ~b_on; // zatrzymanie napelaniania; + else if ((VVP + (BCP - 0.1) / BVM < CVP - 0.05) && (BCP > 0.25)) // zatrzymanie luzowania + BrakeStatus |= b_hld; - if ((VVP + 0.10 < CVP) && (BCP < 0.25)) // poczatek hamowania - if ((!Przys_blok)) - { - ValveRes->CreatePress(0.75 * VVP); - SoundFlag |= sf_Acc; - ValveRes->Act(); - Przys_blok = true; - } + if ((VVP + 0.10 < CVP) && (BCP < 0.25)) // poczatek hamowania + if ((!Przys_blok)) + { + ValveRes->CreatePress(0.75 * VVP); + SoundFlag |= sf_Acc; + ValveRes->Act(); + Przys_blok = true; + } - if ((BCP > 0.5)) - Zamykajacy = true; - else if ((VVP - 0.6 < MPP)) - Zamykajacy = false; + if ((BCP > 0.5)) + Zamykajacy = true; + else if ((VVP - 0.6 < MPP)) + Zamykajacy = false; - if ((BrakeStatus & b_rls) == b_rls) - { - dv = PF(CVP, BCP, 0.024) * dt; - CntrlRes->Flow(+dv); - } + if ((BrakeStatus & b_rls) == b_rls) + { + dv = PF(CVP, BCP, 0.024) * dt; + CntrlRes->Flow(+dv); + } - // luzowanie - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, Nozzles[3] * nastG + (1 - nastG) * Nozzles[1]) * dt; - else - dv = 0; - ImplsRes->Flow(-dv); - if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP)) - dv = - PF(BVP, BCP, Nozzles[2] * (nastG + 2 * int(BCP < 0.8)) + Nozzles[0] * (1 - nastG)) * dt; - else - dv = 0; - ImplsRes->Flow(-dv); - BrakeRes->Flow(dv); + // luzowanie + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, Nozzles[3] * nastG + (1 - nastG) * Nozzles[1]) * dt; + else + dv = 0; + ImplsRes->Flow(-dv); + if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP)) + dv = PF(BVP, BCP, Nozzles[2] * (nastG + 2 * int(BCP < 0.8)) + Nozzles[0] * (1 - nastG)) * dt; + else + dv = 0; + ImplsRes->Flow(-dv); + BrakeRes->Flow(dv); - // przeplyw testowy miedzypojemnosci - if ((MPP < CVP - 0.3)) - temp = Nozzles[4]; - else if ((BCP < 0.5)) - if ((Zamykajacy)) - temp = Nozzles[8]; // 1.25; - else - temp = Nozzles[7]; - else - temp = 0; - dv = PF(MPP, VVP, temp); + // przeplyw testowy miedzypojemnosci + if ((MPP < CVP - 0.3)) + temp = Nozzles[4]; + else if ((BCP < 0.5)) + if ((Zamykajacy)) + temp = Nozzles[8]; // 1.25; + else + temp = Nozzles[7]; + else + temp = 0; + dv = PF(MPP, VVP, temp); - if ((MPP < CVP - 0.17)) - temp = 0; - else if ((MPP > CVP - 0.08)) - temp = Nozzles[5]; - else - temp = Nozzles[6]; - dv = dv + PF(MPP, CVP, temp); + if ((MPP < CVP - 0.17)) + temp = 0; + else if ((MPP > CVP - 0.08)) + temp = Nozzles[5]; + else + temp = Nozzles[6]; + dv = dv + PF(MPP, CVP, temp); - if ((MPP - 0.05 > BVP)) - dv = dv + PF(MPP - 0.05, BVP, Nozzles[10] * nastG + (1 - nastG) * Nozzles[9]); - if (MPP > VVP) - dv = dv + PF(MPP, VVP, 0.02); - Miedzypoj->Flow(dv * dt * 0.15); + if ((MPP - 0.05 > BVP)) + dv = dv + PF(MPP - 0.05, BVP, Nozzles[10] * nastG + (1 - nastG) * Nozzles[9]); + if (MPP > VVP) + dv = dv + PF(MPP, VVP, 0.02); + Miedzypoj->Flow(dv * dt * 0.15); - RapidTemp = - RapidTemp + (RM * int((Vel > RV) && (BrakeDelayFlag == bdelay_R)) - RapidTemp) * dt / 2; - temp = Max0R(1 - RapidTemp, 0.001); - // if EDFlag then temp:=1000; - // temp:=temp/(1-); + RapidTemp = RapidTemp + (RM * int((Vel > RV) && (BrakeDelayFlag == bdelay_R)) - RapidTemp) * dt / 2; + temp = Max0R(1 - RapidTemp, 0.001); + // if EDFlag then temp:=1000; + // temp:=temp/(1-); - // powtarzacz — podwojny zawor zwrotny - temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP); - - if ( ( UniversalFlag & TUniversalBrake::ub_AntiSlipBrake ) > 0 ) + // powtarzacz — podwojny zawor zwrotny + temp = Max0R(LoadC * BCP / temp * Min0R(Max0R(1 - EDFlag, 0), 1), LBP); + + if ((UniversalFlag & TUniversalBrake::ub_AntiSlipBrake) > 0) temp = std::max(temp, ASBP); double speed = 1; @@ -1576,1160 +2011,1440 @@ double TEStED::GetPF( double const PP, double const dt, double const Vel ) speed = 3; } - if ((BrakeCyl->P() > temp)) - dv = -PFVd(BrakeCyl->P(), 0, 0.05 * SizeBC * speed, temp) * dt; - else if ((BrakeCyl->P() < temp) && ((BrakeStatus & b_asb) == 0)) - dv = PFVa(BVP, BrakeCyl->P(), 0.05 * SizeBC, temp) * dt; - else - dv = 0; + if ((BrakeCyl->P() > temp)) + dv = -PFVd(BrakeCyl->P(), 0, 0.05 * SizeBC * speed, temp) * dt; + else if ((BrakeCyl->P() < temp) && ((BrakeStatus & b_asb) == 0)) + dv = PFVa(BVP, BrakeCyl->P(), 0.05 * SizeBC, temp) * dt; + else + dv = 0; - BrakeCyl->Flow(dv); - if (dv > 0) - BrakeRes->Flow(-dv); + BrakeCyl->Flow(dv); + if (dv > 0) + BrakeRes->Flow(-dv); - // przeplyw ZS <-> PG - if ((MPP < CVP - 0.17)) - temp = 0; - else if ((MPP > CVP - 0.08)) - temp = Nozzles[5]; - else - temp = Nozzles[6]; - dv = PF(CVP, MPP, temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.02 * dv); - dV1 = dV1 + 0.98 * dv; + // przeplyw ZS <-> PG + if ((MPP < CVP - 0.17)) + temp = 0; + else if ((MPP > CVP - 0.08)) + temp = Nozzles[5]; + else + temp = Nozzles[6]; + dv = PF(CVP, MPP, temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.02 * dv); + dV1 = dV1 + 0.98 * dv; - // przeplyw ZP <-> MPJ - if ((MPP - 0.05 > BVP)) - dv = PF(BVP, MPP - 0.05, Nozzles[10] * nastG + (1 - nastG) * Nozzles[9]) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dV1 + dv * 0.98; - ValveRes->Flow(-0.02 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.005) * dt; // 0.01 - ValveRes->Flow(-dv); + // przeplyw ZP <-> MPJ + if ((MPP - 0.05 > BVP)) + dv = PF(BVP, MPP - 0.05, Nozzles[10] * nastG + (1 - nastG) * Nozzles[9]) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dV1 + dv * 0.98; + ValveRes->Flow(-0.02 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.005) * dt; // 0.01 + ValveRes->Flow(-dv); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - Miedzypoj->Act(); - ImplsRes->Act(); - return dv - dV1; + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + Miedzypoj->Act(); + ImplsRes->Act(); + return dv - dV1; } -void TEStED::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the EStED: chains TLSt::Init, sizes Miedzypoj (5 l), pre-charges +/// pressures, computes BVM with a 0.05 bar offset on HPP, configures the +/// 11 internal nozzle cross-sections (squared and scaled to the engine's +/// flow units) and clears the latches. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TEStED::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TLSt::Init(PP, HPP, LPP, BP, BDF); - int i; + TLSt::Init(PP, HPP, LPP, BP, BDF); + int i; - ValveRes->CreatePress(PP); - BrakeCyl->CreatePress(BP); + ValveRes->CreatePress(PP); + BrakeCyl->CreatePress(BP); - // CntrlRes:=TReservoir.Create; - // CntrlRes.CreateCap(15); - // CntrlRes.CreatePress(1*HPP); + // CntrlRes:=TReservoir.Create; + // CntrlRes.CreateCap(15); + // CntrlRes.CreatePress(1*HPP); - BrakeStatus = (BP > 1.0) ? 1 : 0; - Miedzypoj->CreateCap(5); - Miedzypoj->CreatePress(PP); + BrakeStatus = (BP > 1.0) ? 1 : 0; + Miedzypoj->CreateCap(5); + Miedzypoj->CreatePress(PP); - ImplsRes->CreateCap(1); - ImplsRes->CreatePress(BP); + ImplsRes->CreateCap(1); + ImplsRes->CreatePress(BP); - BVM = 1.0 / (HPP - 0.05 - LPP) * MaxBP; + BVM = 1.0 / (HPP - 0.05 - LPP) * MaxBP; - BrakeDelayFlag = BDF; - Zamykajacy = false; - EDFlag = 0; + BrakeDelayFlag = BDF; + Zamykajacy = false; + EDFlag = 0; - Nozzles[0] = 1.250 / 1.7; - Nozzles[1] = 0.907; - Nozzles[2] = 0.510 / 1.7; - Nozzles[3] = 0.524 / 1.17; - Nozzles[4] = 7.4; - Nozzles[7] = 5.3; - Nozzles[8] = 2.5; - Nozzles[9] = 7.28; - Nozzles[10] = 2.96; - Nozzles[5] = 1.1; - Nozzles[6] = 0.9; + Nozzles[0] = 1.250 / 1.7; + Nozzles[1] = 0.907; + Nozzles[2] = 0.510 / 1.7; + Nozzles[3] = 0.524 / 1.17; + Nozzles[4] = 7.4; + Nozzles[7] = 5.3; + Nozzles[8] = 2.5; + Nozzles[9] = 7.28; + Nozzles[10] = 2.96; + Nozzles[5] = 1.1; + Nozzles[6] = 0.9; - { - for (i = 0; i < 11; ++i) - { - Nozzles[i] = Nozzles[i] * Nozzles[i] * 3.14159 / 4000; - } - } + { + for (i = 0; i < 11; ++i) + { + Nozzles[i] = Nozzles[i] * Nozzles[i] * 3.14159 / 4000; + } + } } +/// +/// Returns the ED reference pressure for EStED — impulse chamber pressure +/// scaled by the load-weighing coefficient. +/// double TEStED::GetEDBCP() { - return ImplsRes->P() * LoadC; + return ImplsRes->P() * LoadC; } -void TEStED::PLC( double const mass ) +/// Recomputes the load-weighing coefficient LoadC for the current mass. +/// Current vehicle mass. +void TEStED::PLC(double const mass) { - LoadC = 1 + - int(mass < LoadM) * - ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); + LoadC = 1 + int(mass < LoadM) * ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); } -void TEStED::SetLP( double const TM, double const LM, double const TBP ) +/// Stores the load-weighing parameters. +/// Tare (empty) mass. +/// Loaded mass. +/// Tare-mass cylinder pressure. +void TEStED::SetLP(double const TM, double const LM, double const TBP) { - TareM = TM; - LoadM = LM; - TareBP = TBP; + TareM = TM; + LoadM = LM; + TareBP = TBP; } //---DAKO CV1--- -void TCV1::CheckState( double const BCP, double &dV1 ) +/// +/// Drives the BrakeStatus state machine for CV1: handles the releaser +/// auto-disengage (when CVP <= VVP) and the b_on/b_hld transitions +/// from the relations between pre-chamber, cylinder and control reservoir. +/// On the start of braking it returns dV1=1.25 to feed the brake-pipe +/// flow correction. +/// +/// Cylinder pressure. +/// In/out brake-pipe flow correction. +void TCV1::CheckState(double const BCP, double &dV1) { - double VVP; - double BVP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - VVP = Min0R(ValveRes->P(), BVP + 0.05); - CVP = CntrlRes->P(); + BVP = BrakeRes->P(); + VVP = Min0R(ValveRes->P(), BVP + 0.05); + CVP = CntrlRes->P(); - // odluzniacz - if (((BrakeStatus & b_rls) == b_rls) && (CVP - VVP < 0)) - BrakeStatus &= ~b_rls; + // odluzniacz + if (((BrakeStatus & b_rls) == b_rls) && (CVP - VVP < 0)) + BrakeStatus &= ~b_rls; - // sprawdzanie stanu - if ((BrakeStatus & b_hld) == b_hld) - if ((VVP + 0.003 + BCP / BVM < CVP)) - BrakeStatus |= b_on; // hamowanie stopniowe; - else if ((VVP - 0.003 + BCP * 1.0 / BVM > CVP)) - BrakeStatus &= ~( b_on | b_hld ); // luzowanie; - else if ((VVP + BCP * 1.0 / BVM > CVP)) - BrakeStatus &= ~b_on; // zatrzymanie napelaniania; - else - ; - else if ((VVP + 0.10 < CVP) && (BCP < 0.1)) // poczatek hamowania - { - BrakeStatus |= ( b_on | b_hld ); - dV1 = 1.25; - } - else if ((VVP + BCP / BVM < CVP) && (BCP > 0.25)) // zatrzymanie luzowanie - BrakeStatus |= b_hld; + // sprawdzanie stanu + if ((BrakeStatus & b_hld) == b_hld) + if ((VVP + 0.003 + BCP / BVM < CVP)) + BrakeStatus |= b_on; // hamowanie stopniowe; + else if ((VVP - 0.003 + BCP * 1.0 / BVM > CVP)) + BrakeStatus &= ~(b_on | b_hld); // luzowanie; + else if ((VVP + BCP * 1.0 / BVM > CVP)) + BrakeStatus &= ~b_on; // zatrzymanie napelaniania; + else + ; + else if ((VVP + 0.10 < CVP) && (BCP < 0.1)) // poczatek hamowania + { + BrakeStatus |= (b_on | b_hld); + dV1 = 1.25; + } + else if ((VVP + BCP / BVM < CVP) && (BCP > 0.25)) // zatrzymanie luzowanie + BrakeStatus |= b_hld; } +/// +/// Returns the CV1 ZS-filling slide valve opening factor: closed once any +/// pneumatic braking has been requested (BP > 0.05), otherwise a constant 0.23. +/// +/// Cylinder pressure. +/// Opening coefficient. double TCV1::CVs(double const BP) { - // przeplyw ZS <-> PG - if ((BP > 0.05)) - return 0; - else - return 0.23; + // przeplyw ZS <-> PG + if ((BP > 0.05)) + return 0; + else + return 0.23; } -double TCV1::BVs( double const BCP ) +/// +/// Returns the CV1 ZP-filling slide valve opening factor: 1 while the +/// auxiliary reservoir is below the control reservoir (refill), 0 once the +/// brake has been applied, and a small charging value otherwise. +/// +/// Cylinder pressure. +/// Opening coefficient. +double TCV1::BVs(double const BCP) { - double VVP; - double BVP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); + BVP = BrakeRes->P(); + CVP = CntrlRes->P(); + VVP = ValveRes->P(); - // przeplyw ZP <-> rozdzielacz - if ((BVP < CVP - 0.1)) - return 1; - else if ((BCP > 0.05)) - return 0; - else - return 0.2 * (1.5 - int(BVP > VVP)); + // przeplyw ZP <-> rozdzielacz + if ((BVP < CVP - 0.1)) + return 1; + else if ((BCP > 0.05)) + return 0; + else + return 0.2 * (1.5 - int(BVP > VVP)); } -double TCV1::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for the DAKO CV1: runs CheckState, integrates +/// ZS <-> PG, ZP <-> cylinder (with G/P-dependent fill rates), ZP <-> +/// pre-chamber and PG <-> pre-chamber flows. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TCV1::GetPF(double const PP, double const dt, double const Vel) { - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; - BVP = BrakeRes->P(); - VVP = Min0R(ValveRes->P(), BVP + 0.05); - BCP = BrakeCyl->P(); - CVP = CntrlRes->P(); + BVP = BrakeRes->P(); + VVP = Min0R(ValveRes->P(), BVP + 0.05); + BCP = BrakeCyl->P(); + CVP = CntrlRes->P(); - dv = 0; - dV1 = 0; + dv = 0; + dV1 = 0; - // sprawdzanie stanu - CheckState(BCP, dV1); + // sprawdzanie stanu + CheckState(BCP, dV1); - VVP = ValveRes->P(); - // przeplyw ZS <-> PG - temp = CVs(BCP); - dv = PF(CVP, VVP, 0.0015 * temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + VVP = ValveRes->P(); + // przeplyw ZS <-> PG + temp = CVs(BCP); + dv = PF(CVP, VVP, 0.0015 * temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // luzowanie - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.0042 * (1.37 - int(BrakeDelayFlag == bdelay_G)) * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); + // luzowanie + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.0042 * (1.37 - int(BrakeDelayFlag == bdelay_G)) * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); - // przeplyw ZP <-> silowniki - if ((BrakeStatus & b_on) == b_on) - dv = PF(BVP, BCP, - 0.017 * (1 + int((BCP < 0.58) && (BrakeDelayFlag == bdelay_G))) * - (1.13 - int((BCP > 0.6) && (BrakeDelayFlag == bdelay_G))) * SizeBC) * - dt; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); + // przeplyw ZP <-> silowniki + if ((BrakeStatus & b_on) == b_on) + dv = PF(BVP, BCP, 0.017 * (1 + int((BCP < 0.58) && (BrakeDelayFlag == bdelay_G))) * (1.13 - int((BCP > 0.6) && (BrakeDelayFlag == bdelay_G))) * SizeBC) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); - // przeplyw ZP <-> rozdzielacz - temp = BVs(BCP); - if ((VVP + 0.05 > BVP)) - dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dV1 + dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01) * dt; - ValveRes->Flow(-dv); + // przeplyw ZP <-> rozdzielacz + temp = BVs(BCP); + if ((VVP + 0.05 > BVP)) + dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dV1 + dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01) * dt; + ValveRes->Flow(-dv); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return dv - dV1; + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return dv - dV1; } -void TCV1::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the CV1: pre-charges valve / brake / control reservoirs (ZS = 15 l), +/// clears BrakeStatus and computes BVM (= MaxBP / (HPP-LPP)). +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TCV1::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TBrake::Init(PP, HPP, LPP, BP, BDF); - ValveRes->CreatePress(PP); - BrakeCyl->CreatePress(BP); - BrakeRes->CreatePress(PP); - CntrlRes->CreateCap(15); - CntrlRes->CreatePress(HPP); - BrakeStatus = b_off; + TBrake::Init(PP, HPP, LPP, BP, BDF); + ValveRes->CreatePress(PP); + BrakeCyl->CreatePress(BP); + BrakeRes->CreatePress(PP); + CntrlRes->CreateCap(15); + CntrlRes->CreatePress(HPP); + BrakeStatus = b_off; - BVM = 1.0 / (HPP - LPP) * MaxBP; + BVM = 1.0 / (HPP - LPP) * MaxBP; - BrakeDelayFlag = BDF; + BrakeDelayFlag = BDF; } +/// Returns the control reservoir (ZS) pressure. double TCV1::GetCRP() { - return CntrlRes->P(); + return CntrlRes->P(); } -void TCV1::ForceEmptiness() { +/// Vents valve, brake and control reservoirs to zero. +void TCV1::ForceEmptiness() +{ - ValveRes->CreatePress( 0 ); - BrakeRes->CreatePress( 0 ); - CntrlRes->CreatePress( 0 ); + ValveRes->CreatePress(0); + BrakeRes->CreatePress(0); + CntrlRes->CreatePress(0); - ValveRes->Act(); - BrakeRes->Act(); - CntrlRes->Act(); + ValveRes->Act(); + BrakeRes->Act(); + CntrlRes->Act(); } //---CV1-L-TR--- -void TCV1L_TR::SetLBP( double const P ) +/// Sets the auxiliary (local) brake target pressure feeding the DCV. +/// Auxiliary brake pressure [bar]. +void TCV1L_TR::SetLBP(double const P) { - LBP = P; + LBP = P; } -double TCV1L_TR::GetHPFlow( double const HP, double const dt ) +/// +/// High-pressure replenishment for CV1-L-TR: pulls air into the auxiliary +/// reservoir whenever the source is higher (returns a non-positive flow). +/// +/// High-pressure source [bar]. +/// Time step [s]. +/// Inflow into BrakeRes (negative on intake). +double TCV1L_TR::GetHPFlow(double const HP, double const dt) { - double dv; + double dv; - dv = PF(HP, BrakeRes->P(), 0.01) * dt; - dv = Min0R(0, dv); - BrakeRes->Flow(-dv); - return dv; + dv = PF(HP, BrakeRes->P(), 0.01) * dt; + dv = Min0R(0, dv); + BrakeRes->Flow(-dv); + return dv; } -void TCV1L_TR::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises CV1-L-TR: chains TCV1::Init and sizes the impulse chamber to +/// 2.5 l, pre-charging it to BP. +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TCV1L_TR::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TCV1::Init(PP, HPP, LPP, BP, BDF); - ImplsRes->CreateCap(2.5); - ImplsRes->CreatePress(BP); + TCV1::Init(PP, HPP, LPP, BP, BDF); + ImplsRes->CreateCap(2.5); + ImplsRes->CreatePress(BP); } -double TCV1L_TR::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for CV1-L-TR. Drives the impulse chamber (KI) +/// from the CV1 state machine, then computes cylinder fill/release against +/// the higher of the impulse-chamber and auxiliary-brake (LBP) pressure. +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TCV1L_TR::GetPF(double const PP, double const dt, double const Vel) { - double result; - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double CVP; + double result; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double CVP; - BVP = BrakeRes->P(); - VVP = Min0R(ValveRes->P(), BVP + 0.05); - BCP = ImplsRes->P(); - CVP = CntrlRes->P(); + BVP = BrakeRes->P(); + VVP = Min0R(ValveRes->P(), BVP + 0.05); + BCP = ImplsRes->P(); + CVP = CntrlRes->P(); - dv = 0; - dV1 = 0; + dv = 0; + dV1 = 0; - // sprawdzanie stanu - CheckState(BCP, dV1); + // sprawdzanie stanu + CheckState(BCP, dV1); - VVP = ValveRes->P(); - // przeplyw ZS <-> PG - temp = CVs(BCP); - dv = PF(CVP, VVP, 0.0015 * temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + VVP = ValveRes->P(); + // przeplyw ZS <-> PG + temp = CVs(BCP); + dv = PF(CVP, VVP, 0.0015 * temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // luzowanie KI - if ((BrakeStatus & b_hld) == b_off) - dv = PF(0, BCP, 0.000425 * (1.37 - int(BrakeDelayFlag == bdelay_G))) * dt; - else - dv = 0; - ImplsRes->Flow(-dv); - // przeplyw ZP <-> KI - if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP)) - dv = PF(BVP, BCP, - 0.002 * (1 + int((BCP < 0.58) && (BrakeDelayFlag == bdelay_G))) * - (1.13 - int((BCP > 0.6) && (BrakeDelayFlag == bdelay_G)))) * - dt; - else - dv = 0; - BrakeRes->Flow(dv); - ImplsRes->Flow(-dv); + // luzowanie KI + if ((BrakeStatus & b_hld) == b_off) + dv = PF(0, BCP, 0.000425 * (1.37 - int(BrakeDelayFlag == bdelay_G))) * dt; + else + dv = 0; + ImplsRes->Flow(-dv); + // przeplyw ZP <-> KI + if (((BrakeStatus & b_on) == b_on) && (BCP < MaxBP)) + dv = PF(BVP, BCP, 0.002 * (1 + int((BCP < 0.58) && (BrakeDelayFlag == bdelay_G))) * (1.13 - int((BCP > 0.6) && (BrakeDelayFlag == bdelay_G)))) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + ImplsRes->Flow(-dv); - // przeplyw ZP <-> rozdzielacz - temp = BVs(BCP); - if ((VVP + 0.05 > BVP)) - dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dV1 + dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01) * dt; - result = dv - dV1; + // przeplyw ZP <-> rozdzielacz + temp = BVs(BCP); + if ((VVP + 0.05 > BVP)) + dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dV1 + dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01) * dt; + result = dv - dV1; - temp = Max0R(BCP, LBP); + temp = Max0R(BCP, LBP); - // luzowanie CH - if ((BrakeCyl->P() > temp + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.25)) - dv = PF(0, BrakeCyl->P(), 0.015 * SizeBC) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); + // luzowanie CH + if ((BrakeCyl->P() > temp + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.25)) + dv = PF(0, BrakeCyl->P(), 0.015 * SizeBC) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); - // przeplyw ZP <-> CH - if ((BrakeCyl->P() < temp - 0.005) && (Max0R(ImplsRes->P(), 8 * LBP) > 0.3) && - (Max0R(BCP, LBP) < MaxBP)) - dv = PF(BVP, BrakeCyl->P(), 0.020 * SizeBC) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - BrakeCyl->Flow(-dv); + // przeplyw ZP <-> CH + if ((BrakeCyl->P() < temp - 0.005) && (Max0R(ImplsRes->P(), 8 * LBP) > 0.3) && (Max0R(BCP, LBP) < MaxBP)) + dv = PF(BVP, BrakeCyl->P(), 0.020 * SizeBC) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + BrakeCyl->Flow(-dv); - ImplsRes->Act(); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - return result; + ImplsRes->Act(); + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + return result; } //--- KNORR KE --- -void TKE::CheckReleaser( double const dt ) +/// +/// Implements the KE releaser logic: while engaged, vents the control +/// reservoir to zero via a 0.1-area orifice; auto-disengages once CVP <= VVP. +/// +/// Time step [s]. +void TKE::CheckReleaser(double const dt) { - double VVP; - double CVP; + double VVP; + double CVP; - VVP = ValveRes->P(); - CVP = CntrlRes->P(); + VVP = ValveRes->P(); + CVP = CntrlRes->P(); - // odluzniacz - if ( true == ((BrakeStatus & b_rls) == b_rls)) - if ((CVP - VVP < 0)) - BrakeStatus &= ~b_rls; - else - CntrlRes->Flow(+PF(CVP, 0, 0.1) * dt); + // odluzniacz + if (true == ((BrakeStatus & b_rls) == b_rls)) + if ((CVP - VVP < 0)) + BrakeStatus &= ~b_rls; + else + CntrlRes->Flow(+PF(CVP, 0, 0.1) * dt); } -void TKE::CheckState( double const BCP, double &dV1 ) +/// +/// Drives the KE BrakeStatus state machine from the relations between +/// pre-chamber, impulse-chamber and control reservoir pressures (KE-specific +/// thresholds — pulse on the pre-chamber down to 0.8*VVP and 0.1 bar +/// initial-step). Triggers sf_Acc and sf_CylU sound flags. +/// +/// Cylinder (or impulse-chamber) pressure. +/// In/out brake-pipe flow correction (unused here). +void TKE::CheckState(double const BCP, double &dV1) { - double VVP; - double BVP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - CVP = CntrlRes->P(); + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + CVP = CntrlRes->P(); - // sprawdzanie stanu - if( BCP > 0.1 ) { + // sprawdzanie stanu + if (BCP > 0.1) + { - if( ( BrakeStatus & b_hld ) == b_hld ) { + if ((BrakeStatus & b_hld) == b_hld) + { - if( ( VVP + 0.003 + BCP / BVM ) < CVP ) { - // hamowanie stopniowe; - BrakeStatus |= b_on; - } - else { - if( ( VVP + BCP / BVM ) > CVP ) { - // zatrzymanie napelaniania; - BrakeStatus &= ~b_on; - } - if( ( VVP - 0.003 + BCP / BVM ) > CVP ) { - // luzowanie; - BrakeStatus &= ~( b_on | b_hld ); - } - } - } - else { + if ((VVP + 0.003 + BCP / BVM) < CVP) + { + // hamowanie stopniowe; + BrakeStatus |= b_on; + } + else + { + if ((VVP + BCP / BVM) > CVP) + { + // zatrzymanie napelaniania; + BrakeStatus &= ~b_on; + } + if ((VVP - 0.003 + BCP / BVM) > CVP) + { + // luzowanie; + BrakeStatus &= ~(b_on | b_hld); + } + } + } + else + { - if( ( VVP + BCP / BVM < CVP ) - && ( ( CVP - VVP ) * BVM > 0.25 ) ) { - // zatrzymanie luzowanie - BrakeStatus |= b_hld; - } - } - } - else { + if ((VVP + BCP / BVM < CVP) && ((CVP - VVP) * BVM > 0.25)) + { + // zatrzymanie luzowanie + BrakeStatus |= b_hld; + } + } + } + else + { - if( VVP + 0.1 < CVP ) { - // poczatek hamowania - if( ( BrakeStatus & b_hld ) == 0 ) { - // przyspieszacz - ValveRes->CreatePress( 0.8 * VVP ); - SoundFlag |= sf_Acc; - ValveRes->Act(); - } - BrakeStatus |= ( b_on | b_hld ); - } - } + if (VVP + 0.1 < CVP) + { + // poczatek hamowania + if ((BrakeStatus & b_hld) == 0) + { + // przyspieszacz + ValveRes->CreatePress(0.8 * VVP); + SoundFlag |= sf_Acc; + ValveRes->Act(); + } + BrakeStatus |= (b_on | b_hld); + } + } - if( ( BrakeStatus & b_hld ) == 0 ) { - SoundFlag |= sf_CylU; - } + if ((BrakeStatus & b_hld) == 0) + { + SoundFlag |= sf_CylU; + } } -double TKE::CVs( double const BP ) +/// +/// Returns the KE ZS-filling slide valve opening factor: closed once +/// any pneumatic braking is requested, slightly attenuated when the +/// pre-chamber is over-pressurised, and a constant 0.23 otherwise. +/// +/// Cylinder (or impulse) pressure. +/// Opening coefficient. +double TKE::CVs(double const BP) { - double VVP; - double BVP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); + BVP = BrakeRes->P(); + CVP = CntrlRes->P(); + VVP = ValveRes->P(); - // przeplyw ZS <-> PG - if ((BP > 0.2)) - return 0; - else if ((VVP > CVP + 0.4)) - return 0.05; - else - return 0.23; + // przeplyw ZS <-> PG + if ((BP > 0.2)) + return 0; + else if ((VVP > CVP + 0.4)) + return 0.05; + else + return 0.23; } -double TKE::BVs( double const BCP ) +/// +/// Returns the KE ZP-filling slide valve opening factor: closed when ZP +/// is already above the pre-chamber, fully open when ZP is well below the +/// control reservoir, otherwise a low refill rate (0.13). +/// +/// Impulse-chamber pressure. +/// Opening coefficient. +double TKE::BVs(double const BCP) { - double VVP; - double BVP; - double CVP; + double VVP; + double BVP; + double CVP; - BVP = BrakeRes->P(); - CVP = CntrlRes->P(); - VVP = ValveRes->P(); + BVP = BrakeRes->P(); + CVP = CntrlRes->P(); + VVP = ValveRes->P(); - // przeplyw ZP <-> rozdzielacz - if ((BVP > VVP)) - return 0; - else if ((BVP < CVP - 0.3)) - return 0.6; - else - return 0.13; + // przeplyw ZP <-> rozdzielacz + if ((BVP > VVP)) + return 0; + else if ((BVP < CVP - 0.3)) + return 0.6; + else + return 0.13; } -double TKE::GetPF( double const PP, double const dt, double const Vel ) +/// +/// One-step distributor advance for the Knorr KE. Drives CheckState/CheckReleaser, +/// integrates ZS <-> PG, ZP <-> impulse chamber and ZP <-> pre-chamber, +/// applies the velocity- and friction-pair-aware rapid step (RM, RV) and +/// the load-relay output to the brake cylinder, including the auxiliary +/// brake (LBP) and anti-slip path (ASBP). +/// +/// Brake pipe pressure [bar]. +/// Time step [s]. +/// Vehicle velocity [m/s]. +/// Net volume exchanged with the brake pipe. +double TKE::GetPF(double const PP, double const dt, double const Vel) { - double dv; - double dV1; - double temp; - double VVP; - double BVP; - double BCP; - double IMP; - double CVP; + double dv; + double dV1; + double temp; + double VVP; + double BVP; + double BCP; + double IMP; + double CVP; - BVP = BrakeRes->P(); - VVP = ValveRes->P(); - BCP = BrakeCyl->P(); - IMP = ImplsRes->P(); - CVP = CntrlRes->P(); + BVP = BrakeRes->P(); + VVP = ValveRes->P(); + BCP = BrakeCyl->P(); + IMP = ImplsRes->P(); + CVP = CntrlRes->P(); - dv = 0; - dV1 = 0; + dv = 0; + dV1 = 0; - // sprawdzanie stanu - CheckState(IMP, dV1); - CheckReleaser(dt); + // sprawdzanie stanu + CheckState(IMP, dV1); + CheckReleaser(dt); - // przeplyw ZS <-> PG - temp = CVs(IMP); - dv = PF(CVP, VVP, 0.0015 * temp) * dt; - CntrlRes->Flow(+dv); - ValveRes->Flow(-0.04 * dv); - dV1 = dV1 - 0.96 * dv; + // przeplyw ZS <-> PG + temp = CVs(IMP); + dv = PF(CVP, VVP, 0.0015 * temp) * dt; + CntrlRes->Flow(+dv); + ValveRes->Flow(-0.04 * dv); + dV1 = dV1 - 0.96 * dv; - // luzowanie - if ((BrakeStatus & b_hld) == b_off) - { - if (((BrakeDelayFlag & bdelay_G) == 0)) - temp = 0.283 + 0.139; - else - temp = 0.139; - dv = PF(0, IMP, 0.001 * temp) * dt; - } - else - dv = 0; - ImplsRes->Flow(-dv); + // luzowanie + if ((BrakeStatus & b_hld) == b_off) + { + if (((BrakeDelayFlag & bdelay_G) == 0)) + temp = 0.283 + 0.139; + else + temp = 0.139; + dv = PF(0, IMP, 0.001 * temp) * dt; + } + else + dv = 0; + ImplsRes->Flow(-dv); - // przeplyw ZP <-> silowniki - if (((BrakeStatus & b_on) == b_on) && (IMP < MaxBP)) - { - temp = 0.113; - if (((BrakeDelayFlag & bdelay_G) == 0)) - temp = temp + 0.636; - if ((BCP < 0.5)) - temp = temp + 0.785; - dv = PF(BVP, IMP, 0.001 * temp) * dt; - } - else - dv = 0; - BrakeRes->Flow(dv); - ImplsRes->Flow(-dv); + // przeplyw ZP <-> silowniki + if (((BrakeStatus & b_on) == b_on) && (IMP < MaxBP)) + { + temp = 0.113; + if (((BrakeDelayFlag & bdelay_G) == 0)) + temp = temp + 0.636; + if ((BCP < 0.5)) + temp = temp + 0.785; + dv = PF(BVP, IMP, 0.001 * temp) * dt; + } + else + dv = 0; + BrakeRes->Flow(dv); + ImplsRes->Flow(-dv); - // rapid - if (!((typeid(*FM) == typeid(TDisk1)) || - (typeid(*FM) == typeid(TDisk2)))) // jesli zeliwo to schodz - RapidStatus = ((BrakeDelayFlag & bdelay_R) == bdelay_R) && - ((RV < 0) || ((Vel > RV) && (RapidStatus)) || (Vel > (RV + 20))); - else // jesli tarczowki, to zostan - RapidStatus = ((BrakeDelayFlag & bdelay_R) == bdelay_R); + // rapid + if (!((typeid(*FM) == typeid(TDisk1)) || (typeid(*FM) == typeid(TDisk2)))) // jesli zeliwo to schodz + RapidStatus = ((BrakeDelayFlag & bdelay_R) == bdelay_R) && ((RV < 0) || ((Vel > RV) && (RapidStatus)) || (Vel > (RV + 20))); + else // jesli tarczowki, to zostan + RapidStatus = ((BrakeDelayFlag & bdelay_R) == bdelay_R); - // temp:=1.9-0.9*int(RapidStatus); + // temp:=1.9-0.9*int(RapidStatus); - if ((RM * RM > 0.001)) // jesli jest rapid - if ((RM > 0)) // jesli dodatni (naddatek); - temp = 1 - RM * int(RapidStatus); - else - temp = 1 - RM * (1 - int(RapidStatus)); - else - temp = 1; - temp = temp / LoadC; - // luzowanie CH - // temp:=Max0R(BCP,LBP); - IMP = Max0R(IMP / temp, Max0R(LBP, ASBP * int((BrakeStatus & b_asb) == b_asb))); + if ((RM * RM > 0.001)) // jesli jest rapid + if ((RM > 0)) // jesli dodatni (naddatek); + temp = 1 - RM * int(RapidStatus); + else + temp = 1 - RM * (1 - int(RapidStatus)); + else + temp = 1; + temp = temp / LoadC; + // luzowanie CH + // temp:=Max0R(BCP,LBP); + IMP = Max0R(IMP / temp, Max0R(LBP, ASBP * int((BrakeStatus & b_asb) == b_asb))); if ((ASBP < 0.1) && ((BrakeStatus & b_asb) == b_asb)) IMP = 0; - // luzowanie CH - if ((BCP > IMP + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.25)) - dv = PFVd(BCP, 0, 0.05, IMP) * dt; - else - dv = 0; - BrakeCyl->Flow(-dv); - if ((BCP < IMP - 0.005) && (Max0R(ImplsRes->P(), 8 * LBP) > 0.3)) - dv = PFVa(BVP, BCP, 0.05, IMP) * dt; - else - dv = 0; - BrakeRes->Flow(-dv); - BrakeCyl->Flow(+dv); + // luzowanie CH + if ((BCP > IMP + 0.005) || (Max0R(ImplsRes->P(), 8 * LBP) < 0.25)) + dv = PFVd(BCP, 0, 0.05, IMP) * dt; + else + dv = 0; + BrakeCyl->Flow(-dv); + if ((BCP < IMP - 0.005) && (Max0R(ImplsRes->P(), 8 * LBP) > 0.3)) + dv = PFVa(BVP, BCP, 0.05, IMP) * dt; + else + dv = 0; + BrakeRes->Flow(-dv); + BrakeCyl->Flow(+dv); - // przeplyw ZP <-> rozdzielacz - temp = BVs(IMP); - // if(BrakeStatus and b_hld)=b_off then - if ((IMP < 0.25) || (VVP + 0.05 > BVP)) - dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; - else - dv = 0; - BrakeRes->Flow(dv); - dV1 = dV1 + dv * 0.96; - ValveRes->Flow(-0.04 * dv); - // przeplyw PG <-> rozdzielacz - dv = PF(PP, VVP, 0.01) * dt; - ValveRes->Flow(-dv); + // przeplyw ZP <-> rozdzielacz + temp = BVs(IMP); + // if(BrakeStatus and b_hld)=b_off then + if ((IMP < 0.25) || (VVP + 0.05 > BVP)) + dv = PF(BVP, VVP, 0.02 * SizeBR * temp / 1.87) * dt; + else + dv = 0; + BrakeRes->Flow(dv); + dV1 = dV1 + dv * 0.96; + ValveRes->Flow(-0.04 * dv); + // przeplyw PG <-> rozdzielacz + dv = PF(PP, VVP, 0.01) * dt; + ValveRes->Flow(-dv); - ValveRes->Act(); - BrakeCyl->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - ImplsRes->Act(); - return dv - dV1; + ValveRes->Act(); + BrakeCyl->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + ImplsRes->Act(); + return dv - dV1; } -void TKE::Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ) +/// +/// Initialises the KE distributor: pre-charges valve / brake / control / +/// impulse reservoirs (ZS = 5 l, KI = 1 l), clears BrakeStatus and computes +/// BVM (= MaxBP / (HPP-LPP)). +/// +/// Brake pipe pressure [bar]. +/// High (control) pressure [bar]. +/// Low pressure threshold [bar]. +/// Initial cylinder pressure [bar]. +/// Initial brake delay flag. +void TKE::Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) { - TBrake::Init(PP, HPP, LPP, BP, BDF); - ValveRes->CreatePress(PP); - BrakeCyl->CreatePress(BP); - BrakeRes->CreatePress(PP); + TBrake::Init(PP, HPP, LPP, BP, BDF); + ValveRes->CreatePress(PP); + BrakeCyl->CreatePress(BP); + BrakeRes->CreatePress(PP); - CntrlRes->CreateCap(5); - CntrlRes->CreatePress(HPP); + CntrlRes->CreateCap(5); + CntrlRes->CreatePress(HPP); - ImplsRes->CreateCap(1); - ImplsRes->CreatePress(BP); + ImplsRes->CreateCap(1); + ImplsRes->CreatePress(BP); - BrakeStatus = b_off; + BrakeStatus = b_off; - BVM = 1.0 / (HPP - LPP) * MaxBP; + BVM = 1.0 / (HPP - LPP) * MaxBP; - BrakeDelayFlag = BDF; + BrakeDelayFlag = BDF; } +/// Returns the control reservoir (ZS) pressure. double TKE::GetCRP() { - return CntrlRes->P(); + return CntrlRes->P(); } -double TKE::GetHPFlow( double const HP, double const dt ) +/// +/// High-pressure replenishment for KE: pulls air into the auxiliary +/// reservoir from the main reservoir whenever the source is higher. +/// +/// High-pressure source [bar]. +/// Time step [s]. +/// Inflow into BrakeRes (negative on intake). +double TKE::GetHPFlow(double const HP, double const dt) { - double dv; + double dv; - dv = PF(HP, BrakeRes->P(), 0.01) * dt; - dv = Min0R(0, dv); - BrakeRes->Flow(-dv); - return dv; + dv = PF(HP, BrakeRes->P(), 0.01) * dt; + dv = Min0R(0, dv); + BrakeRes->Flow(-dv); + return dv; } -void TKE::PLC( double const mass ) +/// Recomputes the load-weighing coefficient LoadC for the current mass. +/// Current vehicle mass. +void TKE::PLC(double const mass) { - LoadC = 1 + - int(mass < LoadM) * - ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); + LoadC = 1 + int(mass < LoadM) * ((TareBP + (MaxBP - TareBP) * (mass - TareM) / (LoadM - TareM)) / MaxBP - 1); } -void TKE::SetLP( double const TM, double const LM, double const TBP ) +/// Stores the load-weighing parameters. +/// Tare (empty) mass. +/// Loaded mass. +/// Tare-mass cylinder pressure. +void TKE::SetLP(double const TM, double const LM, double const TBP) { - TareM = TM; - LoadM = LM; - TareBP = TBP; + TareM = TM; + LoadM = LM; + TareBP = TBP; } -void TKE::SetRM( double const RMR ) +/// Sets the rapid-step ratio. RM = 1 - RMR. +/// Reduction ratio. +void TKE::SetRM(double const RMR) { - RM = 1.0 - RMR; + RM = 1.0 - RMR; } -void TKE::SetLBP( double const P ) +/// Sets the auxiliary (local) brake target pressure. +/// Auxiliary brake pressure [bar]. +void TKE::SetLBP(double const P) { - LBP = P; + LBP = P; } -void TKE::ForceEmptiness() { +/// +/// Vents valve, brake, control, impulse and secondary auxiliary reservoirs +/// to zero pressure (used on vehicle reset / decoupling). +/// +void TKE::ForceEmptiness() +{ - ValveRes->CreatePress( 0 ); - BrakeRes->CreatePress( 0 ); - CntrlRes->CreatePress( 0 ); - ImplsRes->CreatePress( 0 ); - Brak2Res->CreatePress( 0 ); + ValveRes->CreatePress(0); + BrakeRes->CreatePress(0); + CntrlRes->CreatePress(0); + ImplsRes->CreatePress(0); + Brak2Res->CreatePress(0); - ValveRes->Act(); - BrakeRes->Act(); - CntrlRes->Act(); - ImplsRes->Act(); - Brak2Res->Act(); + ValveRes->Act(); + BrakeRes->Act(); + CntrlRes->Act(); + ImplsRes->Act(); + Brak2Res->Act(); } //---KRANY--- +/// Default brake-pipe flow — 0. Concrete handles override. double TDriverHandle::GetPF(double const i_bcp, double PP, double HP, double dt, double ep) { - return 0; + return 0; } +/// Default initialisation — disables the time / EP-time chambers. +/// Initial pressure (unused in the base implementation). void TDriverHandle::Init(double Press) { - Time = false; - TimeEP = false; + Time = false; + TimeEP = false; } -void TDriverHandle::SetReductor(double nAdj) -{ -} +/// Default reductor adjustment — no-op. +/// Pressure correction. +void TDriverHandle::SetReductor(double nAdj) {} +/// Default cab-gauge pressure — 0. double TDriverHandle::GetCP() { - return 0; + return 0; } +/// Default EP intensity — 0. double TDriverHandle::GetEP() { return 0; } +/// Default regulator pressure — 0. double TDriverHandle::GetRP() { return 0; } +/// Default per-channel sound magnitude — 0. +/// Sound channel index. double TDriverHandle::GetSound(int i) { - return 0; + return 0; } +/// Default position lookup — 0 (i.e. unknown). +/// Function code (bh_*). double TDriverHandle::GetPos(int i) { - return 0; + return 0; } +/// Default EP intensity for a handle position — 0. +/// Handle position. double TDriverHandle::GetEP(double pos) { - return 0; + return 0; } +/// +/// Latches the manual overcharge / assimilation button state. +/// +/// True while the button is pressed. void TDriverHandle::OvrldButton(bool Active) { ManualOvrldActive = Active; } +/// Stores the universal-button flags (combined ub_* values). +/// Universal-button bitfield. void TDriverHandle::SetUniversalFlag(int flag) { UniversalFlag = flag; } //---FV4a--- +/// +/// Computes brake-pipe flow for the classic FV4a handle. Reads target pipe +/// pressure and flow speed from the BPT[] table for the current detent, +/// integrates the control (CP) and reductor (RP) reservoirs, and selects +/// the main-valve flow path based on the handle position (charge stroke at +/// -1, running-position bias at 0, full vent at the maximum detent). +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. double TFV4a::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - static int const LBDelay = 100; + static int const LBDelay = 100; - ep = PP; // SPKS!! - double LimPP = std::min(BPT[std::lround(i_bcp) + 2][1], HP); - double ActFlowSpeed = BPT[std::lround(i_bcp) + 2][0]; + ep = PP; // SPKS!! + double LimPP = std::min(BPT[std::lround(i_bcp) + 2][1], HP); + double ActFlowSpeed = BPT[std::lround(i_bcp) + 2][0]; - if ((i_bcp == i_bcpno)) - LimPP = 2.9; + if ((i_bcp == i_bcpno)) + LimPP = 2.9; - CP = CP + 20 * std::min(std::abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt / 1; - RP = RP + 20 * std::min(std::abs(ep - RP), 0.05) * PR(RP, ep) * dt / 2.5; + CP = CP + 20 * std::min(std::abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt / 1; + RP = RP + 20 * std::min(std::abs(ep - RP), 0.05) * PR(RP, ep) * dt / 2.5; - LimPP = CP; - double dpPipe = std::min(HP, LimPP); + LimPP = CP; + double dpPipe = std::min(HP, LimPP); - double dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; - if ((CP > RP + 0.05)) - dpMainValve = PF(std::min(CP + 0.1, HP), PP, 1.1 * ActFlowSpeed / LBDelay) * dt; - if ((CP < RP - 0.05)) - dpMainValve = PF(CP - 0.1, PP, 1.1 * ActFlowSpeed / LBDelay) * dt; + double dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; + if ((CP > RP + 0.05)) + dpMainValve = PF(std::min(CP + 0.1, HP), PP, 1.1 * ActFlowSpeed / LBDelay) * dt; + if ((CP < RP - 0.05)) + dpMainValve = PF(CP - 0.1, PP, 1.1 * ActFlowSpeed / LBDelay) * dt; - if (lround(i_bcp) == -1) - { - CP = CP + 5 * std::min(std::abs(LimPP - CP), 0.2) * PR(CP, LimPP) * dt / 2; - if ((CP < RP + 0.03)) - if ((TP < 5)) - TP = TP + dt; - // if(cp+0.03<5.4)then - if ((RP + 0.03 < 5.4) || (CP + 0.03 < 5.4)) // fala - dpMainValve = PF(std::min(HP, 17.1), PP, ActFlowSpeed / LBDelay) * dt; - // dpMainValve:=20*Min0R(abs(ep-7.1),0.05)*PF(HP,pp,ActFlowSpeed/LBDelay)*dt; - else - { - RP = 5.45; - if ((CP < PP - 0.01)) //: /34*9 - dpMainValve = PF(dpPipe, PP, ActFlowSpeed / 34 * 9 / LBDelay) * dt; - else - dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; - } - } + if (lround(i_bcp) == -1) + { + CP = CP + 5 * std::min(std::abs(LimPP - CP), 0.2) * PR(CP, LimPP) * dt / 2; + if ((CP < RP + 0.03)) + if ((TP < 5)) + TP = TP + dt; + // if(cp+0.03<5.4)then + if ((RP + 0.03 < 5.4) || (CP + 0.03 < 5.4)) // fala + dpMainValve = PF(std::min(HP, 17.1), PP, ActFlowSpeed / LBDelay) * dt; + // dpMainValve:=20*Min0R(abs(ep-7.1),0.05)*PF(HP,pp,ActFlowSpeed/LBDelay)*dt; + else + { + RP = 5.45; + if ((CP < PP - 0.01)) //: /34*9 + dpMainValve = PF(dpPipe, PP, ActFlowSpeed / 34 * 9 / LBDelay) * dt; + else + dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; + } + } - if ((lround(i_bcp) == 0)) - { - if ((TP > 0.1)) - { - CP = 5 + (TP - 0.1) * 0.08; - TP = TP - dt / 12 / 2; - } - if ((CP > RP + 0.1) && (CP <= 5)) - dpMainValve = PF(std::min(CP + 0.25, HP), PP, 2 * ActFlowSpeed / LBDelay) * dt; - else if (CP > 5) - dpMainValve = PF(std::min(CP, HP), PP, 2 * ActFlowSpeed / LBDelay) * dt; - else - dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; - } + if ((lround(i_bcp) == 0)) + { + if ((TP > 0.1)) + { + CP = 5 + (TP - 0.1) * 0.08; + TP = TP - dt / 12 / 2; + } + if ((CP > RP + 0.1) && (CP <= 5)) + dpMainValve = PF(std::min(CP + 0.25, HP), PP, 2 * ActFlowSpeed / LBDelay) * dt; + else if (CP > 5) + dpMainValve = PF(std::min(CP, HP), PP, 2 * ActFlowSpeed / LBDelay) * dt; + else + dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; + } - if ((lround(i_bcp) == i_bcpno)) - { - dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; - } + if ((lround(i_bcp) == i_bcpno)) + { + dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; + } - return dpMainValve; + return dpMainValve; } +/// Initialises CP and RP to the supplied pressure. +/// Initial pressure [bar]. void TFV4a::Init(double Press) { - CP = Press; - RP = Press; + CP = Press; + RP = Press; } //---FV4a/M--- nowonapisany kran bez poprawki IC +/// +/// Computes brake-pipe flow for the FV4a/M handle. Adds a release pressure +/// wave (XP/Fala) and a time-chamber driven overcharge stroke on top of the +/// FV4a logic; clamps i_bcp to the supported range, integrates CP/RP/TP/XP +/// and updates the Sounds[] channels for braking / release / wave / time +/// outflow / emergency. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. double TFV4aM::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - int const LBDelay { 100 }; - double const xpM { 0.3 }; // mnoznik membrany komory pod + int const LBDelay{100}; + double const xpM{0.3}; // mnoznik membrany komory pod - ep = (PP / 2.0) * 1.5 + (ep / 2.0) * 0.5; // SPKS!! + ep = (PP / 2.0) * 1.5 + (ep / 2.0) * 0.5; // SPKS!! - for( int idx = 0; idx < 5; ++idx ) { - Sounds[ idx ] = 0; - } + for (int idx = 0; idx < 5; ++idx) + { + Sounds[idx] = 0; + } - // na wszelki wypadek, zeby nie wyszlo poza zakres - i_bcp = clamp( i_bcp, -1.999, 5.999 ); + // na wszelki wypadek, zeby nie wyszlo poza zakres + i_bcp = clamp(i_bcp, -1.999, 5.999); - double DP{ 0.0 }; - if( TP > 0.0 ) { - // jesli czasowy jest niepusty - DP = 0.045; // 2.5 w 55 sekund (5,35->5,15 w PG) - TP -= DP * dt; - Sounds[s_fv4a_t] = DP; - } - else { - //.08 - TP = 0.0; - } + double DP{0.0}; + if (TP > 0.0) + { + // jesli czasowy jest niepusty + DP = 0.045; // 2.5 w 55 sekund (5,35->5,15 w PG) + TP -= DP * dt; + Sounds[s_fv4a_t] = DP; + } + else + { + //.08 + TP = 0.0; + } - if (XP > 0) { - // jesli komora pod niepusta jest niepusty - DP = 2.5; - Sounds[s_fv4a_x] = DP * XP; - XP -= dt * DP * 2.0; // od cisnienia 5 do 0 w 10 sekund ((5-0)*dt/10) - } - else { - // jak pusty, to pusty - XP = 0.0; - } + if (XP > 0) + { + // jesli komora pod niepusta jest niepusty + DP = 2.5; + Sounds[s_fv4a_x] = DP * XP; + XP -= dt * DP * 2.0; // od cisnienia 5 do 0 w 10 sekund ((5-0)*dt/10) + } + else + { + // jak pusty, to pusty + XP = 0.0; + } - double pom; - if( EQ( i_bcp, -1.0 ) ) { - pom = std::min( HP, 5.4 + RedAdj ); - } - else { - pom = std::min( CP, HP ); - } + double pom; + if (EQ(i_bcp, -1.0)) + { + pom = std::min(HP, 5.4 + RedAdj); + } + else + { + pom = std::min(CP, HP); + } - if( pom > RP + 0.25 ) { - Fala = true; - } - if( Fala ) { - if( pom > RP + 0.3 ) { - XP = XP - 20.0 * PR( pom, XP ) * dt; - } - else { - Fala = false; - } - } + if (pom > RP + 0.25) + { + Fala = true; + } + if (Fala) + { + if (pom > RP + 0.3) + { + XP = XP - 20.0 * PR(pom, XP) * dt; + } + else + { + Fala = false; + } + } - double LimPP = std::min( - LPP_RP( i_bcp ) + TP * 0.08 + RedAdj, - HP ); // pozycja + czasowy lub zasilanie + double LimPP = std::min(LPP_RP(i_bcp) + TP * 0.08 + RedAdj, + HP); // pozycja + czasowy lub zasilanie - // zbiornik sterujacy - if( LimPP > CP ) { - // podwyzszanie szybkie - CP += - 5.0 * 60.0 - * std::min( - std::abs( LimPP - CP ), - 0.05 ) - * PR( CP, LimPP ) - * dt; - } - else { - CP += - 13 - * std::min( - std::abs( LimPP - CP ), - 0.05 ) - * PR( CP, LimPP ) - * dt; - } + // zbiornik sterujacy + if (LimPP > CP) + { + // podwyzszanie szybkie + CP += 5.0 * 60.0 * std::min(std::abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; + } + else + { + CP += 13 * std::min(std::abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; + } - LimPP = pom; // cp - double const dpPipe = std::min(HP, LimPP + XP * xpM); + LimPP = pom; // cp + double const dpPipe = std::min(HP, LimPP + XP * xpM); - double const ActFlowSpeed = BPT[ std::lround( i_bcp ) + 2 ][ 0 ]; + double const ActFlowSpeed = BPT[std::lround(i_bcp) + 2][0]; - double dpMainValve = ( - dpPipe > PP ? - -PFVa( HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4 ) : - PFVd( PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4 ) ); + double dpMainValve = (dpPipe > PP ? -PFVa(HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4) : PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4)); - if (EQ(i_bcp, -1)) { + if (EQ(i_bcp, -1)) + { - if( TP < 5 ) { TP += dt; } - if( TP < 1 ) { TP -= 0.5 * dt; } - } + if (TP < 5) + { + TP += dt; + } + if (TP < 1) + { + TP -= 0.5 * dt; + } + } - if (EQ(i_bcp, 0)) { + if (EQ(i_bcp, 0)) + { - if( TP > 2 ) { - dpMainValve *= 1.5; - } - } + if (TP > 2) + { + dpMainValve *= 1.5; + } + } - ep = dpPipe; - if( ( EQ( i_bcp, 0 ) - || ( RP > ep ) ) ) { - // powolne wzrastanie, ale szybsze na jezdzie; - RP += PF( RP, ep, 0.0007 ) * dt; - } - else { - // powolne wzrastanie i to bardzo - RP += PF( RP, ep, 0.000093 / 2 * 2 ) * dt; - } - // jednak trzeba wydluzyc, bo obecnie zle dziala - if( ( RP < ep ) - && ( RP < BPT[ std::lround( i_bcpno ) + 2 ][ 1 ] ) ) { - // jesli jestesmy ponizej cisnienia w sterujacym (2.9 bar) - // przypisz cisnienie w PG - wydluzanie napelniania o czas potrzebny do napelnienia PG - RP += PF( RP, CP, 0.005 ) * dt; - } + ep = dpPipe; + if ((EQ(i_bcp, 0) || (RP > ep))) + { + // powolne wzrastanie, ale szybsze na jezdzie; + RP += PF(RP, ep, 0.0007) * dt; + } + else + { + // powolne wzrastanie i to bardzo + RP += PF(RP, ep, 0.000093 / 2 * 2) * dt; + } + // jednak trzeba wydluzyc, bo obecnie zle dziala + if ((RP < ep) && (RP < BPT[std::lround(i_bcpno) + 2][1])) + { + // jesli jestesmy ponizej cisnienia w sterujacym (2.9 bar) + // przypisz cisnienie w PG - wydluzanie napelniania o czas potrzebny do napelnienia PG + RP += PF(RP, CP, 0.005) * dt; + } - if( ( EQ( i_bcp, i_bcpno ) ) - || ( EQ( i_bcp, -2 ) ) ) { + if ((EQ(i_bcp, i_bcpno)) || (EQ(i_bcp, -2))) + { - DP = PF( 0.0, PP, ActFlowSpeed / LBDelay ); - dpMainValve = DP; - Sounds[s_fv4a_e] = DP; - Sounds[s_fv4a_u] = 0.0; - Sounds[s_fv4a_b] = 0.0; - Sounds[s_fv4a_x] = 0.0; - } - else { + DP = PF(0.0, PP, ActFlowSpeed / LBDelay); + dpMainValve = DP; + Sounds[s_fv4a_e] = DP; + Sounds[s_fv4a_u] = 0.0; + Sounds[s_fv4a_b] = 0.0; + Sounds[s_fv4a_x] = 0.0; + } + else + { - if( dpMainValve > 0.0 ) { - Sounds[ s_fv4a_b ] = dpMainValve; - } - else { - Sounds[ s_fv4a_u ] = -dpMainValve; - } - } + if (dpMainValve > 0.0) + { + Sounds[s_fv4a_b] = dpMainValve; + } + else + { + Sounds[s_fv4a_u] = -dpMainValve; + } + } - return dpMainValve * dt; + return dpMainValve * dt; } +/// Initialises CP and RP to the supplied pressure. +/// Initial pressure [bar]. void TFV4aM::Init(double Press) { - CP = Press; - RP = Press; + CP = Press; + RP = Press; } +/// Sets the reductor adjustment offset (turning the reductor cap). +/// Pressure correction [bar]. void TFV4aM::SetReductor(double nAdj) { - RedAdj = nAdj; + RedAdj = nAdj; } +/// Returns Sounds[i] for valid indices, 0 otherwise. +/// Sound channel index (s_fv4a_*). double TFV4aM::GetSound(int i) { - if (i > 4) - return 0; - else - return Sounds[i]; + if (i > 4) + return 0; + else + return Sounds[i]; } +/// Returns pos_table[i] (handle position for the requested function code). +/// Function code (bh_*). double TFV4aM::GetPos(int i) { - return pos_table[i]; + return pos_table[i]; } +/// Returns the time-chamber pressure (TP). double TFV4aM::GetCP() { return TP; } +/// Returns the regulator target — 5 bar nominal plus TP * 0.08 plus RedAdj. double TFV4aM::GetRP() { - return 5.0 +TP * 0.08 + RedAdj; + return 5.0 + TP * 0.08 + RedAdj; } +/// +/// Returns the target brake-pipe pressure for a continuous handle position +/// by linearly interpolating column 1 of BPT[] between the two surrounding +/// detents. +/// +/// Continuous handle position. +/// Interpolated target pressure [bar]. double TFV4aM::LPP_RP(double pos) // cisnienie z zaokraglonej pozycji; { - int const i_pos = 2 + std::floor( pos ); // zaokraglone w dol + int const i_pos = 2 + std::floor(pos); // zaokraglone w dol - return - BPT[i_pos][1] - + (BPT[i_pos + 1][1] - BPT[i_pos][1]) * ((pos + 2) - i_pos); // interpolacja liniowa + return BPT[i_pos][1] + (BPT[i_pos + 1][1] - BPT[i_pos][1]) * ((pos + 2) - i_pos); // interpolacja liniowa } +/// Returns true if pos is within ±0.5 of i_pos (detent test). +/// Continuous handle position. +/// Detent centre. bool TFV4aM::EQ(double pos, double i_pos) { - return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); + return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); } //---MHZ_EN57--- manipulator hamulca zespolonego do EN57 -double TMHZ_EN57::GetPF( double i_bcp, double PP, double HP, double dt, double ep ) { - static int const LBDelay = 100; +/// +/// Computes brake-pipe flow for the MHZ_EN57 combined handle. Drives CP/TP +/// based on the position via , supports auto/manual +/// overcharge (Auto/ManualOvrld and ub_HighPressure / ub_Overload buttons), +/// emits emergency-vent flow at the extreme detents, and exposes EP intensity +/// via the position-encoded RP value. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. +double TMHZ_EN57::GetPF(double i_bcp, double PP, double HP, double dt, double ep) +{ + static int const LBDelay = 100; - double LimPP; - double dpPipe; - double dpMainValve; - double ActFlowSpeed; - double DP; - double pom; + double LimPP; + double dpPipe; + double dpMainValve; + double ActFlowSpeed; + double DP; + double pom; - for( int idx = 0; idx < 5; ++idx ) { - Sounds[ idx ] = 0; - } + for (int idx = 0; idx < 5; ++idx) + { + Sounds[idx] = 0; + } - DP = 0; + DP = 0; - i_bcp = Max0R(Min0R(i_bcp, 9.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres + i_bcp = Max0R(Min0R(i_bcp, 9.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres - if ((TP > 0)&&(CP > 4.9)) - { - DP = OverloadPressureDecrease; - if (EQ(i_bcp, 0)) - TP = TP - DP * dt; - Sounds[s_fv4a_t] = DP; - } - else - { - TP = 0; - } + if ((TP > 0) && (CP > 4.9)) + { + DP = OverloadPressureDecrease; + if (EQ(i_bcp, 0)) + TP = TP - DP * dt; + Sounds[s_fv4a_t] = DP; + } + else + { + TP = 0; + } - LimPP = Min0R(LPP_RP(i_bcp) + TP * 0.08 + RedAdj, HP); // pozycja + czasowy lub zasilanie - ActFlowSpeed = 4; + LimPP = Min0R(LPP_RP(i_bcp) + TP * 0.08 + RedAdj, HP); // pozycja + czasowy lub zasilanie + ActFlowSpeed = 4; - double uop = UnbrakeOverPressure; //unbrake over pressure in actual state - ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); //button is pressed - if (ManualOvrld && !ManualOvrldActive) //no overpressure for not pressed button if it does not exists + double uop = UnbrakeOverPressure; // unbrake over pressure in actual state + ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); // button is pressed + if (ManualOvrld && !ManualOvrldActive) // no overpressure for not pressed button if it does not exists uop = 0; - if ( ( EQ( i_bcp, -1 ) ) && ( uop > 0 ) ) - pom = Min0R(HP, 5.4 + RedAdj + uop); - else - pom = Min0R(CP, HP); + if ((EQ(i_bcp, -1)) && (uop > 0)) + pom = Min0R(HP, 5.4 + RedAdj + uop); + else + pom = Min0R(CP, HP); - if ((LimPP > CP)) // podwyzszanie szybkie - CP = CP + 60 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy; - else - CP = CP + 13 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy + if ((LimPP > CP)) // podwyzszanie szybkie + CP = CP + 60 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy; + else + CP = CP + 13 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy - LimPP = pom; // cp - //if (EQ(i_bcp, -1)) - // dpPipe = HP; - // else - dpPipe = Min0R(HP, LimPP); + LimPP = pom; // cp + // if (EQ(i_bcp, -1)) + // dpPipe = HP; + // else + dpPipe = Min0R(HP, LimPP); - if (dpPipe > PP) - dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4); - else - dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); + if (dpPipe > PP) + dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, dpPipe, 0.4); + else + dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if ( ( EQ(i_bcp, -1) && ( AutoOvrld ) ) - ||(i_bcp<0.5 && (UniversalFlag & TUniversalBrake::ub_Overload))) - { - if ((TP < 5)) - TP = TP + dt; // 5/10 - if ((TP < OverloadMaxPressure)) - TP = TP - 0.5 * dt; // 5/10 - } + if ((EQ(i_bcp, -1) && (AutoOvrld)) || (i_bcp < 0.5 && (UniversalFlag & TUniversalBrake::ub_Overload))) + { + if ((TP < 5)) + TP = TP + dt; // 5/10 + if ((TP < OverloadMaxPressure)) + TP = TP - 0.5 * dt; // 5/10 + } - if ((EQ(i_bcp, 10)) || (EQ(i_bcp, -2))) - { - DP = PF(0, PP, 2 * ActFlowSpeed / LBDelay); - dpMainValve = DP; - Sounds[s_fv4a_e] = DP; - Sounds[s_fv4a_u] = 0; - Sounds[s_fv4a_b] = 0; - Sounds[s_fv4a_x] = 0; - } - else - { - if (dpMainValve > 0) - Sounds[s_fv4a_b] = dpMainValve; - else - Sounds[s_fv4a_u] = -dpMainValve; - } + if ((EQ(i_bcp, 10)) || (EQ(i_bcp, -2))) + { + DP = PF(0, PP, 2 * ActFlowSpeed / LBDelay); + dpMainValve = DP; + Sounds[s_fv4a_e] = DP; + Sounds[s_fv4a_u] = 0; + Sounds[s_fv4a_b] = 0; + Sounds[s_fv4a_x] = 0; + } + else + { + if (dpMainValve > 0) + Sounds[s_fv4a_b] = dpMainValve; + else + Sounds[s_fv4a_u] = -dpMainValve; + } - if ((i_bcp < 1.5)) - RP = Max0R(0, 0.125 * i_bcp); - else - RP = Min0R(1, 0.125 * i_bcp - 0.125); + if ((i_bcp < 1.5)) + RP = Max0R(0, 0.125 * i_bcp); + else + RP = Min0R(1, 0.125 * i_bcp - 0.125); - return dpMainValve * dt; + return dpMainValve * dt; } +/// Initialises CP to the supplied pressure. +/// Initial pressure [bar]. void TMHZ_EN57::Init(double Press) { - CP = Press; + CP = Press; } +/// Sets the reductor adjustment offset. +/// Pressure correction [bar]. void TMHZ_EN57::SetReductor(double nAdj) { - RedAdj = nAdj; + RedAdj = nAdj; } +/// Returns Sounds[i] for valid indices, 0 otherwise. +/// Sound channel index. double TMHZ_EN57::GetSound(int i) { - if (i > 4) - return 0; - else - return Sounds[i]; + if (i > 4) + return 0; + else + return Sounds[i]; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TMHZ_EN57::GetPos(int i) { - return pos_table[i]; + return pos_table[i]; } +/// Returns RP — the regulator-target value computed during the last GetPF call. double TMHZ_EN57::GetCP() { - return RP; + return RP; } +/// Returns the regulator target (5 + RedAdj). double TMHZ_EN57::GetRP() { return 5.0 + RedAdj; } +/// +/// Returns the EP brake intensity for a given handle position +/// (linear ramp 0..1 between positions 0 and 8, zero above 9.5). +/// +/// Handle position. double TMHZ_EN57::GetEP(double pos) { - if (pos < 9.5) - return Min0R(Max0R(0, 0.125 * pos), 1); - else - return 0; + if (pos < 9.5) + return Min0R(Max0R(0, 0.125 * pos), 1); + else + return 0; } +/// +/// Returns the target brake-pipe pressure for a given handle position +/// (5 bar at running, gentle pressure reduction past position 0.5, steeper +/// reduction past position 8.5 toward emergency). +/// +/// Continuous handle position. +/// Target brake-pipe pressure [bar]. double TMHZ_EN57::LPP_RP(double pos) // cisnienie z zaokraglonej pozycji; { - if (pos > 8.5) - return 5.0 - 0.15 * pos - 0.35; - else if (pos > 0.5) - return 5.0 - 0.15 * pos - 0.1; - else - return 5.0; + if (pos > 8.5) + return 5.0 - 0.15 * pos - 0.35; + else if (pos > 0.5) + return 5.0 - 0.15 * pos - 0.1; + else + return 5.0; } +/// +/// Configures handle parameters: auto / manual overcharge support, the +/// unbrake over-pressure value (also enables the wave latch), the maximum +/// overcharge pressure and the overcharge decay rate. +/// +/// Auto-overcharge enabled. +/// Manual-overcharge enabled. +/// Unbrake over-pressure [bar]. +/// Overload (assimilation) max pressure. +/// Overload pressure decay rate. void TMHZ_EN57::SetParams(bool AO, bool MO, double OverP, double, double OMP, double OPD) { AutoOvrld = AO; @@ -2738,17 +3453,30 @@ void TMHZ_EN57::SetParams(bool AO, bool MO, double OverP, double, double OMP, do Fala = (OverP > 0.01); OverloadMaxPressure = OMP; OverloadPressureDecrease = OPD; - } +/// Returns true if pos is within ±0.5 of i_pos (detent test). bool TMHZ_EN57::EQ(double pos, double i_pos) { - return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); + return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); } //---MHZ_K5P--- manipulator hamulca zespolonego Knorr 5-ciopozycyjny -double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { +/// +/// Computes brake-pipe flow for the Knorr 5-position MHZ_K5P handle +/// (release / cut-off / brake / emergency layout). Handles auto / manual +/// overcharge, the optional release wave (Fala) with FillingStrokeFactor, +/// and the emergency vent at position 3. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. +double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) +{ static int const LBDelay = 100; double LimCP; @@ -2758,7 +3486,8 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) double DP; double pom; - for (int idx = 0; idx < 5; ++idx) { + for (int idx = 0; idx < 5; ++idx) + { Sounds[idx] = 0; } @@ -2766,7 +3495,7 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) i_bcp = Max0R(Min0R(i_bcp, 2.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres - if ((TP > 0)&&(CP>4.9)) + if ((TP > 0) && (CP > 4.9)) { DP = OverloadPressureDecrease; TP = TP - DP * dt; @@ -2774,14 +3503,14 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) } else { - //TP = 0; //tu nie powinno być nic, ciśnienie zostaje jak było + // TP = 0; //tu nie powinno być nic, ciśnienie zostaje jak było } - - if (EQ(i_bcp, 1)) //odcięcie - nie rób nic + + if (EQ(i_bcp, 1)) // odcięcie - nie rób nic LimCP = CP; - else if (i_bcp > 1) //hamowanie + else if (i_bcp > 1) // hamowanie LimCP = 3.4; - else //luzowanie + else // luzowanie LimCP = 5.0; pom = CP; LimCP = Min0R(LimCP, HP); // pozycja + czasowy lub zasilanie @@ -2792,9 +3521,9 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else CP = CP + 9 * Min0R(abs(LimCP - CP), 0.05) * PR(CP, LimCP) * dt; // zbiornik sterujacy - double uop = UnbrakeOverPressure; //unbrake over pressure in actual state - ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); //button is pressed - if (ManualOvrld && !ManualOvrldActive) //no overpressure for not pressed button if it does not exists + double uop = UnbrakeOverPressure; // unbrake over pressure in actual state + ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); // button is pressed + if (ManualOvrld && !ManualOvrldActive) // no overpressure for not pressed button if it does not exists uop = 0; dpPipe = Min0R(HP, CP + TP + RedAdj); @@ -2817,10 +3546,10 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if ((EQ(i_bcp, -1) && (AutoOvrld)) || ((i_bcp<0.5) && (UniversalFlag & TUniversalBrake::ub_Overload))) + if ((EQ(i_bcp, -1) && (AutoOvrld)) || ((i_bcp < 0.5) && (UniversalFlag & TUniversalBrake::ub_Overload))) { if ((TP < OverloadMaxPressure)) - TP = TP + 0.03 * dt; + TP = TP + 0.03 * dt; } if (EQ(i_bcp, 3)) @@ -2843,6 +3572,8 @@ double TMHZ_K5P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) return dpMainValve * dt; } +/// Initialises CP and enables the time / EP-time chambers. +/// Initial pressure [bar]. void TMHZ_K5P::Init(double Press) { CP = Press; @@ -2850,11 +3581,15 @@ void TMHZ_K5P::Init(double Press) TimeEP = true; } +/// Sets the reductor adjustment offset. +/// Pressure correction [bar]. void TMHZ_K5P::SetReductor(double nAdj) { RedAdj = nAdj; } +/// Returns Sounds[i] for valid indices, 0 otherwise. +/// Sound channel index. double TMHZ_K5P::GetSound(int i) { if (i > 4) @@ -2863,21 +3598,36 @@ double TMHZ_K5P::GetSound(int i) return Sounds[i]; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TMHZ_K5P::GetPos(int i) { return pos_table[i]; } +/// Returns CP. double TMHZ_K5P::GetCP() { return CP; } +/// Returns the regulator target (5 + TP + RedAdj). double TMHZ_K5P::GetRP() { return 5.0 + TP + RedAdj; } +/// +/// Configures handle parameters: auto/manual overcharge, unbrake over-pressure +/// (also drives the Fala latch), filling-stroke factor (FSF + 1) and the +/// overcharge max pressure / decay rate. +/// +/// Auto-overcharge enabled. +/// Manual-overcharge enabled. +/// Unbrake over-pressure [bar]. +/// Filling-stroke factor offset (FillingStrokeFactor = 1 + FSF). +/// Overload max pressure. +/// Overload pressure decay rate. void TMHZ_K5P::SetParams(bool AO, bool MO, double OverP, double FSF, double OMP, double OPD) { AutoOvrld = AO; @@ -2887,9 +3637,9 @@ void TMHZ_K5P::SetParams(bool AO, bool MO, double OverP, double FSF, double OMP, OverloadMaxPressure = OMP; OverloadPressureDecrease = OPD; FillingStrokeFactor = 1 + FSF; - } +/// Returns true if pos is within ±0.5 of i_pos (detent test). bool TMHZ_K5P::EQ(double pos, double i_pos) { return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); @@ -2897,7 +3647,19 @@ bool TMHZ_K5P::EQ(double pos, double i_pos) //---MHZ_6P--- manipulator hamulca zespolonego 6-ciopozycyjny -double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { +/// +/// Computes brake-pipe flow for the 6-position MHZ_6P handle. Variant of K5P +/// with one additional detent — detent 4 triggers the emergency vent, detent 2 +/// is the cut-off (lap), positions > 2.5 brake, positions < 2 release. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. +double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) +{ static int const LBDelay = 100; double LimCP; @@ -2907,7 +3669,8 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) double DP; double pom; - for (int idx = 0; idx < 5; ++idx) { + for (int idx = 0; idx < 5; ++idx) + { Sounds[idx] = 0; } @@ -2915,7 +3678,7 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) i_bcp = Max0R(Min0R(i_bcp, 3.999), -0.999); // na wszelki wypadek, zeby nie wyszlo poza zakres - if ((TP > 0)&&(CP>4.9)) + if ((TP > 0) && (CP > 4.9)) { DP = OverloadPressureDecrease; TP = TP - DP * dt; @@ -2923,14 +3686,14 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) } else { - //TP = 0; //tu nie powinno być nic, ciśnienie zostaje jak było + // TP = 0; //tu nie powinno być nic, ciśnienie zostaje jak było } - if (EQ(i_bcp, 2)) //odcięcie - nie rób nic + if (EQ(i_bcp, 2)) // odcięcie - nie rób nic LimCP = CP; - else if (i_bcp > 2.5) //hamowanie + else if (i_bcp > 2.5) // hamowanie LimCP = 3.4; - else //luzowanie + else // luzowanie LimCP = 5.0; pom = CP; LimCP = Min0R(LimCP, HP); // pozycja + czasowy lub zasilanie @@ -2943,9 +3706,9 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) dpPipe = Min0R(HP, CP + TP + RedAdj); - double uop = UnbrakeOverPressure; //unbrake over pressure in actual state - ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); //button is pressed - if (ManualOvrld && !ManualOvrldActive) //no overpressure for not pressed button if it does not exists + double uop = UnbrakeOverPressure; // unbrake over pressure in actual state + ManualOvrldActive = (UniversalFlag & TUniversalBrake::ub_HighPressure); // button is pressed + if (ManualOvrld && !ManualOvrldActive) // no overpressure for not pressed button if it does not exists uop = 0; if (EQ(i_bcp, -1)) @@ -2966,10 +3729,10 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, dpPipe, 0.4); - if ((EQ(i_bcp, -1) && (AutoOvrld)) || ((i_bcp<0.5) && (UniversalFlag & TUniversalBrake::ub_Overload))) + if ((EQ(i_bcp, -1) && (AutoOvrld)) || ((i_bcp < 0.5) && (UniversalFlag & TUniversalBrake::ub_Overload))) { if ((TP < OverloadMaxPressure)) - TP = TP + 0.03 * dt; + TP = TP + 0.03 * dt; } if (EQ(i_bcp, 4)) @@ -2992,6 +3755,8 @@ double TMHZ_6P::GetPF(double i_bcp, double PP, double HP, double dt, double ep) return dpMainValve * dt; } +/// Initialises CP and enables the time / EP-time chambers. +/// Initial pressure [bar]. void TMHZ_6P::Init(double Press) { CP = Press; @@ -2999,11 +3764,15 @@ void TMHZ_6P::Init(double Press) TimeEP = true; } +/// Sets the reductor adjustment offset. +/// Pressure correction [bar]. void TMHZ_6P::SetReductor(double nAdj) { RedAdj = nAdj; } +/// Returns Sounds[i] for valid indices, 0 otherwise. +/// Sound channel index. double TMHZ_6P::GetSound(int i) { if (i > 4) @@ -3012,21 +3781,36 @@ double TMHZ_6P::GetSound(int i) return Sounds[i]; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TMHZ_6P::GetPos(int i) { return pos_table[i]; } +/// Returns CP. double TMHZ_6P::GetCP() { return CP; } +/// Returns the regulator target (5 + TP + RedAdj). double TMHZ_6P::GetRP() { return 5.0 + TP + RedAdj; -} +} +/// +/// Configures handle parameters: auto/manual overcharge, unbrake over-pressure +/// (also drives the Fala latch), filling-stroke factor (FSF + 1) and the +/// overcharge max pressure / decay rate. +/// +/// Auto-overcharge enabled. +/// Manual-overcharge enabled. +/// Unbrake over-pressure [bar]. +/// Filling-stroke factor offset. +/// Overload max pressure. +/// Overload pressure decay rate. void TMHZ_6P::SetParams(bool AO, bool MO, double OverP, double FSF, double OMP, double OPD) { AutoOvrld = AO; @@ -3036,9 +3820,9 @@ void TMHZ_6P::SetParams(bool AO, bool MO, double OverP, double FSF, double OMP, OverloadMaxPressure = OMP; OverloadPressureDecrease = OPD; FillingStrokeFactor = 1 + FSF; - } +/// Returns true if pos is within ±0.5 of i_pos (detent test). bool TMHZ_6P::EQ(double pos, double i_pos) { return (pos <= i_pos + 0.5) && (pos > i_pos - 0.5); @@ -3046,403 +3830,548 @@ bool TMHZ_6P::EQ(double pos, double i_pos) //---M394--- Matrosow +/// +/// Computes brake-pipe flow for the Matrosow 394 handle. Reads target pipe +/// pressure and flow speed from BPT_394[] for the current detent (with +/// special handling at the running and emergency positions) and integrates +/// the control reservoir CP at a position-dependent rate. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. double TM394::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - static int const LBDelay = 65; + static int const LBDelay = 65; - double LimPP; - double dpPipe; - double dpMainValve; - double ActFlowSpeed; - int BCP; + double LimPP; + double dpPipe; + double dpMainValve; + double ActFlowSpeed; + int BCP; - BCP = lround(i_bcp); - if (BCP < -1) - BCP = 1; + BCP = lround(i_bcp); + if (BCP < -1) + BCP = 1; - LimPP = Min0R(BPT_394[BCP + 1][1], HP); - ActFlowSpeed = BPT_394[BCP + 1][0]; - if ((BCP == 1) || (BCP == i_bcpno)) - LimPP = PP; - if ((BCP == 0)) - LimPP = LimPP + RedAdj; - if ((BCP != 2)) - if (CP < LimPP) - CP = CP + 4 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy - // cp:=cp+6*(2+int(bcp<0))*Min0R(abs(Limpp-cp),0.05)*PR(cp,Limpp)*dt //zbiornik - // sterujacy; - else if (BCP == 0) - CP = CP - 0.2 * dt / 100; - else - CP = CP + - 4 * (1 + int(BCP != 3) + int(BCP > 4)) * Min0R(abs(LimPP - CP), 0.05) * - PR(CP, LimPP) * dt; // zbiornik sterujacy + LimPP = Min0R(BPT_394[BCP + 1][1], HP); + ActFlowSpeed = BPT_394[BCP + 1][0]; + if ((BCP == 1) || (BCP == i_bcpno)) + LimPP = PP; + if ((BCP == 0)) + LimPP = LimPP + RedAdj; + if ((BCP != 2)) + if (CP < LimPP) + CP = CP + 4 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy + // cp:=cp+6*(2+int(bcp<0))*Min0R(abs(Limpp-cp),0.05)*PR(cp,Limpp)*dt //zbiornik + // sterujacy; + else if (BCP == 0) + CP = CP - 0.2 * dt / 100; + else + CP = CP + 4 * (1 + int(BCP != 3) + int(BCP > 4)) * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy - LimPP = CP; - dpPipe = Min0R(HP, LimPP); + LimPP = CP; + dpPipe = Min0R(HP, LimPP); - // if(dpPipe>pp)then //napelnianie - // dpMainValve:=PF(dpPipe,pp,ActFlowSpeed/LBDelay)*dt - // else //spuszczanie - dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; + // if(dpPipe>pp)then //napelnianie + // dpMainValve:=PF(dpPipe,pp,ActFlowSpeed/LBDelay)*dt + // else //spuszczanie + dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; - if (BCP == -1) - dpMainValve = PF(HP, PP, ActFlowSpeed / LBDelay) * dt; + if (BCP == -1) + dpMainValve = PF(HP, PP, ActFlowSpeed / LBDelay) * dt; - if (BCP == i_bcpno) - dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; + if (BCP == i_bcpno) + dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; - return dpMainValve; + return dpMainValve; } +/// Initialises CP and enables the time chamber. +/// Initial pressure [bar]. void TM394::Init(double Press) { - CP = Press; - Time = true; + CP = Press; + Time = true; } +/// Sets the reductor adjustment offset. +/// Pressure correction [bar]. void TM394::SetReductor(double nAdj) { - RedAdj = nAdj; + RedAdj = nAdj; } +/// Returns CP. double TM394::GetCP() { - return CP; + return CP; } +/// Returns max(5, CP) + RedAdj as the regulator target. double TM394::GetRP() { return std::max(5.0, CP) + RedAdj; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TM394::GetPos(int i) { - return pos_table[i]; + return pos_table[i]; } //---H14K1-- Knorr +/// +/// Computes brake-pipe flow for the Knorr H14K1 auxiliary handle. +/// Picks a target pressure level (high/low/lap) from BPT_K[] depending on the +/// detent, integrates CP toward it and dispatches the resulting flow path +/// (charge / fill toward nominal / vent toward CP / emergency vent at +/// the maximum detent). +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. double TH14K1::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - int const LBDelay = 100; // szybkosc + zasilanie sterujacego - // static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2] = - //{ (10, 0), (4, 1), (0, 1), (4, 0), (4, -1), (15, -1) }; - double const NomPress = 5.0; + int const LBDelay = 100; // szybkosc + zasilanie sterujacego + // static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2] = + //{ (10, 0), (4, 1), (0, 1), (4, 0), (4, -1), (15, -1) }; + double const NomPress = 5.0; - int BCP = std::lround(i_bcp); - if( i_bcp < -1 ) { BCP = 1; } + int BCP = std::lround(i_bcp); + if (i_bcp < -1) + { + BCP = 1; + } - double LimPP = BPT_K[BCP + 1][1]; - if( LimPP < 0.0 ) { LimPP = 0.5 * PP; } - else if( LimPP > 0.0 ) { LimPP = PP; } - else { LimPP = CP; } - double ActFlowSpeed = BPT_K[BCP + 1][0]; + double LimPP = BPT_K[BCP + 1][1]; + if (LimPP < 0.0) + { + LimPP = 0.5 * PP; + } + else if (LimPP > 0.0) + { + LimPP = PP; + } + else + { + LimPP = CP; + } + double ActFlowSpeed = BPT_K[BCP + 1][0]; - CP = CP + 6 * std::min( std::abs(LimPP - CP), 0.05 ) * PR(CP, LimPP) * dt; // zbiornik sterujacy + CP = CP + 6 * std::min(std::abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy - double dpMainValve = 0.0; + double dpMainValve = 0.0; - if (BCP == -1) - dpMainValve = PF(HP, PP, ActFlowSpeed / LBDelay) * dt; - if ((BCP == 0)) - dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, NomPress + RedAdj) * dt; - if ((BCP > 1) && (PP > CP)) - dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, CP) * dt; - if (BCP == i_bcpno) - dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; + if (BCP == -1) + dpMainValve = PF(HP, PP, ActFlowSpeed / LBDelay) * dt; + if ((BCP == 0)) + dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, NomPress + RedAdj) * dt; + if ((BCP > 1) && (PP > CP)) + dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, CP) * dt; + if (BCP == i_bcpno) + dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; - return dpMainValve; + return dpMainValve; } +/// Initialises CP and enables the time / EP-time chambers. +/// Initial pressure [bar]. void TH14K1::Init(double Press) { - CP = Press; - Time = true; - TimeEP = true; + CP = Press; + Time = true; + TimeEP = true; } +/// Sets the reductor adjustment offset. +/// Pressure correction [bar]. void TH14K1::SetReductor(double nAdj) { - RedAdj = nAdj; + RedAdj = nAdj; } +/// Returns CP. double TH14K1::GetCP() { - return CP; + return CP; } +/// Returns the regulator target (5 + RedAdj). double TH14K1::GetRP() { - return 5.0 + RedAdj; + return 5.0 + RedAdj; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TH14K1::GetPos(int i) { - return pos_table[i]; + return pos_table[i]; } //---St113-- Knorr EP +/// +/// Computes brake-pipe flow for the Knorr St113 EP-equipped handle. +/// Reuses the H14K1 flow paths (after collapsing position 1 into the cut-off +/// region) and additionally publishes the EP intensity from BEP_K[]. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. double TSt113::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - static int const LBDelay = 100; // szybkosc + zasilanie sterujacego - static double const NomPress = 5.0; + static int const LBDelay = 100; // szybkosc + zasilanie sterujacego + static double const NomPress = 5.0; - double LimPP; - double dpMainValve; - double ActFlowSpeed; - int BCP; + double LimPP; + double dpMainValve; + double ActFlowSpeed; + int BCP; CP = PP; - BCP = lround(i_bcp); + BCP = lround(i_bcp); - EPS = BEP_K[BCP + 1]; + EPS = BEP_K[BCP + 1]; - if (BCP > 0) - BCP = BCP - 1; + if (BCP > 0) + BCP = BCP - 1; - if (BCP < -1) - BCP = 1; - LimPP = BPT_K[BCP + 1][1]; - if (LimPP < 0) - LimPP = 0.5 * PP; - else if (LimPP > 0) - LimPP = PP; - else - LimPP = CP; - ActFlowSpeed = BPT_K[BCP + 1][0]; + if (BCP < -1) + BCP = 1; + LimPP = BPT_K[BCP + 1][1]; + if (LimPP < 0) + LimPP = 0.5 * PP; + else if (LimPP > 0) + LimPP = PP; + else + LimPP = CP; + ActFlowSpeed = BPT_K[BCP + 1][0]; - CP = CP + 6 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy + CP = CP + 6 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt; // zbiornik sterujacy - dpMainValve = 0; + dpMainValve = 0; - if (BCP == -1) - dpMainValve = PF(HP, PP, ActFlowSpeed / LBDelay) * dt; - if ((BCP == 0)) - dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, NomPress + RedAdj) * dt; - if ((BCP > 1) && (PP > CP)) - dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, CP) * dt; - if (BCP == i_bcpno) - dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; + if (BCP == -1) + dpMainValve = PF(HP, PP, ActFlowSpeed / LBDelay) * dt; + if ((BCP == 0)) + dpMainValve = -PFVa(HP, PP, ActFlowSpeed / LBDelay, NomPress + RedAdj) * dt; + if ((BCP > 1) && (PP > CP)) + dpMainValve = PFVd(PP, 0, ActFlowSpeed / LBDelay, CP) * dt; + if (BCP == i_bcpno) + dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; - return dpMainValve; + return dpMainValve; } +/// Returns CP. double TSt113::GetCP() { - return CP; + return CP; } +/// Returns the regulator target (5 + RedAdj). double TSt113::GetRP() { return 5.0 + RedAdj; } +/// Returns the current EP intensity (read from BEP_K via the last GetPF call). double TSt113::GetEP() { return EPS; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TSt113::GetPos(int i) { - return pos_table[i]; + return pos_table[i]; } +/// Enables the time / EP-time chambers (no pressure init needed). +/// Initial pressure (unused). void TSt113::Init(double Press) { - Time = true; - TimeEP = true; + Time = true; + TimeEP = true; } //--- test --- +/// +/// Computes brake-pipe flow for the test-only handle. Uses BPT[] but +/// overrides the limit pressure for the highest detent (full vent) and +/// for position -1 (raises target to 7 bar). +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input [bar]. +/// Brake pipe volume change for this step. double Ttest::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - static int const LBDelay = 100; + static int const LBDelay = 100; - double LimPP; - double dpPipe; - double dpMainValve; - double ActFlowSpeed; + double LimPP; + double dpPipe; + double dpMainValve; + double ActFlowSpeed; - LimPP = BPT[lround(i_bcp) + 2][1]; - ActFlowSpeed = BPT[lround(i_bcp) + 2][0]; + LimPP = BPT[lround(i_bcp) + 2][1]; + ActFlowSpeed = BPT[lround(i_bcp) + 2][0]; - if ((i_bcp == i_bcpno)) - LimPP = 0.0; + if ((i_bcp == i_bcpno)) + LimPP = 0.0; - if ((i_bcp == -1)) - LimPP = 7; + if ((i_bcp == -1)) + LimPP = 7; - CP = CP + 20 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt / 1; + CP = CP + 20 * Min0R(abs(LimPP - CP), 0.05) * PR(CP, LimPP) * dt / 1; - LimPP = CP; - dpPipe = Min0R(HP, LimPP); + LimPP = CP; + dpPipe = Min0R(HP, LimPP); - dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; + dpMainValve = PF(dpPipe, PP, ActFlowSpeed / LBDelay) * dt; - if ((lround(i_bcp) == i_bcpno)) - { - dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; - } + if ((lround(i_bcp) == i_bcpno)) + { + dpMainValve = PF(0, PP, ActFlowSpeed / LBDelay) * dt; + } - return dpMainValve; + return dpMainValve; } +/// Initialises CP to the supplied pressure. +/// Initial pressure [bar]. void Ttest::Init(double Press) { - CP = Press; + CP = Press; } //---FD1--- +/// +/// Computes the auxiliary-brake outflow for the FD1 handle: drives the +/// cylinder pressure BP toward i_bcp * MaxBP at a configurable Speed, +/// using a soft-clamped PF flow with asymmetric fill/release rates. +/// +/// Continuous handle position (0..1). +/// Brake pipe pressure (unused). +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input (unused). +/// Negated cylinder pressure delta for this step. double TFD1::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - double DP; - double temp; + double DP; + double temp; - // MaxBP:=4; - // temp:=Min0R(i_bcp*MaxBP,Min0R(5.0,HP)); - temp = std::min(i_bcp * MaxBP, HP); // 0011 - DP = 10.0 * std::min(std::abs(temp - BP), 0.1) * PF(temp, BP, 0.0006 * (temp > BP ? 3.0 : 2.0) ) * dt * Speed; - BP = BP - DP; - return -DP; + // MaxBP:=4; + // temp:=Min0R(i_bcp*MaxBP,Min0R(5.0,HP)); + temp = std::min(i_bcp * MaxBP, HP); // 0011 + DP = 10.0 * std::min(std::abs(temp - BP), 0.1) * PF(temp, BP, 0.0006 * (temp > BP ? 3.0 : 2.0)) * dt * Speed; + BP = BP - DP; + return -DP; } +/// Initialises MaxBP and the action speed (defaults to 1.0). +/// Maximum cylinder pressure [bar]. void TFD1::Init(double Press) { - MaxBP = Press; - Speed = 1.0; + MaxBP = Press; + Speed = 1.0; } +/// Returns the currently commanded cylinder pressure (BP). double TFD1::GetCP() { - return BP; + return BP; } +/// Sets the action speed multiplier (scales the response time). +/// Speed multiplier. void TFD1::SetSpeed(double nSpeed) { - Speed = nSpeed; + Speed = nSpeed; } //---KNORR--- +/// +/// Computes the auxiliary-brake outflow for the Knorr H1405 handle. +/// Above 0.5 the handle drives the cylinder up toward MaxBP (apply); below +/// it the cylinder is vented toward zero. The orifice area depends linearly +/// on the deflection from the lap point. +/// +/// Continuous handle position. +/// Brake pipe pressure clamped to MaxBP. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input (unused). +/// Negated cylinder pressure delta for this step. double TH1405::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - double DP; - double temp; - double A; + double DP; + double temp; + double A; - PP = Min0R(PP, MaxBP); - if (i_bcp > 0.5) - { - temp = Min0R(MaxBP, HP); - A = 2 * (i_bcp - 0.5) * 0.0011; - BP = Max0R(BP, PP); - } - else - { - temp = 0; - A = 0.2 * (0.5 - i_bcp) * 0.0033; - BP = Min0R(BP, PP); - } - DP = PF(temp, BP, A) * dt; - BP = BP - DP; - return -DP; + PP = Min0R(PP, MaxBP); + if (i_bcp > 0.5) + { + temp = Min0R(MaxBP, HP); + A = 2 * (i_bcp - 0.5) * 0.0011; + BP = Max0R(BP, PP); + } + else + { + temp = 0; + A = 0.2 * (0.5 - i_bcp) * 0.0033; + BP = Min0R(BP, PP); + } + DP = PF(temp, BP, A) * dt; + BP = BP - DP; + return -DP; } +/// Initialises MaxBP and enables the time chamber. +/// Maximum cylinder pressure [bar]. void TH1405::Init(double Press) { - MaxBP = Press; - Time = true; + MaxBP = Press; + Time = true; } +/// Returns the currently commanded cylinder pressure (BP). double TH1405::GetCP() { - return BP; + return BP; } //---FVel6--- +/// +/// Computes brake-pipe flow for the FVel6 combined handle. Position-dependent +/// flow speed selects between full release, lap, brake (positions 4.3..4.8) +/// and emergency (above 5.5). Also publishes EP intensity (-1, 0 or 1) and +/// the corresponding sound channels. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input (unused). +/// Brake pipe volume change for this step. double TFVel6::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { - static int const LBDelay = 100; + static int const LBDelay = 100; - double LimPP; - double dpMainValve; - double ActFlowSpeed; + double LimPP; + double dpMainValve; + double ActFlowSpeed; CP = PP; - LimPP = Min0R(5 * int(i_bcp < 3.5), HP); - if ((i_bcp >= 3.5) && ((i_bcp < 4.3) || (i_bcp > 5.5))) - ActFlowSpeed = 0; - else if ((i_bcp > 4.3) && (i_bcp < 4.8)) - ActFlowSpeed = 4 * (i_bcp - 4.3); // konsultacje wawa1 - bylo 8; - else if ((i_bcp < 4)) - ActFlowSpeed = 2; - else - ActFlowSpeed = 4; - dpMainValve = PF(LimPP, PP, ActFlowSpeed / LBDelay) * dt; + LimPP = Min0R(5 * int(i_bcp < 3.5), HP); + if ((i_bcp >= 3.5) && ((i_bcp < 4.3) || (i_bcp > 5.5))) + ActFlowSpeed = 0; + else if ((i_bcp > 4.3) && (i_bcp < 4.8)) + ActFlowSpeed = 4 * (i_bcp - 4.3); // konsultacje wawa1 - bylo 8; + else if ((i_bcp < 4)) + ActFlowSpeed = 2; + else + ActFlowSpeed = 4; + dpMainValve = PF(LimPP, PP, ActFlowSpeed / LBDelay) * dt; - Sounds[s_fv4a_e] = 0; - Sounds[s_fv4a_u] = 0; - Sounds[s_fv4a_b] = 0; - if ((i_bcp < 3.5)) - Sounds[s_fv4a_u] = -dpMainValve; - else if ((i_bcp < 4.8)) - Sounds[s_fv4a_b] = dpMainValve; - else if ((i_bcp < 5.5)) - Sounds[s_fv4a_e] = dpMainValve; + Sounds[s_fv4a_e] = 0; + Sounds[s_fv4a_u] = 0; + Sounds[s_fv4a_b] = 0; + if ((i_bcp < 3.5)) + Sounds[s_fv4a_u] = -dpMainValve; + else if ((i_bcp < 4.8)) + Sounds[s_fv4a_b] = dpMainValve; + else if ((i_bcp < 5.5)) + Sounds[s_fv4a_e] = dpMainValve; - if ((i_bcp < -0.5)) - EPS = -1; - else if ((i_bcp > 0.5) && (i_bcp < 4.7)) - EPS = 1; - else - EPS = 0; - // EPS:=i_bcp*int(i_bcp<2) - return dpMainValve; + if ((i_bcp < -0.5)) + EPS = -1; + else if ((i_bcp > 0.5) && (i_bcp < 4.7)) + EPS = 1; + else + EPS = 0; + // EPS:=i_bcp*int(i_bcp<2) + return dpMainValve; } +/// Returns CP. double TFVel6::GetCP() { - return CP; + return CP; } +/// Returns the constant 5 bar regulator target. double TFVel6::GetRP() { return 5.0; } +/// Returns the current EP intensity. double TFVel6::GetEP() { return EPS; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TFVel6::GetPos(int i) { - return pos_table[i]; + return pos_table[i]; } +/// Returns Sounds[i] for valid indices, 0 otherwise. +/// Sound channel index (0..2). double TFVel6::GetSound(int i) { - if (i > 2) - return 0; - else - return Sounds[i]; + if (i > 2) + return 0; + else + return Sounds[i]; } +/// Enables the time and EP-time chambers (no pressure init). +/// Initial pressure (unused). void TFVel6::Init(double Press) { - Time = true; - TimeEP = true; + Time = true; + TimeEP = true; } //---FVE408--- +/// +/// Computes brake-pipe flow for the FVE408 combined handle. Splits the flow +/// behaviour into release (positions < 6.5), brake (7.5..8.5), emergency +/// (8.5..9.5) and locked positions; sets EPS to fixed steps at detents 1..5. +/// +/// Continuous handle position. +/// Brake pipe pressure [bar]. +/// High-pressure source [bar]. +/// Time step [s]. +/// EP / equalising input (unused). +/// Brake pipe volume change for this step. double TFVE408::GetPF(double i_bcp, double PP, double HP, double dt, double ep) { static int const LBDelay = 100; @@ -3474,36 +4403,49 @@ double TFVE408::GetPF(double i_bcp, double PP, double HP, double dt, double ep) else if ((i_bcp < 9.5)) Sounds[s_fv4a_e] = dpMainValve; - if (is_EQ(i_bcp, 1)) EPS = 1.15; else - if (is_EQ(i_bcp, 2)) EPS = 1.40; else - if (is_EQ(i_bcp, 3)) EPS = 2.64; else - if (is_EQ(i_bcp, 4)) EPS = 3.84; else - if (is_EQ(i_bcp, 5)) EPS = 3.99; else - EPS = 0; + if (is_EQ(i_bcp, 1)) + EPS = 1.15; + else if (is_EQ(i_bcp, 2)) + EPS = 1.40; + else if (is_EQ(i_bcp, 3)) + EPS = 2.64; + else if (is_EQ(i_bcp, 4)) + EPS = 3.84; + else if (is_EQ(i_bcp, 5)) + EPS = 3.99; + else + EPS = 0; return dpMainValve; } +/// Returns CP. double TFVE408::GetCP() { return CP; } +/// Returns the current EP intensity. double TFVE408::GetEP() { return EPS; } +/// Returns the constant 5 bar regulator target. double TFVE408::GetRP() { return 5.0; } +/// Returns pos_table[i]. +/// Function code (bh_*). double TFVE408::GetPos(int i) { return pos_table[i]; } +/// Returns Sounds[i] for valid indices, 0 otherwise. +/// Sound channel index (0..2). double TFVE408::GetSound(int i) { if (i > 2) @@ -3512,6 +4454,8 @@ double TFVE408::GetSound(int i) return Sounds[i]; } +/// Enables the time chamber, disables the EP-time chamber. +/// Initial pressure (unused). void TFVE408::Init(double Press) { Time = true; @@ -3519,5 +4463,3 @@ void TFVE408::Init(double Press) } // END - - diff --git a/McZapkie/hamulce.h b/McZapkie/hamulce.h index 4dd2b9dd..4e3e888e 100644 --- a/McZapkie/hamulce.h +++ b/McZapkie/hamulce.h @@ -14,7 +14,6 @@ http://mozilla.org/MPL/2.0/. Copyright (C) 2007-2014 Maciej Cierniak */ - /* (C) youBy Co brakuje: @@ -36,664 +35,1301 @@ Knorr/West EP - żeby był #include "friction.h" // Pascal unit -static int const LocalBrakePosNo = 10; /*ilosc nastaw hamulca recznego lub pomocniczego*/ -static int const MainBrakeMaxPos = 10; /*max. ilosc nastaw hamulca zasadniczego*/ +/// Number of positions of the local (auxiliary/manual) brake handle. +static int const LocalBrakePosNo = 10; /*ilosc nastaw hamulca recznego lub pomocniczego*/ +/// Maximum number of positions of the main (train) brake handle. +static int const MainBrakeMaxPos = 10; /*max. ilosc nastaw hamulca zasadniczego*/ /*nastawy hamulca*/ -static int const bdelay_G = 1; //G -static int const bdelay_P = 2; //P -static int const bdelay_R = 4; //R -static int const bdelay_M = 8; //Mg - +/// Brake delay setting flag: G (goods/freight slow). +static int const bdelay_G = 1; // G +/// Brake delay setting flag: P (passenger fast). +static int const bdelay_P = 2; // P +/// Brake delay setting flag: R (rapid - high braking force). +static int const bdelay_R = 4; // R +/// Brake delay setting flag: Mg (magnetic rail brake enabled). +static int const bdelay_M = 8; // Mg /*stan hamulca*/ -static int const b_off = 0; //luzowanie -static int const b_hld = 1; //trzymanie -static int const b_on = 2; //napelnianie -static int const b_rfl = 4; //uzupelnianie -static int const b_rls = 8; //odluzniacz -static int const b_ep = 16; //elektropneumatyczny -static int const b_asb = 32; //przeciwposlizg-wstrzymanie -static int const b_asb_unbrake = 64; //przeciwposlizg-luzowanie -static int const b_dmg = 128; //wylaczony z dzialania +/// Brake state flag: brake released (no action). +static int const b_off = 0; // luzowanie +/// Brake state flag: hold (lap) - keep current cylinder pressure. +static int const b_hld = 1; // trzymanie +/// Brake state flag: applying - filling brake cylinder. +static int const b_on = 2; // napelnianie +/// Brake state flag: replenishing the auxiliary reservoir. +static int const b_rfl = 4; // uzupelnianie +/// Brake state flag: releaser engaged (vents the control reservoir to release brakes). +static int const b_rls = 8; // odluzniacz +/// Brake state flag: electro-pneumatic action active. +static int const b_ep = 16; // elektropneumatyczny +/// Brake state flag: anti-slip protection holding the brake (preventing further filling). +static int const b_asb = 32; // przeciwposlizg-wstrzymanie +/// Brake state flag: anti-slip protection releasing the brake. +static int const b_asb_unbrake = 64; // przeciwposlizg-luzowanie +/// Brake state flag: brake disabled / damaged. +static int const b_dmg = 128; // wylaczony z dzialania /*uszkodzenia hamulca*/ -static int const df_on = 1; //napelnianie -static int const df_off = 2; //luzowanie -static int const df_br = 4; //wyplyw z ZP -static int const df_vv = 8; //wyplyw z komory wstepnej -static int const df_bc = 16; //wyplyw z silownika -static int const df_cv = 32; //wyplyw z ZS -static int const df_PP = 64; //zawsze niski stopien -static int const df_RR = 128; //zawsze wysoki stopien +/// Brake damage flag: faulty filling phase. +static int const df_on = 1; // napelnianie +/// Brake damage flag: faulty release phase. +static int const df_off = 2; // luzowanie +/// Brake damage flag: leak in auxiliary reservoir (ZP). +static int const df_br = 4; // wyplyw z ZP +/// Brake damage flag: leak in valve pre-chamber. +static int const df_vv = 8; // wyplyw z komory wstepnej +/// Brake damage flag: leak in brake cylinder. +static int const df_bc = 16; // wyplyw z silownika +/// Brake damage flag: leak in control reservoir (ZS). +static int const df_cv = 32; // wyplyw z ZS +/// Brake damage flag: stuck at low load step. +static int const df_PP = 64; // zawsze niski stopien +/// Brake damage flag: stuck at high load step. +static int const df_RR = 128; // zawsze wysoki stopien /*indeksy dzwiekow FV4a*/ -static int const s_fv4a_b = 0; //hamowanie -static int const s_fv4a_u = 1; //luzowanie -static int const s_fv4a_e = 2; //hamowanie nagle -static int const s_fv4a_x = 3; //wyplyw sterujacego fala -static int const s_fv4a_t = 4; //wyplyw z czasowego +/// FV4a sound index: braking flow. +static int const s_fv4a_b = 0; // hamowanie +/// FV4a sound index: release flow. +static int const s_fv4a_u = 1; // luzowanie +/// FV4a sound index: emergency braking flow. +static int const s_fv4a_e = 2; // hamowanie nagle +/// FV4a sound index: control wave outflow. +static int const s_fv4a_x = 3; // wyplyw sterujacego fala +/// FV4a sound index: timing chamber outflow. +static int const s_fv4a_t = 4; // wyplyw z czasowego /*pary cierne*/ +/// Friction pair: P10 (default cast iron). static int const bp_P10 = 0; -static int const bp_P10Bg = 2; //żeliwo fosforowe P10 +/// Friction pair: P10 phosphoric cast iron with Bg block. +static int const bp_P10Bg = 2; // żeliwo fosforowe P10 +/// Friction pair: P10 phosphoric cast iron with Bgu block. static int const bp_P10Bgu = 1; -static int const bp_LLBg = 4; //komp. b.n.t. +/// Friction pair: low-friction composite (b.n.t.) with Bg block. +static int const bp_LLBg = 4; // komp. b.n.t. +/// Friction pair: low-friction composite (b.n.t.) with Bgu block. static int const bp_LLBgu = 3; -static int const bp_LBg = 6; //komp. n.t. +/// Friction pair: low-friction composite (n.t.) with Bg block. +static int const bp_LBg = 6; // komp. n.t. +/// Friction pair: low-friction composite (n.t.) with Bgu block. static int const bp_LBgu = 5; -static int const bp_KBg = 8; //komp. w.t. +/// Friction pair: high-friction composite (w.t.) with Bg block. +static int const bp_KBg = 8; // komp. w.t. +/// Friction pair: high-friction composite (w.t.) with Bgu block. static int const bp_KBgu = 7; -static int const bp_D1 = 9; //tarcze +/// Friction pair: disc brake type 1. +static int const bp_D1 = 9; // tarcze +/// Friction pair: disc brake type 2. static int const bp_D2 = 10; +/// Friction pair: Frenoplast FR513 composite. static int const bp_FR513 = 11; // Frenoplast FR513 +/// Friction pair: Cosid composite. static int const bp_Cosid = 12; // jakistam kompozyt :D -static int const bp_PKPBg = 13; //żeliwo PKP +/// Friction pair: PKP cast iron with Bg block. +static int const bp_PKPBg = 13; // żeliwo PKP +/// Friction pair: PKP cast iron with Bgu block. static int const bp_PKPBgu = 14; +/// Friction pair flag: magnetic rail brake (added bitwise to other types). static int const bp_MHS = 128; // magnetyczny hamulec szynowy -static int const bp_P10yBg = 15; //żeliwo fosforowe P10 +/// Friction pair: P10y phosphoric cast iron with Bg block. +static int const bp_P10yBg = 15; // żeliwo fosforowe P10 +/// Friction pair: P10y phosphoric cast iron with Bgu block. static int const bp_P10yBgu = 16; -static int const bp_FR510 = 17; //Frenoplast FR510 +/// Friction pair: Frenoplast FR510 composite. +static int const bp_FR510 = 17; // Frenoplast FR510 -static int const sf_Acc = 1; //przyspieszacz -static int const sf_BR = 2; //przekladnia -static int const sf_CylB = 4; //cylinder - napelnianie -static int const sf_CylU = 8; //cylinder - oproznianie -static int const sf_rel = 16; //odluzniacz -static int const sf_ep = 32; //zawory ep +/// Sound flag: accelerator (rapid pressure drop in valve pre-chamber). +static int const sf_Acc = 1; // przyspieszacz +/// Sound flag: brake transmission/load relay actuating. +static int const sf_BR = 2; // przekladnia +/// Sound flag: brake cylinder filling. +static int const sf_CylB = 4; // cylinder - napelnianie +/// Sound flag: brake cylinder venting. +static int const sf_CylU = 8; // cylinder - oproznianie +/// Sound flag: releaser actuated. +static int const sf_rel = 16; // odluzniacz +/// Sound flag: electro-pneumatic valves switching. +static int const sf_ep = 32; // zawory ep +/// Brake handle position index: minimum position. static int const bh_MIN = 0; // minimalna pozycja +/// Brake handle position index: maximum position. static int const bh_MAX = 1; // maksymalna pozycja +/// Brake handle position index: filling stroke (high-pressure overcharge); if not present, equivalent to running. static int const bh_FS = 2; // napelnianie uderzeniowe //jesli nie ma, to jazda +/// Brake handle position index: running (driving) position. static int const bh_RP = 3; // jazda +/// Brake handle position index: cut-off (double traction / neutral). static int const bh_NP = 4; // odciecie - podwojna trakcja +/// Brake handle position index: minimum braking step (lap or first step). static int const bh_MB = 5; // odciecie - utrzymanie stopnia hamowania/pierwszy 1 stopien hamowania +/// Brake handle position index: full service brake. static int const bh_FB = 6; // pelne +/// Brake handle position index: emergency brake. static int const bh_EB = 7; // nagle +/// Brake handle position index: EP release (full release for angular EP). static int const bh_EPR = 8; // ep - luzowanie //pelny luz dla ep kątowego +/// Brake handle position index: EP hold/lap; if equal to release, button-only EP control. static int const bh_EPN = 9; // ep - utrzymanie //jesli rowne luzowaniu, wtedy sterowanie przyciskiem +/// Brake handle position index: EP brake (full braking for angular EP). static int const bh_EPB = 10; // ep - hamowanie //pelne hamowanie dla ep kątowego - +/// Diameter of the brake pipe (1") used in flow calculations. static double const SpgD = 0.7917; -static double const SpO = 0.5067; //przekroj przewodu 1" w l/m - //wyj: jednostka dosyc dziwna, ale wszystkie obliczenia - //i pojemnosci sa podane w litrach (rozsadne wielkosci) - //zas dlugosc pojazdow jest podana w metrach - //a predkosc przeplywu w m/s //3.5 - //7//1.5 +/// Cross-section of a 1" brake pipe expressed in l/m (used to keep volumes in liters and lengths in meters). +static double const SpO = 0.5067; // przekroj przewodu 1" w l/m + // wyj: jednostka dosyc dziwna, ale wszystkie obliczenia + // i pojemnosci sa podane w litrach (rozsadne wielkosci) + // zas dlugosc pojazdow jest podana w metrach + // a predkosc przeplywu w m/s //3.5 + // 7//1.5 // BPT: array[-2..6] of array [0..1] of real= ((0, 5.0), (14, 5.4), (9, 5.0), (6, 4.6), (9, 4.5), (9, 4.0), (9, 3.5), (9, 2.8), (34, 2.8)); // BPT: array[-2..6] of array [0..1] of real= ((0, 5.0), (7, 5.0), (2.0, 5.0), (4.5, 4.6), (4.5, 4.2), (4.5, 3.8), (4.5, 3.4), (4.5, 2.8), (8, 2.8)); -static double const BPT[9][2] = { {0 , 5.0} , {7 , 5.0} , {2.0 , 5.0} , {4.5 , 4.6} , {4.5 , 4.2} , {4.5 , 3.8} , {4.5 , 3.4} , {4.5 , 2.8} , {8 , 2.8} }; -static double const BPT_394[7][2] = { {13 , 10.0} , {5 , 5.0} , {0 , -1} , {5 , -1} , {5 , 0.0} , {5 , 0.0} , {18 , 0.0} }; -//double *BPT = zero_based_BPT[2]; //tablica pozycji hamulca dla zakresu -2..6 -//double *BPT_394 = zero_based_BPT_394[1]; //tablica pozycji hamulca dla zakresu -1..5 -// BPT: array[-2..6] of array [0..1] of real= ((0, 5.0), (12, 5.4), (9, 5.0), (9, 4.6), (9, 4.2), (9, 3.8), (9, 3.4), (9, 2.8), (34, 2.8)); -// BPT: array[-2..6] of array [0..1] of real= ((0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0)); -// static double const pi = 3.141592653589793; //definicja w mctools +/// +/// Brake handle position table for FV4a-family valves (range -2..6). +/// Each row holds {flow speed, target brake pipe pressure [bar]} for the matching position index (offset by +2). +/// +static double const BPT[9][2] = {{0, 5.0}, {7, 5.0}, {2.0, 5.0}, {4.5, 4.6}, {4.5, 4.2}, {4.5, 3.8}, {4.5, 3.4}, {4.5, 2.8}, {8, 2.8}}; +/// +/// Brake handle position table for the Matrosow 394 valve (range -1..5). +/// Each row holds {flow speed, target brake pipe pressure [bar]} for the matching position index (offset by +1). +/// +static double const BPT_394[7][2] = {{13, 10.0}, {5, 5.0}, {0, -1}, {5, -1}, {5, 0.0}, {5, 0.0}, {18, 0.0}}; +// double *BPT = zero_based_BPT[2]; //tablica pozycji hamulca dla zakresu -2..6 +// double *BPT_394 = zero_based_BPT_394[1]; //tablica pozycji hamulca dla zakresu -1..5 +// BPT: array[-2..6] of array [0..1] of real= ((0, 5.0), (12, 5.4), (9, 5.0), (9, 4.6), (9, 4.2), (9, 3.8), (9, 3.4), (9, 2.8), (34, 2.8)); +// BPT: array[-2..6] of array [0..1] of real= ((0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0),(0, 0)); +// static double const pi = 3.141592653589793; //definicja w mctools +/// +/// Bit flags for the universal brake button — actions that can be triggered +/// from a single hardware button on the driver's stand. Combined bitwise. +/// enum TUniversalBrake // możliwe działania uniwersalnego przycisku hamulca { // kolejne flagi + /// Releaser (ZR) — vents control reservoir to release brakes on this vehicle. ub_Release = 0x01, // odluźniacz - ZR + /// Brake pipe unlock / safety brake bridging (vehicle-level). ub_UnlockPipe = 0x02, // odblok PG / mostkowanie hamulca bezpieczeństwa - POJAZD + /// High-pressure pulse (ZM) — overcharge stroke. ub_HighPressure = 0x04, // impuls wysokiego ciśnienia - ZM + /// Assimilation / controlled overcharge button (ZM). ub_Overload = 0x08, // przycisk asymilacji / kontrolowanego przeładowania - ZM + /// Anti-slip light braking button (ZR). ub_AntiSlipBrake = 0x10, // przycisk przyhamowania przeciwposlizgowego - ZR + /// Reserved sentinel — last bit flag (highest bit). ub_Ostatni = 0x80000000 // ostatnia flaga bitowa }; -//klasa obejmujaca pojedyncze zbiorniki -class TReservoir { +/// +/// Single pneumatic reservoir. Tracks capacity (Cap), current volume (Vol) +/// and the pending flow (dVol) accumulated during a simulation step. +/// +class TReservoir +{ -protected: - double Cap{ 1.0 }; - double Vol{ 0.0 }; - double dVol{ 0.0 }; + protected: + /// Reservoir capacity in liters. + double Cap{1.0}; + /// Current air volume contained, scaled by capacity (Vol/Cap == pressure). + double Vol{0.0}; + /// Accumulated flow (in/out) for the current step; applied by . + double dVol{0.0}; public: - void CreateCap(double Capacity); - void CreatePress(double Press); - virtual double pa(); - virtual double P(); - void Flow(double dv); - void Act(); + /// + /// Sets reservoir capacity. + /// + /// Capacity in liters. + void CreateCap(double Capacity); + /// + /// Initialises the reservoir to a given absolute pressure (clears pending flow). + /// + /// Pressure in bar (atm). + void CreatePress(double Press); + /// + /// Returns absolute (atmospheric) pressure inside the reservoir. + /// + /// Pressure value (0.1 * Vol / Cap). + virtual double pa(); + /// + /// Returns gauge pressure inside the reservoir. + /// + /// Pressure value (Vol / Cap), in bar. + virtual double P(); + /// + /// Accumulates a flow into the reservoir for the current step (positive = in, negative = out). + /// + /// Volume change to add to dVol. + void Flow(double dv); + /// + /// Applies the accumulated flow (dVol) to the volume and resets dVol. + /// Volume is clamped to be non-negative. + /// + void Act(); - TReservoir() = default; + /// Default constructor — creates a 1 L reservoir at zero pressure. + TReservoir() = default; }; +/// Pointer typedef for a reservoir instance. typedef TReservoir *PReservoir; - -class TBrakeCyl : public TReservoir { +/// +/// Brake cylinder reservoir — overrides pressure functions to model the +/// non-linear behaviour of a piston cylinder (initial dead volume, working stroke, +/// fully extended piston). +/// +class TBrakeCyl : public TReservoir +{ public: - virtual double pa()/*override*/; - virtual double P()/*override*/; - TBrakeCyl() : TReservoir() {}; + /// + /// Returns absolute pressure inside the brake cylinder (P() * 0.1). + /// + /// Absolute cylinder pressure. + virtual double pa() /*override*/; + /// + /// Returns gauge pressure inside the brake cylinder, modelling the + /// piston-stroke pressure curve (dead volume, linear stroke, fully extended). + /// + /// Cylinder pressure in bar. + virtual double P() /*override*/; + /// Default constructor. + TBrakeCyl() : TReservoir() {}; }; -//klasa obejmujaca uklad hamulca zespolonego pojazdu -class TBrake { +/// +/// Base class for the complete pneumatic brake system of a single vehicle. +/// Holds the brake cylinder, auxiliary reservoir, valve pre-chamber and the +/// generic logic shared by every distributor type. Concrete distributor +/// behaviour is implemented in derived classes (TWest, TESt, TLSt, TKE, ...). +/// +class TBrake +{ protected: - std::shared_ptr BrakeCyl; //silownik - std::shared_ptr BrakeRes; //ZP - std::shared_ptr ValveRes; //komora wstepna - int BCN = 0; //ilosc silownikow - double BCM = 0.0; //przekladnia hamulcowa - double BCA = 0.0; //laczny przekroj silownikow - int BrakeDelays = 0; //dostepne opoznienia - int BrakeDelayFlag = 0; //aktualna nastawa - std::shared_ptr FM; //material cierny - double MaxBP = 0.0; //najwyzsze cisnienie - int BA = 0; //osie hamowane - int NBpA = 0; //klocki na os - double SizeBR = 0.0; //rozmiar^2 ZP (w stosunku do 14") - double SizeBC = 0.0; //rozmiar^2 CH (w stosunku do 14") - bool DCV = false; //podwojny zawor zwrotny - double ASBP = 0.0; //cisnienie hamulca pp - double RV = 0.0; // rapid activation vehicle velocity threshold + /// Brake cylinder (silownik) — actuator that pushes the brake blocks. + std::shared_ptr BrakeCyl; // silownik + /// Auxiliary reservoir (ZP) — local source of compressed air for the cylinder. + std::shared_ptr BrakeRes; // ZP + /// Valve pre-chamber (komora wstepna) — small volume connected to the brake pipe / distributor. + std::shared_ptr ValveRes; // komora wstepna + /// Number of brake cylinders on the vehicle. + int BCN = 0; // ilosc silownikow + /// Brake transmission ratio (mechanical leverage between cylinder and shoes). + double BCM = 0.0; // przekladnia hamulcowa + /// Combined cross-section area of all brake cylinders. + double BCA = 0.0; // laczny przekroj silownikow + /// Bitfield of available brake delay positions (combination of bdelay_* flags). + int BrakeDelays = 0; // dostepne opoznienia + /// Currently selected brake delay (one of bdelay_* values). + int BrakeDelayFlag = 0; // aktualna nastawa + /// Friction material model used for the shoes/discs. + std::shared_ptr FM; // material cierny + /// Maximum brake cylinder pressure [bar] in service braking. + double MaxBP = 0.0; // najwyzsze cisnienie + /// Number of braked axles on the vehicle. + int BA = 0; // osie hamowane + /// Number of brake blocks per axle. + int NBpA = 0; // klocki na os + /// Squared size of the auxiliary reservoir relative to a 14" reference cylinder. + double SizeBR = 0.0; // rozmiar^2 ZP (w stosunku do 14") + /// Squared size of the brake cylinder relative to a 14" reference cylinder. + double SizeBC = 0.0; // rozmiar^2 CH (w stosunku do 14") + /// True when the double check valve (auxiliary brake -> cylinder) is engaged. + bool DCV = false; // podwojny zawor zwrotny + /// Anti-slip brake target pressure. + double ASBP = 0.0; // cisnienie hamulca pp + /// Velocity threshold above which the rapid braking step is enabled. + double RV = 0.0; // rapid activation vehicle velocity threshold - int UniversalFlag = 0; //flaga wcisnietych przyciskow uniwersalnych - int BrakeStatus{ b_off }; //flaga stanu - int SoundFlag = 0; + /// Bitfield with the currently active universal-button actions (see TUniversalBrake). + int UniversalFlag = 0; // flaga wcisnietych przyciskow uniwersalnych + /// Current brake state (combination of b_off / b_hld / b_on / b_rls / ... flags). + int BrakeStatus{b_off}; // flaga stanu + /// Bitfield of pending sound events (sf_* flags). Cleared after each read. + int SoundFlag = 0; public: - TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa); - //maksymalne cisnienie, promien, skok roboczy, pojemnosc ZP, ilosc cylindrow, opoznienia hamulca, material klockow, osie hamowane, klocki na os; - virtual void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF ); //inicjalizacja hamulca + /// + /// Builds a brake unit and selects the friction material. + /// + /// Maximum brake cylinder pressure [bar]. + /// Brake cylinder radius [m]. + /// Brake cylinder working stroke [m]. + /// Auxiliary reservoir capacity [l]. + /// Number of brake cylinders. + /// Available brake delay positions (bitwise of bdelay_* flags). + /// Friction material id (one of bp_* constants, optionally OR'ed with bp_MHS). + /// Number of braked axles. + /// Number of blocks per axle. + TBrake(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa); + // maksymalne cisnienie, promien, skok roboczy, pojemnosc ZP, ilosc cylindrow, opoznienia hamulca, material klockow, osie hamowane, klocki na os; + /// + /// Initialises the brake to a given starting state (pressures and delay). + /// + /// Brake pipe pressure [bar]. + /// High (control) pressure [bar]. + /// Low pressure threshold [bar]. + /// Initial brake cylinder pressure [bar]. + /// Initial brake delay flag. + virtual void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF); // inicjalizacja hamulca - double GetFC( double const Vel, double const N ); //wspolczynnik tarcia - hamulec wie lepiej - virtual double GetPF( double const PP, double const dt, double const Vel ); //przeplyw miedzy komora wstepna i PG - double GetBCF(); //sila tlokowa z tloka - virtual double GetHPFlow( double const HP, double const dt ); //przeplyw - 8 bar - double GetBCP(); //cisnienie cylindrow hamulcowych - virtual double GetEDBCP(); //cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED w EP09 - double GetBRP(); //cisnienie zbiornika pomocniczego - double GetVRP(); //cisnienie komory wstepnej rozdzielacza - virtual double GetCRP(); //cisnienie zbiornika sterujacego - bool SetBDF( int const nBDF ); //nastawiacz GPRM - void Releaser( int const state ); //odluzniacz - bool Releaser() const; - virtual void SetEPS( double const nEPS ); //hamulec EP - virtual void SetRM( double const RMR ) {}; //ustalenie przelozenia rapida - virtual void SetRV( double const RVR ) { RV = RVR; }; //ustalenie przelozenia rapida - virtual void SetLP(double const TM, double const LM, double const TBP) {}; //parametry przystawki wazacej - virtual void SetLBP(double const P) {}; //cisnienie z hamulca pomocniczego - virtual void PLC(double const mass) {}; //wspolczynnik cisnienia przystawki wazacej - void ASB(int state); //hamulec przeciwposlizgowy - int GetStatus(); //flaga statusu, moze sie przydac do odglosow - void SetASBP( double const Press ); //ustalenie cisnienia pp - virtual void ForceEmptiness(); - // removes specified amount of air from the reservoirs - virtual void ForceLeak( double const Amount ); - int GetSoundFlag(); - int GetBrakeStatus() const { return BrakeStatus; } - void SetBrakeStatus( int const Status ) { BrakeStatus = Status; } - virtual void SetED( double const EDstate ) {}; //stan hamulca ED do luzowania - virtual void SetUniversalFlag(int flag) { UniversalFlag = flag; } //przycisk uniwersalny + /// + /// Returns the current friction coefficient between blocks and the wheel/disc. + /// Delegates to the friction material model. + /// + /// Current vehicle velocity [m/s or km/h depending on FM]. + /// Normal force on the block [N]. + /// Friction coefficient. + double GetFC(double const Vel, double const N); // wspolczynnik tarcia - hamulec wie lepiej + /// + /// Advances the brake distributor for one simulation step and returns the net + /// volume exchanged with the brake pipe (positive = drawn from the brake pipe). + /// + /// Brake pipe pressure [bar] at the connection point. + /// Time step [s]. + /// Vehicle velocity [m/s]. + /// Volume exchanged between the valve pre-chamber and the brake pipe. + virtual double GetPF(double const PP, double const dt, double const Vel); // przeplyw miedzy komora wstepna i PG + /// + /// Returns the piston force produced by the brake cylinder pressure. + /// + /// Force in arbitrary engine units (BCA * 100 * P). + double GetBCF(); // sila tlokowa z tloka + /// + /// Computes the airflow drawn from the high-pressure (8 bar / main) line for one step. + /// + /// High-pressure source pressure [bar]. + /// Time step [s]. + /// Net flow from the high-pressure line. + virtual double GetHPFlow(double const HP, double const dt); // przeplyw - 8 bar + /// Returns brake cylinder gauge pressure [bar]. + double GetBCP(); // cisnienie cylindrow hamulcowych + /// + /// Returns brake cylinder pressure originating only from the pneumatic + /// (main) brake — used to drive the ED (electrodynamic) brake e.g. in EP09. + /// + virtual double GetEDBCP(); // cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED w EP09 + /// Returns auxiliary reservoir (ZP) pressure [bar]. + double GetBRP(); // cisnienie zbiornika pomocniczego + /// Returns valve pre-chamber pressure [bar]. + double GetVRP(); // cisnienie komory wstepnej rozdzielacza + /// Returns control reservoir (ZS) pressure [bar]; defaults to the auxiliary reservoir for valves without a dedicated ZS. + virtual double GetCRP(); // cisnienie zbiornika sterujacego + /// + /// Sets the brake delay (G/P/R/M) selector if requested mode is supported. + /// + /// Requested delay flag (bdelay_*). + /// True if accepted (mode supported and changed); false otherwise. + bool SetBDF(int const nBDF); // nastawiacz GPRM + /// + /// Engages or disengages the releaser (odluzniacz), updating the brake state flags. + /// + /// 1 to engage releaser, 0 to disengage. + void Releaser(int const state); // odluzniacz + /// Returns true if the releaser is currently engaged. + bool Releaser() const; + /// + /// Sets the electro-pneumatic state (EP) — strength of the EP brake action. + /// Default no-op; overridden by EP-capable distributors. + /// + /// EP intensity (typically -1..1). + virtual void SetEPS(double const nEPS); // hamulec EP + /// Sets the rapid step ratio. Default no-op; overridden where supported. + /// Rapid ratio. + virtual void SetRM(double const RMR) {}; // ustalenie przelozenia rapida + /// Sets the velocity threshold for the rapid step. + /// Velocity threshold (same unit as Vel passed to GetPF). + virtual void SetRV(double const RVR) + { + RV = RVR; + }; // ustalenie przelozenia rapida + /// + /// Sets the load-weighing parameters (empty/loaded mass, empty-mass cylinder pressure). + /// Default no-op; overridden where load-weighing is supported. + /// + /// Tare (empty) mass. + /// Loaded mass. + /// Brake cylinder pressure for the tare mass. + virtual void SetLP(double const TM, double const LM, double const TBP) {}; // parametry przystawki wazacej + /// Sets the auxiliary (local) brake target pressure. + /// Local brake pressure [bar]. + virtual void SetLBP(double const P) {}; // cisnienie z hamulca pomocniczego + /// Updates the load-weighing pressure coefficient based on current vehicle mass. + /// Current vehicle mass. + virtual void PLC(double const mass) {}; // wspolczynnik cisnienia przystawki wazacej + /// + /// Engages the anti-slip brake function (set hold and/or release flags). + /// + /// Two-bit value: bit1 = hold (b_asb), bit0 = release (b_asb_unbrake). + void ASB(int state); // hamulec przeciwposlizgowy + /// Returns the raw BrakeStatus flags (for sound/visual cues). + int GetStatus(); // flaga statusu, moze sie przydac do odglosow + /// Sets the anti-slip target pressure. + /// Pressure [bar]. + void SetASBP(double const Press); // ustalenie cisnienia pp + /// Vents all reservoirs to zero pressure (used when the vehicle is decoupled or reset). + virtual void ForceEmptiness(); + /// + /// Removes a specified relative amount of air from the reservoirs to simulate leaks. + /// + /// Fraction of pressure to bleed (0..1) per call. + virtual void ForceLeak(double const Amount); + /// Returns and clears the accumulated SoundFlag bitfield. + int GetSoundFlag(); + /// Returns the current brake status flags. + int GetBrakeStatus() const + { + return BrakeStatus; + } + /// Overwrites the brake status flags. + /// New BrakeStatus value. + void SetBrakeStatus(int const Status) + { + BrakeStatus = Status; + } + /// + /// Sets the ED (electrodynamic) brake state, used to release the pneumatic + /// brake when ED braking is sufficient. Default no-op; overridden where supported. + /// + /// ED brake intensity (0..1). + virtual void SetED(double const EDstate) {}; // stan hamulca ED do luzowania + /// Sets the universal-button flags (see TUniversalBrake). + /// Combined ub_* flags. + virtual void SetUniversalFlag(int flag) + { + UniversalFlag = flag; + } // przycisk uniwersalny }; -class TWest : public TBrake { +/// +/// Simple Westinghouse triple-valve distributor with optional EP brake and +/// load-weighing equipment. The auxiliary brake (cab handle) feeds straight +/// into the cylinder via the double check valve (DCV). +/// +class TWest : public TBrake +{ private: - double LBP = 0.0; //cisnienie hamulca pomocniczego - double dVP = 0.0; //pobor powietrza wysokiego cisnienia - double EPS = 0.0; //stan elektropneumatyka - double TareM = 0.0; //masa proznego - double LoadM = 0.0; //i pelnego - double TareBP = 0.0; //cisnienie dla proznego - double LoadC = 0.0; //wspolczynnik przystawki wazacej + /// Auxiliary (local) brake pressure [bar]. + double LBP = 0.0; // cisnienie hamulca pomocniczego + /// High-pressure flow drawn during the last step (for the main reservoir bookkeeping). + double dVP = 0.0; // pobor powietrza wysokiego cisnienia + /// Current EP brake intensity (-1..1). + double EPS = 0.0; // stan elektropneumatyka + /// Tare (empty) vehicle mass. + double TareM = 0.0; // masa proznego + /// Loaded vehicle mass. + double LoadM = 0.0; // i pelnego + /// Cylinder pressure for tare mass. + double TareBP = 0.0; // cisnienie dla proznego + /// Computed load-weighing coefficient (1.0 for fully loaded). + double LoadC = 0.0; // wspolczynnik przystawki wazacej public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - void SetLBP(double const P); //cisnienie z hamulca pomocniczego - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - double GetHPFlow( double const HP, double const dt )/*override*/; - void PLC(double const mass); //wspolczynnik cisnienia przystawki wazacej - void SetEPS( double const nEPS )/*override*/; //stan hamulca EP - void SetLP(double const TM, double const LM, double const TBP); //parametry przystawki wazacej + /// Initialises pressures: PP into ValveRes, BP into BrakeCyl, average of PP/HPP into BrakeRes. + /// Brake pipe pressure. + /// High pressure. + /// Low pressure. + /// Initial cylinder pressure. + /// Initial brake delay flag. + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// Sets the auxiliary brake target pressure and engages the DCV when above cylinder. + /// Pressure [bar]. + void SetLBP(double const P); // cisnienie z hamulca pomocniczego + /// One-step distributor advance (Westinghouse logic). + /// Net flow exchanged with the brake pipe. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Returns the high-pressure flow drawn during the last GetPF step. + double GetHPFlow(double const HP, double const dt) /*override*/; + /// Recomputes the load-weighing pressure coefficient for the current mass. + /// Vehicle mass. + void PLC(double const mass); // wspolczynnik cisnienia przystawki wazacej + /// Sets the EP brake state and toggles the DCV / latches LBP from cylinder pressure on release. + /// New EP intensity. + void SetEPS(double const nEPS) /*override*/; // stan hamulca EP + /// Stores the load-weighing parameters (TareM, LoadM, TareBP). + void SetLP(double const TM, double const LM, double const TBP); // parametry przystawki wazacej - inline TWest(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - {} + /// Constructs the distributor by forwarding all parameters to TBrake. + inline TWest(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) {} }; -class TESt : public TBrake { +/// +/// Oerlikon ESt distributor base. Adds a control reservoir (ZS) and the +/// classical "main slide-valve" logic (CheckState/CheckReleaser/CVs/BVs). +/// Concrete variants (ESt3, ESt3AL2, ESt4R, LSt, EStED, EStEP1/2) refine GetPF. +/// +class TESt : public TBrake +{ private: + protected: + /// Control reservoir (ZS) — long-term reference pressure. + std::shared_ptr CntrlRes; // zbiornik sterujący + /// Brake-pipe to brake-cylinder transmission ratio (BVM = MaxBP / (HPP-LPP)). + double BVM = 0.0; // przelozenie PG-CH + + public: + /// Initialises the ESt distributor; sizes the control reservoir (15 l) and computes BVM. + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// One-step distributor advance for the ESt baseline. + /// Net flow exchanged with the brake pipe. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Sets ESt-specific characteristic parameters (placeholder; used by some variants). + /// Characteristic value. + void EStParams(double i_crc); // parametry charakterystyczne dla ESt + /// Returns the control reservoir (ZS) pressure. + double GetCRP() /*override*/; + /// + /// Updates BrakeStatus (b_on/b_hld) according to the relations between + /// pre-chamber, cylinder and control reservoir pressures (the main slide valve). + /// Triggers the accelerator (sf_Acc) at the start of braking. + /// + /// Brake cylinder (or impulse) pressure. + /// In/out accumulator for the brake pipe flow correction. + void CheckState(double BCP, double &dV1); // glowny przyrzad rozrzadczy + /// Drives the releaser logic — bleeds the control reservoir while the releaser is engaged. + /// Time step [s]. + void CheckReleaser(double dt); // odluzniacz + /// + /// Returns the effective opening factor of the ZS-filling slide valve as a + /// function of cylinder pressure and current pre-chamber/reservoir state. + /// + /// Cylinder pressure (or impulse-chamber pressure). + /// Dimensionless opening coefficient. + double CVs(double BP); // napelniacz sterujacego + /// + /// Returns the effective opening factor of the auxiliary-reservoir filling + /// slide valve (ZP <-> pre-chamber path). + /// + /// Brake cylinder pressure. + /// Dimensionless opening coefficient. + double BVs(double BCP); // napelniacz pomocniczego + /// Vents the valve, brake and control reservoirs to zero. + void ForceEmptiness() /*override*/; // wymuszenie bycia pustym + + /// Constructs the ESt distributor and creates the control reservoir. + inline TESt(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + CntrlRes = std::make_shared(); + } +}; + +/// +/// ESt3 variant — adjusts the cylinder fill/release rates depending on the +/// G/P delay setting; otherwise keeps the ESt slide-valve logic. +/// +class TESt3 : public TESt +{ + + private: + // double CylFlowSpeed[2][2]; //zmienna nie uzywana + + public: + /// One-step distributor advance for ESt3 (G/P-dependent fill/release curves). + /// Net flow exchanged with the brake pipe. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + + /// Constructs the ESt3 distributor. + inline TESt3(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TESt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) {} +}; + +/// +/// ESt3 with AL2 load-weighing equipment. Adds an impulse chamber and a +/// load-pressure relay that scales the cylinder pressure between empty/loaded. +/// +class TESt3AL2 : public TESt3 +{ + + private: + /// Impulse chamber (KI) — drives the load relay output to the brake cylinder. + std::shared_ptr ImplsRes; // komora impulsowa + /// Tare (empty) vehicle mass. + double TareM = 0.0; // masa proznego + /// Loaded vehicle mass. + double LoadM = 0.0; // i pelnego + /// Cylinder pressure for tare mass. + double TareBP = 0.0; // cisnienie dla proznego + /// Computed load-weighing coefficient. + double LoadC = 0.0; + + public: + /// Initialises the impulse chamber on top of the ESt initialisation. + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// One-step distributor advance for ESt3/AL2 with load-weighing relay. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Recomputes LoadC for the current vehicle mass. + void PLC(double const mass); // wspolczynnik cisnienia przystawki wazacej + /// Stores the load-weighing parameters. + void SetLP(double const TM, double const LM, double const TBP); // parametry przystawki wazacej + + /// Constructs the distributor and creates the impulse chamber. + inline TESt3AL2(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TESt3(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + ImplsRes = std::make_shared(); + } +}; + +/// +/// ESt4 with rapid (R) step. Adds a separately controlled impulse chamber +/// and a velocity-driven rapid factor that boosts cylinder pressure above a +/// configurable speed threshold. +/// +class TESt4R : public TESt +{ + + private: + /// Hysteretic rapid-step latch (true while rapid is active). + bool RapidStatus = false; protected: - std::shared_ptr CntrlRes; // zbiornik sterujący - double BVM = 0.0; // przelozenie PG-CH + /// Impulse chamber (KI) — intermediate pressure feeding the load relay. + std::shared_ptr ImplsRes; // komora impulsowa + /// Smoothed rapid-step coefficient (current effective ratio). + double RapidTemp = 0.0; // aktualne, zmienne przelozenie public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - void EStParams(double i_crc); //parametry charakterystyczne dla ESt - double GetCRP()/*override*/; - void CheckState(double BCP, double & dV1); //glowny przyrzad rozrzadczy - void CheckReleaser(double dt); //odluzniacz - double CVs(double BP); //napelniacz sterujacego - double BVs(double BCP); //napelniacz pomocniczego - void ForceEmptiness() /*override*/; // wymuszenie bycia pustym + /// Initialises the ESt4R; sizes the impulse chamber and selects the R delay. + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// One-step distributor advance for ESt4R (rapid step active above velocity threshold). + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG - inline TESt(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - CntrlRes = std::make_shared(); - } + /// Constructs the distributor and creates the impulse chamber. + inline TESt4R(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TESt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + ImplsRes = std::make_shared(); + } }; -class TESt3 : public TESt { +/// +/// LSt distributor — locomotive variant of ESt4R with a double check valve +/// (auxiliary brake LBP), configurable rapid ratio and ED-brake release input. +/// +class TLSt : public TESt4R +{ private: - //double CylFlowSpeed[2][2]; //zmienna nie uzywana - - public: - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - - inline TESt3(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TESt( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - {} -}; - -class TESt3AL2 : public TESt3 { - - private: - std::shared_ptr ImplsRes; //komora impulsowa - double TareM = 0.0; //masa proznego - double LoadM = 0.0; //i pelnego - double TareBP = 0.0; //cisnienie dla proznego - double LoadC = 0.0; - - public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - void PLC(double const mass); //wspolczynnik cisnienia przystawki wazacej - void SetLP(double const TM, double const LM, double const TBP); //parametry przystawki wazacej - - inline TESt3AL2(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TESt3( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - ImplsRes = std::make_shared(); - } -}; - -class TESt4R : public TESt { - - private: - bool RapidStatus = false; + // double CylFlowSpeed[2][2]; // zmienna nie używana protected: - std::shared_ptr ImplsRes; //komora impulsowa - double RapidTemp = 0.0; //aktualne, zmienne przelozenie + /// Auxiliary (local) brake pressure feeding the DCV. + double LBP = 0.0; // cisnienie hamulca pomocniczego + /// Rapid step ratio (1 - RMR; see SetRM). + double RM = 0.0; // przelozenie rapida + /// ED brake state (0..1) — relaxes the pneumatic brake when ED is active. + double EDFlag = 0.0; // luzowanie hamulca z powodu zalaczonego ED public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG + /// Initialises the LSt; resizes the valve and impulse reservoirs and presets pressures. + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// Sets the auxiliary brake target pressure for the DCV. + void SetLBP(double const P); // cisnienie z hamulca pomocniczego + /// Sets the rapid step ratio (RM = 1 - RMR). + /// Reduction ratio (0 disables rapid, > 0 enables). + void SetRM(double const RMR); // ustalenie przelozenia rapida + /// One-step distributor advance for LSt (DCV + rapid + ED release). + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Computes the high-pressure inflow (replenishes the auxiliary reservoir from the main line). + double GetHPFlow(double const HP, double const dt) /*override*/; // przeplyw - 8 bar + /// Returns the brake-cylinder reference pressure used by the ED brake controller (CVP-BCP * BVM). + virtual double GetEDBCP(); // cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED w EP09 + /// Sets the ED brake state used to relax the pneumatic brake. + /// ED intensity (0..1). + virtual void SetED(double const EDstate); // stan hamulca ED do luzowania - inline TESt4R(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TESt( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - ImplsRes = std::make_shared(); - } + /// Constructs the LSt distributor. + inline TLSt(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TESt4R(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) {} }; -class TLSt : public TESt4R { +/// +/// EStED distributor (used in EP09): ESt4R with a separate load relay, +/// rapid-step control, intermediate reservoir (Miedzypoj) and a fully +/// nozzle-tuned ZP/ZS filling characteristic. +/// +class TEStED : public TLSt +{ // zawor z EP09 - Est4 z oddzielnym przekladnikiem, kontrola rapidu i takie tam private: - // double CylFlowSpeed[2][2]; // zmienna nie używana + /// Intermediate (virtual) reservoir used to refill ZP and ZS. + std::shared_ptr Miedzypoj; // pojemnosc posrednia (urojona) do napelniania ZP i ZS + /// Effective cross-sections of the internal nozzles (squared diameters). + double Nozzles[11]; // dysze + /// Closing-valve memory latch. + bool Zamykajacy = false; // pamiec zaworka zamykajacego + /// Accelerator-block latch (prevents the accelerator from triggering twice). + bool Przys_blok = false; // blokada przyspieszacza + /// Tare (empty) vehicle mass. + double TareM = 0.0; // masa proznego + /// Loaded vehicle mass. + double LoadM = 0.0; // i pelnego + /// Cylinder pressure for tare mass. + double TareBP = 0.0; // cisnienie dla proznego + /// Computed load-weighing coefficient. + double LoadC = 0.0; + + public: + /// Initialises the EStED — sets up Miedzypoj, ImplsRes and the nozzle characteristics. + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// One-step distributor advance for EStED (full EP09 logic with intermediate reservoir). + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Returns ED-brake reference pressure (ImplsRes pressure scaled by load coefficient). + double GetEDBCP() /*override*/; // cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED + /// Recomputes LoadC for the current vehicle mass. + void PLC(double const mass); // wspolczynnik cisnienia przystawki wazacej + /// Stores the load-weighing parameters. + void SetLP(double const TM, double const LM, double const TBP); // parametry przystawki wazacej + + /// Constructs the distributor and creates the intermediate reservoir. + inline TEStED(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TLSt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + Miedzypoj = std::make_shared(); + } +}; + +/// +/// ESt with EP2 electro-pneumatic add-on (continuous EP brake, two-wire +/// driver). Uses the LSt base and supplies its own EP-flow calculation. +/// +class TEStEP2 : public TLSt +{ protected: - double LBP = 0.0; //cisnienie hamulca pomocniczego - double RM = 0.0; //przelozenie rapida - double EDFlag = 0.0; //luzowanie hamulca z powodu zalaczonego ED + /// Tare (empty) vehicle mass. + double TareM = 0.0; // masa proznego + /// Loaded vehicle mass. + double LoadM = 0.0; // masa pelnego + /// Cylinder pressure for tare mass. + double TareBP = 0.0; // cisnienie dla proznego + /// Computed load-weighing coefficient. + double LoadC = 0.0; + /// EP intensity (-1..1). + double EPS = 0.0; public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - void SetLBP(double const P); //cisnienie z hamulca pomocniczego - void SetRM( double const RMR ); //ustalenie przelozenia rapida - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - double GetHPFlow( double const HP, double const dt )/*override*/; //przeplyw - 8 bar - virtual double GetEDBCP(); //cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED w EP09 - virtual void SetED( double const EDstate ); //stan hamulca ED do luzowania - - inline TLSt(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TESt4R( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - {} -}; - -class TEStED : public TLSt { //zawor z EP09 - Est4 z oddzielnym przekladnikiem, kontrola rapidu i takie tam - - private: - std::shared_ptr Miedzypoj; //pojemnosc posrednia (urojona) do napelniania ZP i ZS - double Nozzles[ 11 ]; //dysze - bool Zamykajacy = false; //pamiec zaworka zamykajacego - bool Przys_blok = false; //blokada przyspieszacza - double TareM = 0.0; //masa proznego - double LoadM = 0.0; //i pelnego - double TareBP = 0.0; //cisnienie dla proznego - double LoadC = 0.0; - - - public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - double GetEDBCP()/*override*/; //cisnienie tylko z hamulca zasadniczego, uzywane do hamulca ED - void PLC(double const mass); //wspolczynnik cisnienia przystawki wazacej - void SetLP( double const TM, double const LM, double const TBP ); //parametry przystawki wazacej - - inline TEStED(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TLSt( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - Miedzypoj = std::make_shared(); - } -}; - -class TEStEP2 : public TLSt { - -protected: - double TareM = 0.0; //masa proznego - double LoadM = 0.0; //masa pelnego - double TareBP = 0.0; //cisnienie dla proznego - double LoadC = 0.0; - double EPS = 0.0; - -public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; //inicjalizacja - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - void PLC( double const mass ); //wspolczynnik cisnienia przystawki wazacej - void SetEPS( double const nEPS )/*override*/; //stan hamulca EP - void SetLP( double const TM, double const LM, double const TBP ); //parametry przystawki wazacej + /// Initialises the EP2-equipped distributor (impulse chamber, P delay). + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; // inicjalizacja + /// One-step distributor advance with EP2 EP brake logic. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Recomputes LoadC for the current vehicle mass. + void PLC(double const mass); // wspolczynnik cisnienia przystawki wazacej + /// Sets EP intensity; if EP is active and LBP < cylinder pressure, latches LBP from cylinder. + void SetEPS(double const nEPS) /*override*/; // stan hamulca EP + /// Stores the load-weighing parameters. + void SetLP(double const TM, double const LM, double const TBP); // parametry przystawki wazacej + /// EP brake flow integration step. Override in EP1 for proportional control. + /// Time step [s]. void virtual EPCalc(double dt); - inline TEStEP2(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TLSt( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - {} + /// Constructs the EP2 distributor. + inline TEStEP2(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TLSt(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) {} }; -class TEStEP1 : public TEStEP2 { +/// +/// EP1 variant of the EP brake (continuous, proportional). Reuses EP2's +/// distributor pneumatics but replaces the EP-flow integrator with a +/// proportional model based on the fractional part of EPS. +/// +class TEStEP1 : public TEStEP2 +{ -public: + public: + /// Proportional EP flow integration step (uses fractional part of EPS as the EP target). void EPCalc(double dt); - void SetEPS( double const nEPS ) override; //stan hamulca EP + /// Stores the EP intensity. + /// Target EP value (integer part = direction, fractional part = magnitude). + void SetEPS(double const nEPS) override; // stan hamulca EP - inline TEStEP1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TEStEP2(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - {} + /// Constructs the EP1 distributor. + inline TEStEP1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TEStEP2(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + } }; -class TCV1 : public TBrake { +/// +/// DAKO CV1 distributor — Czech triple-valve with control reservoir and a +/// simpler slide-valve characteristic than ESt. +/// +class TCV1 : public TBrake +{ -private: - double BVM = 0.0; //przelozenie PG-CH + private: + /// Brake-pipe to brake-cylinder transmission ratio. + double BVM = 0.0; // przelozenie PG-CH -protected: - std::shared_ptr CntrlRes; // zbiornik sterujący + protected: + /// Control reservoir (ZS). + std::shared_ptr CntrlRes; // zbiornik sterujący -public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - double GetCRP()/*override*/; - void CheckState( double const BCP, double &dV1 ); - double CVs( double const BP ); - double BVs( double const BCP ); - void ForceEmptiness() /*override*/; // wymuszenie bycia pustym + public: + /// Initialises the CV1 distributor (sizes ZS, sets pressures, computes BVM). + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// One-step distributor advance for the CV1 baseline. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Returns the control reservoir (ZS) pressure. + double GetCRP() /*override*/; + /// Updates BrakeStatus based on pre-chamber/cylinder/control reservoir relations and the releaser. + /// Cylinder (or impulse) pressure. + /// In/out brake pipe flow correction. + void CheckState(double const BCP, double &dV1); + /// Returns the ZS-filling slide valve opening factor for the given cylinder pressure. + double CVs(double const BP); + /// Returns the ZP-filling slide valve opening factor for the given cylinder pressure. + double BVs(double const BCP); + /// Vents valve, brake and control reservoirs to zero. + void ForceEmptiness() /*override*/; // wymuszenie bycia pustym - inline TCV1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - CntrlRes = std::make_shared(); - } + /// Constructs the CV1 distributor and creates the control reservoir. + inline TCV1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + CntrlRes = std::make_shared(); + } }; - //class TCV1R : public TCV1 +// class TCV1R : public TCV1 //{ - //private: +// private: // TReservoir *ImplsRes; //komora impulsowa // bool RapidStatus; - //public: - // // function GetPF(PP, dt, Vel: real): real; override; //przeplyw miedzy komora wstepna i PG +// public: +// // function GetPF(PP, dt, Vel: real): real; override; //przeplyw miedzy komora wstepna i PG // // procedure Init(PP, HPP, LPP, BP: real; BDF: int); override; // inline TCV1R(double i_mbp, double i_bcr, double i_bcd, double i_brc, // int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa, - // double PP, double HPP, double LPP, double BP, int BDF) : TCV1(i_mbp, i_bcr, i_bcd, i_brc, i_bcn +// double PP, double HPP, double LPP, double BP, int BDF) : TCV1(i_mbp, i_bcr, i_bcd, i_brc, i_bcn // , i_BD, i_mat, i_ba, i_nbpa, PP, HPP, LPP, BP, BDF) { } //}; -class TCV1L_TR : public TCV1 { - -private: - std::shared_ptr ImplsRes; //komora impulsowa - double LBP = 0.0; //cisnienie hamulca pomocniczego - -public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - void SetLBP( double const P ); //cisnienie z hamulca pomocniczego - double GetHPFlow( double const HP, double const dt )/*override*/; //przeplyw - 8 bar - - inline TCV1L_TR(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TCV1( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - ImplsRes = std::make_shared(); - } -}; - -class TKE : public TBrake { //Knorr Einheitsbauart — jeden do wszystkiego +/// +/// CV1-L-TR distributor — locomotive variant of CV1 with auxiliary (local) +/// brake input, impulse chamber and a high-pressure replenishing path. +/// +class TCV1L_TR : public TCV1 +{ private: - std::shared_ptr ImplsRes; //komora impulsowa - std::shared_ptr CntrlRes; // zbiornik sterujący - std::shared_ptr Brak2Res; //zbiornik pomocniczy 2 - bool RapidStatus = false; - double BVM = 0.0; //przelozenie PG-CH - double TareM = 0.0; //masa proznego - double LoadM = 0.0; //masa pelnego - double TareBP = 0.0; //cisnienie dla proznego - double LoadC = 0.0; //wspolczynnik zaladowania - double RM = 0.0; //przelozenie rapida - double LBP = 0.0; //cisnienie hamulca pomocniczego + /// Impulse chamber (KI) — drives the relay output to the brake cylinder. + std::shared_ptr ImplsRes; // komora impulsowa + /// Auxiliary (local) brake pressure feeding the DCV. + double LBP = 0.0; // cisnienie hamulca pomocniczego public: - void Init( double const PP, double const HPP, double const LPP, double const BP, int const BDF )/*override*/; - void SetRM( double const RMR ); //ustalenie przelozenia rapida - double GetPF( double const PP, double const dt, double const Vel )/*override*/; //przeplyw miedzy komora wstepna i PG - double GetHPFlow( double const HP, double const dt )/*override*/; //przeplyw - 8 bar - double GetCRP()/*override*/; - void CheckState( double const BCP, double &dV1 ); - void CheckReleaser( double const dt ); //odluzniacz - double CVs( double const BP ); //napelniacz sterujacego - double BVs( double const BCP ); //napelniacz pomocniczego - void PLC( double const mass ); //wspolczynnik cisnienia przystawki wazacej - void SetLP( double const TM, double const LM, double const TBP ); //parametry przystawki wazacej - void SetLBP( double const P ); //cisnienie z hamulca pomocniczego - void ForceEmptiness() /*override*/; // wymuszenie bycia pustym + /// Initialises the CV1-L-TR (sizes the impulse chamber on top of CV1::Init). + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// One-step distributor advance for CV1-L-TR (impulse chamber + DCV). + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Sets the auxiliary brake target pressure for the DCV. + void SetLBP(double const P); // cisnienie z hamulca pomocniczego + /// Computes the high-pressure (8 bar) inflow used to replenish the auxiliary reservoir. + double GetHPFlow(double const HP, double const dt) /*override*/; // przeplyw - 8 bar - inline TKE(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : - TBrake( i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) - { - ImplsRes = std::make_shared(); - CntrlRes = std::make_shared(); - Brak2Res = std::make_shared(); - } + /// Constructs the CV1-L-TR and creates the impulse chamber. + inline TCV1L_TR(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TCV1(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + ImplsRes = std::make_shared(); + } }; -//klasa obejmujaca krany -class TDriverHandle { +/// +/// Knorr KE (Einheitsbauart) — universal distributor with control reservoir, +/// impulse chamber, optional auxiliary reservoir, rapid step driven by speed +/// and friction-pair type, and load-weighing equipment. +/// +class TKE : public TBrake +{ // Knorr Einheitsbauart — jeden do wszystkiego + + private: + /// Impulse chamber (KI). + std::shared_ptr ImplsRes; // komora impulsowa + /// Control reservoir (ZS). + std::shared_ptr CntrlRes; // zbiornik sterujący + /// Secondary auxiliary reservoir (ZP2) — used in some variants for additional capacity. + std::shared_ptr Brak2Res; // zbiornik pomocniczy 2 + /// Hysteretic rapid-step latch. + bool RapidStatus = false; + /// Brake-pipe to brake-cylinder transmission ratio. + double BVM = 0.0; // przelozenie PG-CH + /// Tare (empty) vehicle mass. + double TareM = 0.0; // masa proznego + /// Loaded vehicle mass. + double LoadM = 0.0; // masa pelnego + /// Cylinder pressure for tare mass. + double TareBP = 0.0; // cisnienie dla proznego + /// Computed load-weighing coefficient. + double LoadC = 0.0; // wspolczynnik zaladowania + /// Rapid step coefficient (RM = 1 - RMR). + double RM = 0.0; // przelozenie rapida + /// Auxiliary (local) brake pressure feeding the DCV. + double LBP = 0.0; // cisnienie hamulca pomocniczego + + public: + /// Initialises the KE distributor (control / impulse / auxiliary reservoirs and BVM). + void Init(double const PP, double const HPP, double const LPP, double const BP, int const BDF) /*override*/; + /// Sets the rapid step ratio (RM = 1 - RMR). + void SetRM(double const RMR); // ustalenie przelozenia rapida + /// One-step distributor advance for the KE distributor. + double GetPF(double const PP, double const dt, double const Vel) /*override*/; // przeplyw miedzy komora wstepna i PG + /// Computes the high-pressure (8 bar) inflow used to replenish the auxiliary reservoir. + double GetHPFlow(double const HP, double const dt) /*override*/; // przeplyw - 8 bar + /// Returns the control reservoir (ZS) pressure. + double GetCRP() /*override*/; + /// Updates BrakeStatus from cylinder/pre-chamber/control reservoir pressures (KE-specific thresholds). + void CheckState(double const BCP, double &dV1); + /// Drives the releaser logic for KE — bleeds the control reservoir while engaged. + void CheckReleaser(double const dt); // odluzniacz + /// ZS-filling slide valve opening factor for the given cylinder pressure. + double CVs(double const BP); // napelniacz sterujacego + /// ZP-filling slide valve opening factor for the given cylinder pressure. + double BVs(double const BCP); // napelniacz pomocniczego + /// Recomputes LoadC for the current vehicle mass. + void PLC(double const mass); // wspolczynnik cisnienia przystawki wazacej + /// Stores the load-weighing parameters. + void SetLP(double const TM, double const LM, double const TBP); // parametry przystawki wazacej + /// Sets the auxiliary brake target pressure for the DCV. + void SetLBP(double const P); // cisnienie z hamulca pomocniczego + /// Vents valve, brake, control, impulse and secondary auxiliary reservoirs to zero. + void ForceEmptiness() /*override*/; // wymuszenie bycia pustym + + /// Constructs the KE distributor and creates the control / impulse / secondary reservoirs. + inline TKE(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) : TBrake(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa) + { + ImplsRes = std::make_shared(); + CntrlRes = std::make_shared(); + Brak2Res = std::make_shared(); + } +}; + +/// +/// Base class for the driver's brake handle (cab valve / kran maszynisty). +/// Concrete handles (FV4a, FV4a/M, MHZ_*, M394, H14K1, St113, FVel6, ...) +/// implement to compute the brake pipe flow for a given +/// handle position and supply additional gauges (control, equalising, EP). +/// +class TDriverHandle +{ protected: - // BCP: integer; - bool AutoOvrld = false; //czy jest asymilacja automatyczna na pozycji -1 - bool ManualOvrld = false; //czy jest asymilacja reczna przyciskiem - bool ManualOvrldActive = false; //czy jest wcisniety przycisk asymilacji - int UniversalFlag = 0; //flaga wcisnietych przyciskow uniwersalnych - int i_bcpno = 6; - public: - bool Time = false; - bool TimeEP = false; - double Sounds[ 5 ]; //wielkosci przeplywow dla dzwiekow + // BCP: integer; + /// True if the handle automatically overcharges in the high-pressure position (e.g. -1). + bool AutoOvrld = false; // czy jest asymilacja automatyczna na pozycji -1 + /// True if the handle supports manual overcharge/assimilation via a dedicated button. + bool ManualOvrld = false; // czy jest asymilacja reczna przyciskiem + /// Whether the manual overcharge button is currently pressed. + bool ManualOvrldActive = false; // czy jest wcisniety przycisk asymilacji + /// Bitfield with the active universal-button actions (see TUniversalBrake). + int UniversalFlag = 0; // flaga wcisnietych przyciskow uniwersalnych + /// Number of the highest (last) handle position. + int i_bcpno = 6; - virtual double GetPF(double i_bcp, double PP, double HP, double dt, double ep); - virtual void Init(double Press); - virtual double GetCP(); - virtual double GetEP(); - virtual double GetRP(); - virtual void SetReductor(double nAdj); //korekcja pozycji reduktora cisnienia - virtual double GetSound(int i); //pobranie glosnosci wybranego dzwieku - virtual double GetPos(int i); //pobranie numeru pozycji o zadanym kodzie (funkcji) - virtual double GetEP(double pos); //pobranie sily hamulca ep - virtual void SetParams(bool AO, bool MO, double, double, double OMP, double OPD) {}; //ustawianie jakichs parametrow dla zaworu - virtual void OvrldButton(bool Active); //przycisk recznego przeladowania/asymilacji - virtual void SetUniversalFlag(int flag); //przycisk uniwersalny - inline TDriverHandle() { memset( Sounds, 0, sizeof( Sounds ) ); } + public: + /// True if the handle has a "time" (delay/charge) chamber. + bool Time = false; + /// True if the handle has an EP-time chamber. + bool TimeEP = false; + /// Per-event sound flow magnitudes (indices defined by s_fv4a_*). + double Sounds[5]; // wielkosci przeplywow dla dzwiekow + + /// + /// Computes the brake pipe flow produced by the handle in one simulation step. + /// + /// Handle position (continuous; integer values map to detents). + /// Brake pipe pressure [bar]. + /// High-pressure source [bar]. + /// Time step [s]. + /// EP / equalising input pressure [bar]. + /// Volume change of the brake pipe (positive = into pipe). + virtual double GetPF(double i_bcp, double PP, double HP, double dt, double ep); + /// Initialises internal pressures from the supplied reference. + /// Initial pressure [bar]. + virtual void Init(double Press); + /// Returns the control-reservoir / equalising pressure displayed on the cab gauge. + virtual double GetCP(); + /// Returns the EP brake intensity reported by the handle (0 by default). + virtual double GetEP(); + /// Returns the regulator (reduction) pressure target. + virtual double GetRP(); + /// Adjusts the pressure reductor offset (turning the cap of the reductor). + /// Pressure correction [bar]. + virtual void SetReductor(double nAdj); // korekcja pozycji reduktora cisnienia + /// Returns the requested sound channel magnitude (index 0..4 defined by s_fv4a_*). + /// Sound index. + virtual double GetSound(int i); // pobranie glosnosci wybranego dzwieku + /// + /// Returns the position value (number of detents) for the requested function code. + /// + /// Function index (bh_* constants). + virtual double GetPos(int i); // pobranie numeru pozycji o zadanym kodzie (funkcji) + /// Returns EP brake force at the given handle position. + /// Handle position. + virtual double GetEP(double pos); // pobranie sily hamulca ep + /// + /// Configures handle-specific behaviour (overcharge mode, filling stroke factor and overcharge dynamics). + /// + /// Auto-overcharge enabled. + /// Manual-overcharge enabled. + /// Unbrake over-pressure [bar]. + /// Overload (assimilation) max pressure [bar]. + /// Overload pressure decay rate [bar/s]. + virtual void SetParams(bool AO, bool MO, double, double, double OMP, double OPD) {}; // ustawianie jakichs parametrow dla zaworu + /// Sets the manual overcharge button state. + /// True while the button is pressed. + virtual void OvrldButton(bool Active); // przycisk recznego przeladowania/asymilacji + /// Stores the universal-button flags (see TUniversalBrake). + /// Combined ub_* flags. + virtual void SetUniversalFlag(int flag); // przycisk uniwersalny + /// Default constructor — clears the Sounds[] array. + inline TDriverHandle() + { + memset(Sounds, 0, sizeof(Sounds)); + } }; -class TFV4a : public TDriverHandle { +/// +/// FV4a driver's handle (classic Polish PKP cab valve, 6-position). +/// +class TFV4a : public TDriverHandle +{ private: - double CP = 0.0; //zbiornik sterujący - double TP = 0.0; //zbiornik czasowy - double RP = 0.0; //zbiornik redukcyjny + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący + /// Time chamber pressure [bar]. + double TP = 0.0; // zbiornik czasowy + /// Reductor reservoir pressure [bar]. + double RP = 0.0; // zbiornik redukcyjny public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; + /// Computes brake pipe flow for the FV4a handle (uses BPT[] table). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP and RP to the supplied pressure. + void Init(double Press) /*override*/; - inline TFV4a() : - TDriverHandle() - {} + /// Default constructor. + inline TFV4a() : TDriverHandle() {} }; -class TFV4aM : public TDriverHandle { +/// +/// FV4a/M — modernised FV4a without the IC correction. Adds a reductor air +/// chamber to model the brake pipe pressure wave at the start of a release. +/// +class TFV4aM : public TDriverHandle +{ private: - double CP = 0.0; //zbiornik sterujący - double TP = 0.0; //zbiornik czasowy - double RP = 0.0; //zbiornik redukcyjny - double XP = 0.0; //komora powietrzna w reduktorze — jest potrzebna do odwzorowania fali - double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) - // Sounds: array[0..4] of real; //wielkosci przeplywow dla dzwiekow - bool Fala = false; - static double const pos_table[11]; // = { -2, 6, -1, 0, -2, 1, 4, 6, 0, 0, 0 }; + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący + /// Time chamber pressure [bar]. + double TP = 0.0; // zbiornik czasowy + /// Reductor reservoir pressure [bar]. + double RP = 0.0; // zbiornik redukcyjny + /// Reductor air chamber pressure (models the release pressure wave). + double XP = 0.0; // komora powietrzna w reduktorze — jest potrzebna do odwzorowania fali + /// Reductor adjustment offset (turning the cap). + double RedAdj = 0.0; // dostosowanie reduktora cisnienia (krecenie kapturkiem) + // Sounds: array[0..4] of real; //wielkosci przeplywow dla dzwiekow + /// True while the release pressure wave is active. + bool Fala = false; + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; // = { -2, 6, -1, 0, -2, 1, 4, 6, 0, 0, 0 }; - double LPP_RP(double pos); - bool EQ(double pos, double i_pos); + /// + /// Returns the brake pipe pressure target interpolated from BPT[] for the given handle position. + /// + /// Handle position. + double LPP_RP(double pos); + /// Returns true if pos is within ±0.5 of i_pos (detent comparison). + bool EQ(double pos, double i_pos); public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - void SetReductor(double nAdj)/*override*/; - double GetSound(int i)/*override*/; - double GetPos(int i)/*override*/; - double GetCP(); - double GetRP(); - inline TFV4aM() : - TDriverHandle() - {} + /// Computes brake pipe flow for the FV4a/M handle (interpolated BPT, wave modelling, accelerator). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP and RP. + void Init(double Press) /*override*/; + /// Sets the reductor adjustment offset. + void SetReductor(double nAdj) /*override*/; + /// Returns Sounds[i] (or 0 if i > 4). + double GetSound(int i) /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Returns the time chamber pressure (TP). + double GetCP(); + /// Returns the regulator pressure (5 + TP*0.08 + RedAdj). + double GetRP(); + /// Default constructor. + inline TFV4aM() : TDriverHandle() {} }; -class TMHZ_EN57 : public TDriverHandle { +/// +/// MHZ_EN57 — combined brake handle for EN57 EMUs (10-position, EP brake plus pneumatic). +/// +class TMHZ_EN57 : public TDriverHandle +{ private: - double CP = 0.0; //zbiornik sterujący - double TP = 0.0; //zbiornik czasowy - double RP = 0.0; //zbiornik redukcyjny - double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) - bool Fala = false; - double UnbrakeOverPressure = 0.0; - double OverloadMaxPressure = 1.0; //maksymalne zwiekszenie cisnienia przy asymilacji - double OverloadPressureDecrease = 0.045; //predkosc spadku cisnienia przy asymilacji - static double const pos_table[11]; //= { -2, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0 }; - - double LPP_RP(double pos); - bool EQ(double pos, double i_pos); - - public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - void SetReductor(double nAdj)/*override*/; - double GetSound(int i)/*override*/; - double GetPos(int i)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; - double GetEP(double pos); - void SetParams(bool AO, bool MO, double OverP, double, double OMP, double OPD); - inline TMHZ_EN57(void) : - TDriverHandle() - {} -}; - -class TMHZ_K5P : public TDriverHandle { - -private: - double CP = 0.0; //zbiornik sterujący - double TP = 0.0; //zbiornik czasowy - double RP = 0.0; //zbiornik redukcyjny - double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) - bool Fala = false; //czy jest napelnianie uderzeniowe + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący + /// Time chamber pressure [bar]. + double TP = 0.0; // zbiornik czasowy + /// Reductor reservoir pressure [bar]. + double RP = 0.0; // zbiornik redukcyjny + /// Reductor adjustment offset. + double RedAdj = 0.0; // dostosowanie reduktora cisnienia (krecenie kapturkiem) + /// True while the release pressure wave is active. + bool Fala = false; + /// Configured unbrake over-pressure [bar]. double UnbrakeOverPressure = 0.0; - double OverloadMaxPressure = 1.0; //maksymalne zwiekszenie cisnienia przy asymilacji - double OverloadPressureDecrease = 0.002; //predkosc spadku cisnienia przy asymilacji - double FillingStrokeFactor = 1.0; //mnożnik otwarcia zaworu przy uderzeniowym (bez fali) + /// Maximum overcharge pressure when assimilating. + double OverloadMaxPressure = 1.0; // maksymalne zwiekszenie cisnienia przy asymilacji + /// Decay rate of the overcharge pressure. + double OverloadPressureDecrease = 0.045; // predkosc spadku cisnienia przy asymilacji + /// Lookup of bh_* function codes to handle position values. static double const pos_table[11]; //= { -2, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0 }; + /// Returns the brake pipe pressure target for the given handle position (piecewise). + double LPP_RP(double pos); + /// Returns true if pos is within ±0.5 of i_pos. bool EQ(double pos, double i_pos); -public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - void SetReductor(double nAdj)/*override*/; - double GetSound(int i)/*override*/; - double GetPos(int i)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; - void SetParams(bool AO, bool MO, double, double, double OMP, double OPD); /*ovveride*/ - - inline TMHZ_K5P(void) : - TDriverHandle() - {} + public: + /// Computes brake pipe flow for MHZ_EN57 (covers handle positions -1..10 with EP/pneumatic mix). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP. + void Init(double Press) /*override*/; + /// Sets the reductor adjustment offset. + void SetReductor(double nAdj) /*override*/; + /// Returns Sounds[i] (or 0 if i > 4). + double GetSound(int i) /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Returns the regulator pressure (RP). + double GetCP() /*override*/; + /// Returns the regulator target (5 + RedAdj). + double GetRP() /*override*/; + /// Returns EP brake intensity for the given handle position. + double GetEP(double pos); + /// Configures handle parameters (auto/manual overcharge, over-pressure, overcharge dynamics). + void SetParams(bool AO, bool MO, double OverP, double, double OMP, double OPD); + /// Default constructor. + inline TMHZ_EN57(void) : TDriverHandle() {} }; -class TMHZ_6P : public TDriverHandle { +/// +/// MHZ_K5P — Knorr 5-position combined brake handle. +/// +class TMHZ_K5P : public TDriverHandle +{ -private: - double CP = 0.0; //zbiornik sterujący - double TP = 0.0; //zbiornik czasowy - double RP = 0.0; //zbiornik redukcyjny - double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) - bool Fala = false; //czy jest napelnianie uderzeniowe - double UnbrakeOverPressure = 0.0; //wartosc napelniania uderzeniowego - double OverloadMaxPressure = 1.0; //maksymalne zwiekszenie cisnienia przy asymilacji - double OverloadPressureDecrease = 0.002; //predkosc spadku cisnienia przy asymilacji - double FillingStrokeFactor = 1.0; //mnożnik otwarcia zaworu przy uderzeniowym (bez fali) + private: + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący + /// Time chamber pressure [bar]. + double TP = 0.0; // zbiornik czasowy + /// Reductor reservoir pressure [bar]. + double RP = 0.0; // zbiornik redukcyjny + /// Reductor adjustment offset. + double RedAdj = 0.0; // dostosowanie reduktora cisnienia (krecenie kapturkiem) + /// True while filling-stroke / release wave is active. + bool Fala = false; // czy jest napelnianie uderzeniowe + /// Configured unbrake over-pressure [bar]. + double UnbrakeOverPressure = 0.0; + /// Maximum overcharge pressure when assimilating. + double OverloadMaxPressure = 1.0; // maksymalne zwiekszenie cisnienia przy asymilacji + /// Decay rate of the overcharge pressure. + double OverloadPressureDecrease = 0.002; // predkosc spadku cisnienia przy asymilacji + /// Filling-stroke valve opening multiplier when no wave is active. + double FillingStrokeFactor = 1.0; // mnożnik otwarcia zaworu przy uderzeniowym (bez fali) + /// Lookup of bh_* function codes to handle position values. static double const pos_table[11]; //= { -2, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0 }; + /// Returns true if pos is within ±0.5 of i_pos. bool EQ(double pos, double i_pos); -public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - void SetReductor(double nAdj)/*override*/; - double GetSound(int i)/*override*/; - double GetPos(int i)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; + public: + /// Computes brake pipe flow for the K5P 5-position handle (release / cut-off / brake / emergency). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP and enables the time chambers. + void Init(double Press) /*override*/; + /// Sets the reductor adjustment offset. + void SetReductor(double nAdj) /*override*/; + /// Returns Sounds[i] (or 0 if i > 4). + double GetSound(int i) /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns the regulator target (5 + TP + RedAdj). + double GetRP() /*override*/; + /// Configures handle parameters (auto/manual overcharge, over-pressure, filling-stroke factor, overcharge dynamics). void SetParams(bool AO, bool MO, double, double, double OMP, double OPD); /*ovveride*/ - inline TMHZ_6P(void) : - TDriverHandle() - {} + /// Default constructor. + inline TMHZ_K5P(void) : TDriverHandle() {} +}; + +/// +/// MHZ_6P — 6-position combined brake handle (similar logic to K5P with one more detent). +/// +class TMHZ_6P : public TDriverHandle +{ + + private: + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący + /// Time chamber pressure [bar]. + double TP = 0.0; // zbiornik czasowy + /// Reductor reservoir pressure [bar]. + double RP = 0.0; // zbiornik redukcyjny + /// Reductor adjustment offset. + double RedAdj = 0.0; // dostosowanie reduktora cisnienia (krecenie kapturkiem) + /// True while filling-stroke / release wave is active. + bool Fala = false; // czy jest napelnianie uderzeniowe + /// Configured filling-stroke over-pressure value. + double UnbrakeOverPressure = 0.0; // wartosc napelniania uderzeniowego + /// Maximum overcharge pressure when assimilating. + double OverloadMaxPressure = 1.0; // maksymalne zwiekszenie cisnienia przy asymilacji + /// Decay rate of the overcharge pressure. + double OverloadPressureDecrease = 0.002; // predkosc spadku cisnienia przy asymilacji + /// Filling-stroke valve opening multiplier when no wave is active. + double FillingStrokeFactor = 1.0; // mnożnik otwarcia zaworu przy uderzeniowym (bez fali) + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; //= { -2, 10, -1, 0, 0, 2, 9, 10, 0, 0, 0 }; + + /// Returns true if pos is within ±0.5 of i_pos. + bool EQ(double pos, double i_pos); + + public: + /// Computes brake pipe flow for the 6P handle. + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP and enables the time chambers. + void Init(double Press) /*override*/; + /// Sets the reductor adjustment offset. + void SetReductor(double nAdj) /*override*/; + /// Returns Sounds[i] (or 0 if i > 4). + double GetSound(int i) /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns the regulator target (5 + TP + RedAdj). + double GetRP() /*override*/; + /// Configures handle parameters (auto/manual overcharge, over-pressure, filling-stroke factor, overcharge dynamics). + void SetParams(bool AO, bool MO, double, double, double OMP, double OPD); /*ovveride*/ + + /// Default constructor. + inline TMHZ_6P(void) : TDriverHandle() {} }; /* FBS2= class(TTDriverHandle) private - CP, TP, RP: real; //zbiornik sterujący, czasowy, redukcyjny - XP: real; //komora powietrzna w reduktorze — jest potrzebna do odwzorowania fali + CP, TP, RP: real; //zbiornik sterujący, czasowy, redukcyjny + XP: real; //komora powietrzna w reduktorze — jest potrzebna do odwzorowania fali RedAdj: real; //dostosowanie reduktora cisnienia (krecenie kapturkiem) // Sounds: array[0..4] of real; //wielkosci przeplywow dla dzwiekow Fala: boolean; @@ -707,8 +1343,8 @@ public: /* TD2= class(TTDriverHandle) private - CP, TP, RP: real; //zbiornik sterujący, czasowy, redukcyjny - XP: real; //komora powietrzna w reduktorze — jest potrzebna do odwzorowania fali + CP, TP, RP: real; //zbiornik sterujący, czasowy, redukcyjny + XP: real; //komora powietrzna w reduktorze — jest potrzebna do odwzorowania fali RedAdj: real; //dostosowanie reduktora cisnienia (krecenie kapturkiem) // Sounds: array[0..4] of real; //wielkosci przeplywow dla dzwiekow Fala: boolean; @@ -720,168 +1356,303 @@ public: function GetPos(i: int): real; override; end;*/ -class TM394 : public TDriverHandle { +/// +/// Matrosow 394 — Russian/Soviet 5-position cab valve. Uses the BPT_394 table. +/// +class TM394 : public TDriverHandle +{ private: - double CP = 0.0; //zbiornik sterujący, czasowy, redukcyjny - double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) - static double const pos_table[11]; // = { -1, 5, -1, 0, 1, 2, 4, 5, 0, 0, 0 }; + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący, czasowy, redukcyjny + /// Reductor adjustment offset. + double RedAdj = 0.0; // dostosowanie reduktora cisnienia (krecenie kapturkiem) + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; // = { -1, 5, -1, 0, 1, 2, 4, 5, 0, 0, 0 }; public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - void SetReductor(double nAdj)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; - double GetPos(int i)/*override*/; + /// Computes brake pipe flow for the M394 handle (uses BPT_394). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP and enables the time chamber. + void Init(double Press) /*override*/; + /// Sets the reductor adjustment offset. + void SetReductor(double nAdj) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns max(5, CP) + RedAdj. + double GetRP() /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; - inline TM394(void) : - TDriverHandle() - { - i_bcpno = 5; } + /// Default constructor — sets the maximum handle position to 5. + inline TM394(void) : TDriverHandle() + { + i_bcpno = 5; + } }; -class TH14K1 : public TDriverHandle { +/// +/// H14K1 — Knorr auxiliary (independent) brake handle (4-position). +/// +class TH14K1 : public TDriverHandle +{ private: - static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2]; - static double const pos_table[11]; // = {-1, 4, -1, 0, 1, 2, 3, 4, 0, 0, 0}; + /// Position table for the H14K1 (range -1..4): {flow speed, target multiplier}. + static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2]; + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; // = {-1, 4, -1, 0, 1, 2, 3, 4, 0, 0, 0}; protected: - double CP = 0.0; //zbiornik sterujący, czasowy, redukcyjny - double RedAdj = 0.0; //dostosowanie reduktora cisnienia (krecenie kapturkiem) + /// Control reservoir pressure [bar]. + double CP = 0.0; // zbiornik sterujący, czasowy, redukcyjny + /// Reductor adjustment offset. + double RedAdj = 0.0; // dostosowanie reduktora cisnienia (krecenie kapturkiem) public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - void SetReductor(double nAdj)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; - double GetPos(int i)/*override*/; + /// Computes brake pipe flow for the H14K1 handle. + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP and enables the time chambers. + void Init(double Press) /*override*/; + /// Sets the reductor adjustment offset. + void SetReductor(double nAdj) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns the regulator target (5 + RedAdj). + double GetRP() /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; - inline TH14K1(void) : - TDriverHandle() - { - i_bcpno = 4; } + /// Default constructor — sets the maximum handle position to 4. + inline TH14K1(void) : TDriverHandle() + { + i_bcpno = 4; + } }; -class TSt113 : public TH14K1 { +/// +/// St113 — Knorr EP-equipped 5-position brake handle (extends H14K1 with EP step). +/// +class TSt113 : public TH14K1 +{ private: - double EPS = 0.0; - static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2]; - static double const BEP_K[/*?*/ /*-1..5*/ (5) - (-1) + 1]; - static double const pos_table[11]; // = {-1, 5, -1, 0, 2, 3, 4, 5, 0, 0, 1}; - double CP = 0; - public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; - double GetEP()/*override*/; - double GetPos(int i)/*override*/; - void Init(double Press)/*override*/; - - inline TSt113(void) : - TH14K1() - {} -}; - -class Ttest : public TDriverHandle { - - private: - double CP = 0.0; - - public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - - inline Ttest(void) : - TDriverHandle() - {} -}; - -class TFD1 : public TDriverHandle { - - private: - double MaxBP = 0.0; //najwyzsze cisnienie - double BP = 0.0; //aktualne cisnienie - - public: - double Speed = 0.0; //szybkosc dzialania - - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - double GetCP()/*override*/; - void SetSpeed(double nSpeed); - // procedure Init(press: real; MaxBP: real); overload; - - inline TFD1(void) : - TDriverHandle() - {} -}; - -class TH1405 : public TDriverHandle { - - private: - double MaxBP = 0.0; //najwyzsze cisnienie - double BP = 0.0; //aktualne cisnienie - - public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - void Init(double Press)/*override*/; - double GetCP()/*override*/; - // procedure Init(press: real; MaxBP: real); overload; - - inline TH1405(void) : - TDriverHandle() - {} -}; - -class TFVel6 : public TDriverHandle { - - private: - double EPS = 0.0; - static double const pos_table[ 11 ]; // = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1}; - double CP = 0.0; - - public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - double GetCP()/*override*/; - double GetRP()/*override*/; - double GetEP()/*override*/; - double GetPos(int i)/*override*/; - double GetSound(int i)/*override*/; - void Init(double Press)/*override*/; - - inline TFVel6(void) : - TDriverHandle() - {} -}; - -class TFVE408 : public TDriverHandle { - -private: + /// Current EP intensity reported by the handle. double EPS = 0.0; - static double const pos_table[11]; // = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1}; + /// Position table (override of H14K1's, with adjusted parameters). + static double const BPT_K[/*?*/ /*-1..4*/ (4) - (-1) + 1][2]; + /// EP table — EP intensity per handle position (range -1..5). + static double const BEP_K[/*?*/ /*-1..5*/ (5) - (-1) + 1]; + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; // = {-1, 5, -1, 0, 2, 3, 4, 5, 0, 0, 1}; + /// Local control pressure (mirrors PP). + double CP = 0; + + public: + /// Computes brake pipe flow for the St113 handle (with EP). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns the regulator target (5 + RedAdj). + double GetRP() /*override*/; + /// Returns the current EP intensity. + double GetEP() /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Enables the time chambers (no pressure init). + void Init(double Press) /*override*/; + + /// Default constructor. + inline TSt113(void) : TH14K1() {} +}; + +/// +/// Test handle — minimal implementation used during development for verifying +/// brake pipe responses with the BPT[] table. +/// +class Ttest : public TDriverHandle +{ + + private: + /// Control reservoir pressure [bar]. double CP = 0.0; -public: - double GetPF(double i_bcp, double PP, double HP, double dt, double ep)/*override*/; - double GetCP()/*override*/; - double GetEP()/*override*/; - double GetRP()/*override*/; - double GetPos(int i)/*override*/; - double GetSound(int i)/*override*/; - void Init(double Press)/*override*/; + public: + /// Computes brake pipe flow using the FV4a-style BPT table for testing. + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises CP. + void Init(double Press) /*override*/; - inline TFVE408(void) : - TDriverHandle() - {} + /// Default constructor. + inline Ttest(void) : TDriverHandle() {} }; +/// +/// FD1 auxiliary brake handle — directly drives the cylinder pressure between +/// 0 and MaxBP based on the handle position (linear scaling with configurable speed). +/// +class TFD1 : public TDriverHandle +{ -extern double PF( double const P1, double const P2, double const S, double const DP = 0.25 ); -extern double PF1( double const P1, double const P2, double const S ); + private: + /// Maximum cylinder pressure [bar] commandable by this handle. + double MaxBP = 0.0; // najwyzsze cisnienie + /// Current commanded cylinder pressure [bar]. + double BP = 0.0; // aktualne cisnienie -extern double PFVa( double PH, double PL, double const S, double LIM, double const DP = 0.1 ); //zawor napelniajacy z PH do PL, PL do LIM -extern double PFVd( double PH, double PL, double const S, double LIM, double const DP = 0.1 ); //zawor wypuszczajacy z PH do PL, PH do LIM + public: + /// Action speed multiplier — scales the response time. + double Speed = 0.0; // szybkosc dzialania + + /// Computes the auxiliary brake outflow for this step. + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises MaxBP and the action speed. + void Init(double Press) /*override*/; + /// Returns the currently commanded cylinder pressure (BP). + double GetCP() /*override*/; + /// Sets the action speed multiplier. + void SetSpeed(double nSpeed); + // procedure Init(press: real; MaxBP: real); overload; + + /// Default constructor. + inline TFD1(void) : TDriverHandle() {} +}; + +/// +/// H1405 — Knorr auxiliary brake handle (continuous, independent brake). +/// +class TH1405 : public TDriverHandle +{ + + private: + /// Maximum cylinder pressure [bar]. + double MaxBP = 0.0; // najwyzsze cisnienie + /// Current commanded cylinder pressure [bar]. + double BP = 0.0; // aktualne cisnienie + + public: + /// Computes the auxiliary brake outflow for this step (proportional to handle deflection). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Initialises MaxBP and enables the time chamber. + void Init(double Press) /*override*/; + /// Returns the currently commanded cylinder pressure (BP). + double GetCP() /*override*/; + // procedure Init(press: real; MaxBP: real); overload; + + /// Default constructor. + inline TH1405(void) : TDriverHandle() {} +}; + +/// +/// FVel6 — combined EP + pneumatic brake handle (Czech, 6+1 positions). +/// +class TFVel6 : public TDriverHandle +{ + + private: + /// Current EP intensity reported by the handle. + double EPS = 0.0; + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; // = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1}; + /// Local control pressure (mirrors PP). + double CP = 0.0; + + public: + /// Computes brake pipe flow for FVel6 (continuous EP brake plus pneumatic emergency). + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns the regulator target (constant 5 bar). + double GetRP() /*override*/; + /// Returns the current EP intensity. + double GetEP() /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Returns Sounds[i] (or 0 if i > 2). + double GetSound(int i) /*override*/; + /// Enables the time chambers. + void Init(double Press) /*override*/; + + /// Default constructor. + inline TFVel6(void) : TDriverHandle() {} +}; + +/// +/// FVE408 — newer combined EP + pneumatic brake handle (10 positions). +/// EP intensity is set to fixed steps for positions 1..5. +/// +class TFVE408 : public TDriverHandle +{ + + private: + /// Current EP intensity reported by the handle. + double EPS = 0.0; + /// Lookup of bh_* function codes to handle position values. + static double const pos_table[11]; // = {-1, 6, -1, 0, 6, 4, 4.7, 5, -1, 0, 1}; + /// Local control pressure (mirrors PP). + double CP = 0.0; + + public: + /// Computes brake pipe flow for the FVE408 handle. + double GetPF(double i_bcp, double PP, double HP, double dt, double ep) /*override*/; + /// Returns CP. + double GetCP() /*override*/; + /// Returns the current EP intensity. + double GetEP() /*override*/; + /// Returns the regulator target (constant 5 bar). + double GetRP() /*override*/; + /// Returns pos_table[i]. + double GetPos(int i) /*override*/; + /// Returns Sounds[i] (or 0 if i > 2). + double GetSound(int i) /*override*/; + /// Enables the time chamber, disables the EP-time chamber. + void Init(double Press) /*override*/; + + /// Default constructor. + inline TFVE408(void) : TDriverHandle() {} +}; + +/// +/// Pneumatic flow rate from one pressure to another through an orifice of area S. +/// Models choked vs. subsonic flow (critical pressure ratio = 0.5) and softens +/// the response near zero pressure difference using a DP-wide ramp. +/// +/// Source pressure [bar]. +/// Destination pressure [bar]. +/// Effective orifice cross-section. +/// Soft-clip pressure delta — softens flow for tiny PH-PL differences (default 0.25). +/// Volumetric flow rate (signed; positive = P1->P2 direction). +extern double PF(double const P1, double const P2, double const S, double const DP = 0.25); +/// +/// Variant of that uses the dimensionless pressure ratio (sg) +/// for the soft-clip threshold instead of an absolute pressure delta. +/// +/// Source pressure [bar]. +/// Destination pressure [bar]. +/// Effective orifice cross-section. +/// Volumetric flow rate. +extern double PF1(double const P1, double const P2, double const S); + +/// +/// Filling valve flow: flows from PH to PL until PL reaches LIM. The valve +/// throttles smoothly as PL approaches LIM (within DP of the target). +/// Returns 0 once PL is already >= LIM. +/// +/// High-pressure source [bar]. +/// Low-pressure side [bar]. +/// Effective orifice cross-section. +/// Target pressure for PL [bar]. +/// Throttling distance from LIM (default 0.1). +/// Flow rate from PH to PL (positive into PL). +extern double PFVa(double PH, double PL, double const S, double LIM, double const DP = 0.1); // zawor napelniajacy z PH do PL, PL do LIM +/// +/// Venting valve flow: flows from PH to PL until PH falls to LIM. The valve +/// throttles smoothly as PH approaches LIM. Returns 0 once PH <= LIM. +/// +/// High-pressure side that is being vented [bar]. +/// Low-pressure destination [bar]. +/// Effective orifice cross-section. +/// Lower bound for PH [bar]. +/// Throttling distance from LIM (default 0.1). +/// Flow rate from PH to PL. +extern double PFVd(double PH, double PL, double const S, double LIM, double const DP = 0.1); // zawor wypuszczajacy z PH do PL, PH do LIM