Files
maszyna/McZapkie/Mover.cpp
2016-10-31 07:38:45 +01:00

7877 lines
286 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
*/
#include <MATH.H>
#include <FLOAT.H>
#include <typeinfo>
#include <fstream> // std::ifstream
#include <sstream>
#include <istream>
#include <iostream>
#include <stdio.h> // sprintf()
#include <stdlib.h>
#include <math.h>
#include <cmath>
#include <stdio.h>
#include "Mover.h"
#include "../globals.h"
//#include "../qutils.h"
#include <mctools.h>
#include "../logs.h"
#include "hamulce.h"
#include "Oerlikon_ESt.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
// Ra: tu nale¿y przenosiæ funcje z mover.pas, które nie s¹ z niego wywo³ywane.
// Jeœli jakieœ zmienne nie s¹ u¿ywane w mover.pas, te¿ mo¿na je przenosiæ.
// Przeniesienie wszystkiego na raz zrobi³o by zbyt wielki chaos do ogarniêcia.
const double dEpsilon = 0.01; // 1cm (zale¿y od typu sprzêgu...)
const double CouplerTune = 0.1; // skalowanie tlumiennosci
long Trunc(float f)
{
return (long)f;
}
long ROUND(float f)
{
return Trunc(f + 0.5);
}
double sqr(double val) // SQR() zle liczylo w current() ...
{
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
if (v1 < v2 && vc)
return 0;
else
{
double sum = m1 + m2;
double w1 = ((m1 - m2) * v1 + 2 * m2 * v2) / sum;
double w2 = ((m2 - m1) * v2 + 2 * m1 * v1) / sum;
v1 = w1 * sqrt(1 - beta); // niejawna zmiana predkosci wskutek zderzenia
v2 = w2 * sqrt(1 - beta);
return m1 * (w2 - w1) * (1 - beta);
}
}
int DirPatch(int Coupler1, int Coupler2)
{
return (Coupler1 != Coupler2 ? 1 : -1);
}
int DirF(int CouplerN)
{
switch (CouplerN)
{
case 0:
return -1;
case 1:
return 1;
default:
return 0;
}
}
// *************************************************************************************************
// Q: 20160716
// *************************************************************************************************
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
const float ep09resED = 5.8; // TODO: dobrac tak aby sie zgadzalo ze wbudzeniem
double R, MotorCurrent;
double Rz, Delta, Isf;
int Mn;
double Bn;
int SP;
double U1; // napiecie z korekta
MotorCurrent = 0;
// i dzialanie hamulca ED w EP09
//- if (DynamicBrakeType == dbrake_automatic)
//- {
//- if ((( static_cast<TLSt*>(Hamulec)->GetEDBCP() < 0.25) && (Vadd < 1)) || (BrakePress >
//2.1))
//- DynamicBrakeFlag = false;
//- else if ((BrakePress > 0.25) && (static_cast<TLSt*>(Hamulec)->GetEDBCP() > 0.25))
//- DynamicBrakeFlag = true;
//- DynamicBrakeFlag = (DynamicBrakeFlag && ConverterFlag);
//- }
// 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)
if (DynamicBrakeFlag)
{
static_cast<TLSt *>(Hamulec)
->SetED(abs(Im / 350)); // hamulec ED na EP09 dziala az do zatrzymania lokomotywy
//- WriteLog("A");
}
else
{
static_cast<TLSt *>(Hamulec)->SetED(0);
//- WriteLog("B");
}
ResistorsFlag = (RList[MainCtrlActualPos].R > 0.01); // and (!DelayCtrlFlag)
ResistorsFlag =
(ResistorsFlag || ((DynamicBrakeFlag == true) && (DynamicBrakeType == dbrake_automatic)));
if ((TrainType == dt_ET22) && (DelayCtrlFlag) && (MainCtrlActualPos > 1))
Bn = 1 - 1 / RList[MainCtrlActualPos].Bn;
else
Bn = 1; // to jest wykonywane dla EU07
R = RList[MainCtrlActualPos].R * Bn + CircuitRes;
if ((TrainType != dt_EZT) || (Imin != IminLo) ||
(!ScndS)) // yBARC - boczniki na szeregu poprawnie
Mn = RList[MainCtrlActualPos].Mn; // to jest wykonywane dla EU07
else
Mn = RList[MainCtrlActualPos].Mn * RList[MainCtrlActualPos].Bn;
// writepaslog("#",
// "C++-----------------------------------------------------------------------------");
// writepaslog("MCAP ", IntToStr(MainCtrlActualPos));
// writepaslog("SCAP ", IntToStr(ScndCtrlActualPos));
// writepaslog("n ", FloatToStr(n));
// writepaslog("StLinFlag ", BoolToYN(StLinFlag));
// writepaslog("DelayCtrlFlag ", booltoYN(DelayCtrlFlag));
// writepaslog("Bn ", FloatToStr(Bn));
// writepaslog("R ", FloatToStr(R));
// writepaslog("Mn ", IntToStr(Mn));
// writepaslog("RList[MCAP].Bn ", FloatToStr(RList[MainCtrlActualPos].Bn));
// writepaslog("RList[MCAP].Mn ", FloatToStr(RList[MainCtrlActualPos].Mn));
// writepaslog("RList[MCAP].R ", FloatToStr(RList[MainCtrlActualPos].R));
// z Megapacka ... bylo tutaj zakomentowane Q: no to usuwam...
//- if (DynamicBrakeFlag && (!FuseFlag) && (DynamicBrakeType == dbrake_automatic) &&
//ConverterFlag && Mains) //hamowanie EP09 //TUHEX
//- {
//- WriteLog("TUHEX");
//- MotorCurrent = -Max0R(MotorParam[0].fi * (Vadd / (Vadd + MotorParam[0].Isat) -
//MotorParam[0].fi0), 0) * n * 2 / ep09resED; //TODO: zrobic bardziej uniwersalne nie tylko dla
//EP09
//- }
//- else
if ((RList[MainCtrlActualPos].Bn == 0) || (!StLinFlag))
MotorCurrent = 0; // wylaczone
else
{ // wlaczone...
SP = ScndCtrlActualPos;
if (ScndCtrlActualPos < 255) // tak smiesznie bede wylaczal
{
if (ScndInMain)
if (!(RList[MainCtrlActualPos].ScndAct == 255))
SP = RList[MainCtrlActualPos].ScndAct;
Rz = Mn * WindingRes + R;
//- if (DynamicBrakeFlag) //hamowanie
//- {
//-
//- if (DynamicBrakeType > 1)
//- {
//-
//- if ((DynamicBrakeType == dbrake_switch) && (TrainType == dt_ET42))
//- { //z Megapacka
//- Rz = WindingRes + R;
//- 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 = sqr(Isf * Rz + Mn * MotorParam[SP].fi * n - U1) +
4 * 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 + sqrt(Delta)) / (2.0 * Rz);
else
MotorCurrent =
(U1 - Isf * Rz - Mn * MotorParam[SP].fi * n - sqrt(Delta)) / (2.0 * Rz);
}
else
MotorCurrent = 0;
} // else DBF
} // 255
else
MotorCurrent = 0;
}
// writepaslog("MotorCurrent ", FloatToStr(MotorCurrent));
//- if ((DynamicBrakeType == dbrake_switch) && ((BrakePress > 2.0) || (PipePress < 3.6)))
//- {
//- WriteLog("DynamicBrakeType=" + IntToStr( dbrake_switch ));
//- Im = 0;
//- MotorCurrent = 0;
//- Itot = 0;
//- }
//- else
{
Im = MotorCurrent;
}
EnginePower = abs(Itot) * (1 + RList[MainCtrlActualPos].Mn) * abs(U);
// awarie
MotorCurrent = abs(Im); // zmienna pomocnicza
if (MotorCurrent > 0)
{
//-if FuzzyLogic(Abs(n),nmax*1.1,p_elengproblem) then
//- if MainSwitch(false) then
//- EventFlag:=true; {zbyt duze obroty - wywalanie wskutek ognia okreznego}
//-if TestFlag(DamageFlag,dtrain_engine) then
//- if FuzzyLogic(MotorCurrent,ImaxLo/10.0,p_elengproblem) then
//- if MainSwitch(false) then
//- EventFlag:=true;
// uszkodzony silnik (uplywy)
//-if ((FuzzyLogic(abs(Im), Imax * 2, p_elengproblem) || FuzzyLogic(abs(n), nmax * 1.11,
//p_elengproblem)))
//-if (SetFlag(DamageFlag, dtrain_engine))
//- EventFlag = true;
//! dorobic grzanie oporow rozruchowych i silnika
}
return Im;
}
// *************************************************************************************************
// g³ówny konstruktor
// *************************************************************************************************
TMoverParameters::TMoverParameters(double VelInitial, std::string TypeNameInit,
std::string NameInit, int LoadInitial,
std::string LoadTypeInitial,
int Cab) //: T_MoverParameters(VelInitial, TypeNameInit,
//NameInit, LoadInitial, LoadTypeInitial, Cab)
{
int b, k;
WriteLog(
"----------------------------------------------------------------------------------------");
WriteLog("init default physic values for " + NameInit + ", [" + TypeNameInit + "], [" +
LoadTypeInitial + "]");
DimHalf.x = 0.5 * Dim.W; // po³owa szerokoœci, OX jest w bok?
DimHalf.y = 0.5 * Dim.L; // po³owa d³ugoœci, OY jest do przodu?
DimHalf.z = 0.5 * Dim.H; // po³owa wysokoœci, OZ jest w górê?
// BrakeLevelSet(-2); //Pascal ustawia na 0, przestawimy na odciêcie (CHK jest jeszcze nie
// wczytane!)
bPantKurek3 = true; // domyœlnie zbiornik pantografu po³¹czony jest ze zbiornikiem g³ównym
iProblem = 0; // pojazd w pe³ni gotowy do ruchu
iLights[0] = iLights[1] = 0; //œwiat³a zgaszone
// inicjalizacja stalych
dMoveLen = 0;
CategoryFlag = 1;
EngineType = None;
for (b = 0; b < ResArraySize; b++)
{
RList[b].Relay = 0;
RList[b].R = 0;
RList[b].Bn = 0;
RList[b].Mn = 0;
RList[b].AutoSwitch = false;
}
WheelDiameter = 1.0;
BrakeCtrlPosNo = 0;
LightsPosNo = 0;
LightsDefPos = 1;
for (k = -1; k < MainBrakeMaxPos; k++)
{
BrakePressureTable[k].PipePressureVal = 0;
BrakePressureTable[k].BrakePressureVal = 0;
BrakePressureTable[k].FlowSpeedVal = 0;
}
// with BrakePressureTable[-2] do {pozycja odciecia}
{
BrakePressureTable[-2].PipePressureVal = -1;
BrakePressureTable[-2].BrakePressureVal = -1;
BrakePressureTable[-2].FlowSpeedVal = 0;
}
Transmision.Ratio = 1;
NBpA = 0;
DynamicBrakeType = 0;
ASBType = 0;
AutoRelayType = 0;
for (b = 0; b < 1; b++) // Ra: kto tu zrobi³ "for b:=1 to 2 do" ???
{
Couplers[b].CouplerType = NoCoupler;
Couplers[b].SpringKB = 1;
Couplers[b].SpringKC = 1;
Couplers[b].DmaxB = 0.1;
Couplers[b].FmaxB = 1000;
Couplers[b].DmaxC = 0.1;
Couplers[b].FmaxC = 1000;
}
Power = 0;
MaxLoad = 0;
LoadAccepted = "";
LoadSpeed = 0;
UnLoadSpeed = 0;
HeatingPower = 0;
LightPower = 0;
HeatingPowerSource.MaxVoltage = 0;
HeatingPowerSource.MaxCurrent = 0;
HeatingPowerSource.IntR = 0.001;
HeatingPowerSource.SourceType = NotDefined;
HeatingPowerSource.PowerType = NoPower;
HeatingPowerSource.RPowerCable.PowerTrans = NoPower;
AlterHeatPowerSource.MaxVoltage = 0;
AlterHeatPowerSource.MaxCurrent = 0;
AlterHeatPowerSource.IntR = 0.001;
AlterHeatPowerSource.SourceType = NotDefined;
AlterHeatPowerSource.PowerType = NoPower;
AlterHeatPowerSource.RPowerCable.PowerTrans = NoPower;
LightPowerSource.MaxVoltage = 0;
LightPowerSource.MaxCurrent = 0;
LightPowerSource.IntR = 0.001;
LightPowerSource.SourceType = NotDefined;
LightPowerSource.PowerType = NoPower;
LightPowerSource.RPowerCable.PowerTrans = NoPower;
AlterLightPowerSource.MaxVoltage = 0;
AlterLightPowerSource.MaxCurrent = 0;
AlterLightPowerSource.IntR = 0.001;
AlterLightPowerSource.SourceType = NotDefined;
AlterLightPowerSource.PowerType = NoPower;
AlterLightPowerSource.RPowerCable.PowerTrans = NoPower;
TypeName = TypeNameInit;
HighPipePress = 0;
LowPipePress = 0;
DeltaPipePress = 0;
BrakeCylNo = 0;
BrakeCylRadius = 0;
BrakeCylDist = 0;
for (b = 0; b < 3; b++)
BrakeCylMult[b] = 0;
VeselVolume = 0;
BrakeVolume = 0;
RapidMult = 1;
dizel_Mmax = 1;
dizel_nMmax = 1;
dizel_Mnmax = 2;
dizel_nmax = 2;
dizel_nominalfill = 0;
dizel_Mstand = 0;
dizel_nmax_cutoff = 0;
dizel_nmin = 0;
dizel_minVelfullengage = 0;
dizel_AIM = 1;
dizel_engageDia = 0.5;
dizel_engageMaxForce = 6000;
dizel_engagefriction = 0.5;
DoorOpenCtrl = 0;
DoorCloseCtrl = 0;
DoorStayOpen = 0;
DoorClosureWarning = false;
DoorOpenSpeed = 1;
DoorCloseSpeed = 1;
DoorMaxShiftL = 0.5;
DoorMaxShiftR = 0.5;
DoorOpenMethod = 2;
DepartureSignal = false;
InsideConsist = false;
CompressorPower = 1;
SmallCompressorPower = 0;
ScndInMain = false;
Vhyp = 1;
Vadd = 1;
PowerCorRatio = 1;
// inicjalizacja zmiennych}
// Loc:=LocInitial; //Ra: to i tak trzeba potem przesun¹æ, po ustaleniu pozycji na torze
// (potrzebna d³ugoœæ)
// Rot:=RotInitial;
for (b = 0; b < 1; 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;
Couplers[b].Dist = 0;
Couplers[b].CheckCollision = false;
}
ScanCounter = 0;
BrakeCtrlPos = -2; // to nie ma znaczenia, konstruktor w Mover.cpp zmienia na -2
BrakeDelayFlag = 0;
BrakeStatus = b_off;
EmergencyBrakeFlag = false;
MainCtrlPos = 0;
ScndCtrlPos = 0;
MainCtrlActualPos = 0;
ScndCtrlActualPos = 0;
Heating = false;
Mains = false;
ActiveDir = 0; // kierunek nie ustawiony
CabNo = 0; // sterowania nie ma, ustawiana przez CabActivization()
ActiveCab = Cab; // obsada w podanej kabinie
DirAbsolute = 0;
SlippingWheels = false;
SandDose = false;
FuseFlag = false;
ConvOvldFlag = false; // hunter-251211
StLinFlag = false;
ResistorsFlag = false;
RventRot = 0;
enrot = 0;
nrot = 0;
Itot = 0;
EnginePower = 0;
BrakePress = 0;
Compressor = 0;
ConverterFlag = false;
CompressorAllow = false;
DoorLeftOpened = false;
DoorRightOpened = false;
Battery = false;
EpFuse = true;
Signalling = false;
Radio = true;
DoorSignalling = false;
UnBrake = false;
// Winger 160204
PantVolume =
0.48; // aby podniesione pantografy opad³y w krótkim czasie przy wy³¹czonej sprê¿arce
PantFrontUp = false;
PantRearUp = false;
PantFrontStart = 0;
PantRearStart = 0;
PantFrontSP = true;
PantRearSP = true;
DoubleTr = 1;
BrakeSlippingTimer = 0;
dpBrake = 0;
dpPipe = 0;
dpMainValve = 0;
dpLocalValve = 0;
MBPM = 1;
DynamicBrakeFlag = false;
BrakeSystem = Individual;
BrakeSubsystem = ss_None;
Ft = 0;
Ff = 0;
Fb = 0;
FTotal = 0;
FStand = 0;
FTrain = 0;
AccS = 0;
AccN = 0;
AccV = 0;
EventFlag = false;
SoundFlag = 0;
Vel = abs(VelInitial);
V = VelInitial / 3.6;
LastSwitchingTime = 0;
LastRelayTime = 0;
DistCounter = 0;
PulseForce = 0;
PulseForceTimer = 0;
PulseForceCount = 0;
eAngle = 1.5;
dizel_fill = 0;
dizel_engagestate = 0;
dizel_engage = 0;
dizel_automaticgearstatus = 0;
dizel_enginestart = false;
dizel_engagedeltaomega = 0;
PhysicActivation = true;
RunningShape.R = 0;
RunningShape.Len = 1;
RunningShape.dHtrack = 0;
RunningShape.dHrail = 0;
RunningTrack.CategoryFlag = CategoryFlag;
RunningTrack.Width = TrackW;
RunningTrack.friction = Steel2Steel_friction;
RunningTrack.QualityFlag = 20;
RunningTrack.DamageFlag = 0;
RunningTrack.Velmax = 100; // dla uzytku maszynisty w ai_driver}
RunningTraction.TractionVoltage = 0;
RunningTraction.TractionFreq = 0;
RunningTraction.TractionMaxCurrent = 0;
RunningTraction.TractionResistivity = 1;
OffsetTrackH = 0;
OffsetTrackV = 0;
CommandIn.Command = "";
CommandIn.Value1 = 0;
CommandIn.Value2 = 0;
CommandIn.Location.X = 0;
CommandIn.Location.Y = 0;
CommandIn.Location.Z = 0;
// czesciowo stale, czesciowo zmienne}
SecuritySystem.SystemType = 0;
SecuritySystem.AwareDelay = -1;
SecuritySystem.SoundSignalDelay = -1;
SecuritySystem.EmergencyBrakeDelay = -1;
SecuritySystem.Status = 0;
SecuritySystem.SystemTimer = 0;
SecuritySystem.SystemBrakeCATimer = 0;
SecuritySystem.SystemBrakeSHPTimer = 0; // hunter-091012
SecuritySystem.VelocityAllowed = -1;
SecuritySystem.NextVelocityAllowed = -1;
SecuritySystem.RadioStop = false; // domyœlnie nie ma
SecuritySystem.AwareMinSpeed = 0.1 * Vmax;
// ABu 240105:
// CouplerNr[0]:=1;
// CouplerNr[1]:=0;
// TO POTEM TU UAKTYWNIC A WYWALIC Z CHECKPARAM}
//{
// if Pos(LoadTypeInitial,LoadAccepted)>0 then
// begin
//}
LoadType = LoadTypeInitial;
Load = LoadInitial;
LoadStatus = 0;
LastLoadChangeTime = 0;
//{
// end
// else Load:=0;
// }
Name = NameInit;
DerailReason = 0; // Ra: powód wykolejenia
TotalCurrent = 0;
ShuntModeAllow = false;
ShuntMode = false;
};
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);
};
double TMoverParameters::Distance(const vector3 &s1, const vector3 &s2, const vector3 &d1,
const vector3 &d2){
// obliczenie odleg³oœci prostopad³oœcianów o œrodkach (s1) i (s2) i wymiarach (d1) i (d2)
// return 0.0; //bêdzie zg³aszaæ warning - funkcja do usuniêcia, chyba ¿e siê przyda...
};
double TMoverParameters::CouplerDist(int Coupler)
{ // obliczenie odleg³oœci pomiêdzy sprzêgami (kula!)
return Couplers[Coupler].CoupleDist =
Distance(Loc, Couplers[Coupler].Connected->Loc, Dim,
Couplers[Coupler].Connected->Dim); // odleg³oœæ pomiêdzy sprzêgami (kula!)
};
bool TMoverParameters::AttachA(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo,
int CouplingType, bool Forced)
{ //³¹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) // jeœli nie pusty
{
if (ConnectToNr != 2)
Couplers[ConnectNo].ConnectedNr = ConnectToNr; // 2=nic nie pod³¹czone
TCouplerType ct = ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr]
.CouplerType; // typ sprzêgu pod³¹czanego pojazdu
Couplers[ConnectNo].Connected =
ConnectTo; // tak podpi¹æ (do siebie) zawsze mo¿na, najwy¿ej bêdzie wirtualny
CouplerDist(ConnectNo); // przeliczenie odleg³oœci pomiêdzy sprzêgami
if (CouplingType == ctrain_virtual)
return false; // wirtualny wiêcej nic nie robi
if (Forced ? true : ((Couplers[ConnectNo].CoupleDist <= dEpsilon) &&
(Couplers[ConnectNo].CouplerType != NoCoupler) &&
(Couplers[ConnectNo].CouplerType == ct)))
{ // stykaja sie zderzaki i kompatybilne typy sprzegow, chyba ¿e ³¹czenie na starcie
if (Couplers[ConnectNo].CouplingFlag ==
ctrain_virtual) // jeœli wczeœniej nie by³o po³¹czone
{ // ustalenie z której strony rysowaæ sprzêg
Couplers[ConnectNo].Render = true; // tego rysowaæ
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].Render = false; // a tego nie
};
Couplers[ConnectNo].CouplingFlag = CouplingType; // ustawienie typu sprzêgu
// if (CouplingType!=ctrain_virtual) //Ra: wirtualnego nie ³¹czymy zwrotnie!
//{//jeœli ³¹czenie sprzêgiem niewirtualnym, ustawiamy po³¹czenie zwrotne
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag = CouplingType;
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].Connected = this;
ConnectTo->Couplers[Couplers[ConnectNo].ConnectedNr].CoupleDist =
Couplers[ConnectNo].CoupleDist;
return true;
//}
// pod³¹czenie nie uda³o siê - jest wirtualne
}
}
return false; // brak pod³¹czanego pojazdu, zbyt du¿a odleg³oœæ, niezgodny typ sprzêgu, brak
// sprzêgu, brak haka
};
bool TMoverParameters::Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo,
int CouplingType, bool Forced)
{ //³¹czenie do (ConnectNo) pojazdu (ConnectTo) stron¹ (ConnectToNr)
return AttachA(ConnectNo, ConnectToNr, (TMoverParameters *)ConnectTo, CouplingType, Forced);
};
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
// ABu021104: zakomentowane 'and (CouplerType<>Articulated)' w warunku, nie wiem co to bylo, ale
// za to teraz dziala odczepianie... :) }
// if (CouplerType==Articulated) return false; //sprzêg nie do rozpiêcia - mo¿e byæ tylko urwany
// Couplers[ConnectNo].CoupleDist=Distance(Loc,Couplers[ConnectNo].Connected->Loc,Dim,Couplers[ConnectNo].Connected->Dim);
CouplerDist(ConnectNo);
if (Couplers[ConnectNo].CouplerType == Screw ? Couplers[ConnectNo].CoupleDist < 0.0 : true)
return -Couplers[ConnectNo].CouplingFlag; // mo¿na roz³¹czaæ, jeœli dociœniêty
return (Couplers[ConnectNo].CoupleDist > 0.2) ? -Couplers[ConnectNo].CouplingFlag :
Couplers[ConnectNo].CouplingFlag;
};
bool TMoverParameters::Dettach(int ConnectNo)
{ // rozlaczanie
if (!Couplers[ConnectNo].Connected)
return true; // nie ma nic, to odczepiono
// with Couplers[ConnectNo] do
int i = DettachStatus(ConnectNo); // stan sprzêgu
if (i < 0)
{ // gdy scisniete zderzaki, chyba ze zerwany sprzeg (wirtualnego nie odpinamy z drugiej strony)
// Couplers[ConnectNo].Connected=NULL; //lepiej zostawic bo przeciez trzeba kontrolowac
// zderzenia odczepionych
Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag =
0; // pozostaje sprzêg wirtualny
Couplers[ConnectNo].CouplingFlag = 0; // pozostaje sprzêg wirtualny
return true;
}
else if (i > 0)
{ // od³¹czamy wê¿e i resztê, pozostaje sprzêg fizyczny, który wymaga dociœniêcia (z wirtualnym
// nic)
Couplers[ConnectNo].CouplingFlag &= ctrain_coupler;
Couplers[ConnectNo].Connected->Couplers[Couplers[ConnectNo].ConnectedNr].CouplingFlag =
Couplers[ConnectNo].CouplingFlag;
}
return false; // jeszcze nie roz³¹czony
};
void TMoverParameters::SetCoupleDist()
{ // przeliczenie odleg³oœci sprzêgów
if (Couplers[0].Connected)
{
CouplerDist(0);
if (CategoryFlag & 2)
{ // Ra: dla samochodów zderzanie kul to za ma³o
}
}
if (Couplers[1].Connected)
{
CouplerDist(1);
if (CategoryFlag & 2)
{ // Ra: dla samochodów zderzanie kul to za ma³o
}
}
};
bool TMoverParameters::DirectionForward()
{
if ((MainCtrlPosNo > 0) && (ActiveDir < 1) && (MainCtrlPos == 0))
{
++ActiveDir;
DirAbsolute = ActiveDir * CabNo;
if (DirAbsolute)
if (Battery) // jeœli bateria jest ju¿ za³¹czona
BatterySwitch(true); // to w ten oto durny sposób aktywuje siê CA/SHP
SendCtrlToNext("Direction", ActiveDir, CabNo);
return true;
}
else if ((ActiveDir == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT))
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;
BrakeCtrlPosR = 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);
int x = 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 + 2]; // 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æ
};
bool TMoverParameters::IncBrakeLevel()
{ // nowa wersja na u¿ytek AI, false gdy osi¹gniêto pozycjê BrakeCtrlPosNo
return BrakeLevelAdd(1.0);
};
bool TMoverParameters::DecBrakeLevel()
{
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 (abs(ActiveCab + direction) < 2)
{
// if (ActiveCab+direction=0) then LastCab:=ActiveCab;
ActiveCab = ActiveCab + direction;
if ((BrakeSystem == Pneumatic) && (BrakeCtrlPosNo > 0))
{
// if (BrakeHandle==FV4a) //!!!POBIERAÆ WARTOŒÆ Z KLASY ZAWORU!!!
// BrakeLevelSet(-2); //BrakeCtrlPos=-2;
// else if ((BrakeHandle==FVel6)||(BrakeHandle==St113))
// BrakeLevelSet(2);
// else
// BrakeLevelSet(1);
BrakeLevelSet(Handle->GetPos(bh_NP));
LimPipePress = PipePress;
ActFlowSpeed = 0;
}
else
// if (TrainType=dt_EZT) and (BrakeCtrlPosNo>0) then
// BrakeCtrlPos:=5; //z Megapacka
// else
// BrakeLevelSet(0); //BrakeCtrlPos=0;
BrakeLevelSet(Handle->GetPos(bh_NP));
// if not TestFlag(BrakeStatus,b_dmg) then
// BrakeStatus:=b_off; //z Megapacka
MainCtrlPos = 0;
ScndCtrlPos = 0;
// Ra: to poni¿ej jest bez sensu - mo¿na przejœæ nie wy³¹czaj¹c
// if ((EngineType!=DieselEngine)&&(EngineType!=DieselElectric))
//{
// Mains=false;
// CompressorAllow=false;
// ConverterAllow=false;
//}
// ActiveDir=0;
// DirAbsolute=0;
return true;
}
return false;
};
bool TMoverParameters::CurrentSwitch(int direction)
{ // rozruch wysoki (true) albo niski (false)
// Ra: przenios³em z Train.cpp, nie wiem czy ma to sens
if (MaxCurrentSwitch(direction))
{
if (TrainType != dt_EZT)
return (MinCurrentSwitch(direction));
}
if (EngineType == DieselEngine) // dla 2Ls150
if (ShuntModeAllow)
if (ActiveDir == 0) // przed ustawieniem kierunku
ShuntMode = direction;
return false;
};
void TMoverParameters::UpdatePantVolume(double dt)
{ // KURS90 - sprê¿arka pantografów; Ra 2014-07: teraz jest to zbiornik rozrz¹du, chocia¿ to jeszcze
// nie tak
if (EnginePowerSource.SourceType == CurrentCollector) // tylko jeœli pantografuj¹cy
{
// 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 ((TrainType == dt_EZT) ? (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 = EnginePowerSource.CollectorParameters
.MaxPress; // ograniczenie ciœnienia do MaxPress (tylko w pantografach!)
if (PantPress > ScndPipePress)
PantPress = ScndPipePress; // oraz do ScndPipePress
PantVolume = (PantPress + 1) * 0.1; // objêtoœæ, na wypadek odciêcia kurkiem
}
else
{ // zbiornik g³ówny odciêty, mo¿na pompowaæ pantografy
if (PantCompFlag && Battery) // w³¹czona bateria i ma³a sprê¿arka
PantVolume += dt * (TrainType == dt_EZT ? 0.003 : 0.005) *
(2 * 0.45 - ((0.1 / PantVolume / 10) - 0.1)) /
0.45; // nape³nianie zbiornika pantografów
// Ra 2013-12: Niebugoc³aw mówi, ¿e w EZT nabija 1.5 raz wolniej ni¿ jak by³o 0.005
PantPress = (10.0 * PantVolume) - 1.0; // tu by siê przyda³a objêtoœæ zbiornika
}
if (!PantCompFlag && (PantVolume > 0.1))
PantVolume -= dt * 0.0003; // nieszczelnoœci: 0.0003=0.3l/s
if (Mains) // nie wchodziæ w funkcjê bez potrzeby
if (EngineType == ElectricSeriesMotor) // nie dotyczy... czego w³aœciwie?
if (PantPress < EnginePowerSource.CollectorParameters.MinPress)
if ((TrainType & (dt_EZT | dt_ET40 | dt_ET41 | dt_ET42)) ?
(GetTrainsetVoltage() < EnginePowerSource.CollectorParameters.MinV) :
true) // to jest trochê proteza; zasilanie cz³onu mo¿e byæ przez sprzêg
// WN
if (MainSwitch(false))
EventFlag = true; // wywalenie szybkiego z powodu niskiego ciœnienia
if (TrainType != dt_EZT) // w EN57 pompuje siê tylko w silnikowym
// pierwotnie w CHK pantografy mia³y równie¿ rozrz¹dcze EZT
for (int b = 0; b <= 1; ++b)
if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
if (Couplers[b].Connected->PantVolume <
PantVolume) // bo inaczej trzeba w obydwu cz³onach przestawiaæ
Couplers[b].Connected->PantVolume =
PantVolume; // przekazanie ciœnienia do s¹siedniego cz³onu
// czy np. w ET40, ET41, ET42 pantografy cz³onów maj¹ po³¹czenie pneumatyczne?
// Ra 2014-07: raczej nie - najpierw siê za³¹cza jeden cz³on, a potem mo¿na podnieœæ w
// drugim
}
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, sn2, sn3, sn4, sn5; // Ra: zrobiæ z tego amperomierz NN
if ((BatteryVoltage > 0) && (EngineType != DieselEngine) && (EngineType != WheelsDriven) &&
(NominalBatteryVoltage > 0))
{
if ((NominalBatteryVoltage / BatteryVoltage < 1.22) && Battery)
{ // 110V
if (!ConverterFlag)
sn1 = (dt * 2.0); // szybki spadek do ok 90V
else
sn1 = 0;
if (ConverterFlag)
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 (ConverterFlag)
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 != DieselEngine) && (EngineType != 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 if (NominalBatteryVoltage == 0)
BatteryVoltage = 0;
else
BatteryVoltage = 90;
};
/* Ukrotnienie EN57:
1 //uk³ad szeregowy
2 //uk³ad równoleg³y
3 //bocznik 1
4 //bocznik 2
5 //bocznik 3
6 //do przodu
7 //do ty³u
8 //1 przyspieszenie
9 //minus obw. 2 przyspieszenia
10 //jazda na oporach
11 //SHP
12A //podnoszenie pantografu przedniego
12B //podnoszenie pantografu tylnego
13A //opuszczanie pantografu przedniego
13B //opuszczanie wszystkich pantografów
14 //za³¹czenie WS
15 //rozrz¹d (WS, PSR, wa³ ku³akowy)
16 //odblok PN
18 //sygnalizacja przetwornicy g³ównej
19 //luzowanie EP
20 //hamowanie EP
21 //rezerwa** (1900+: zamykanie drzwi prawych)
22 //za³. przetwornicy g³ównej
23 //wy³. przetwornicy g³ównej
24 //za³. przetw. oœwietlenia
25 //wy³. przetwornicy oœwietlenia
26 //sygnalizacja WS
28 //sprê¿arka
29 //ogrzewanie
30 //rezerwa* (1900+: zamykanie drzwi lewych)
31 //otwieranie drzwi prawych
32H //zadzia³anie PN siln. trakcyjnych
33 //sygna³ odjazdu
34 //rezerwa (sygnalizacja poœlizgu)
35 //otwieranie drzwi lewych
ZN //masa
*/
// *****************************************************************************
// Q: 20160714
// *****************************************************************************
double TMoverParameters::LocalBrakeRatio(void)
{
double LBR;
if (LocalBrakePosNo > 0)
LBR = LocalBrakePos / LocalBrakePosNo;
else
LBR = 0;
// if (TestFlag(BrakeStatus, b_antislip))
// LBR = Max0R(LBR, PipeRatio) + 0.4;
return LBR;
}
// *****************************************************************************
// Q: 20160714
// *****************************************************************************
double TMoverParameters::ManualBrakeRatio(void)
{
double MBR;
if (ManualBrakePosNo > 0)
MBR = ManualBrakePos / ManualBrakePosNo;
else
MBR = 0;
return MBR;
}
// *****************************************************************************
// Q: 20160713
// *****************************************************************************
double TMoverParameters::BrakeVP(void)
{
if (BrakeVVolume > 0)
return Volume / (10.0 * BrakeVVolume);
else
return 0;
}
// *****************************************************************************
// Q: 20160713
// *****************************************************************************
double TMoverParameters::RealPipeRatio(void)
{
double rpp;
if (DeltaPipePress > 0)
rpp = (CntrlPipePress - PipePress) / (DeltaPipePress);
else
rpp = 0;
return rpp;
}
// *****************************************************************************
// Q: 20160713
// *****************************************************************************
double TMoverParameters::PipeRatio(void)
{
double pr;
if (DeltaPipePress > 0)
if (false) // SPKS!!
{
if ((3 * 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;
}
// *************************************************************************************************
// Q: 20160716
// *************************************************************************************************
void TMoverParameters::CollisionDetect(int CouplerN, double dt)
{
double CCF, Vprev, VprevC;
bool VirtualCoupling;
CCF = 0;
// with Couplers[CouplerN] do
if (Couplers[CouplerN].Connected != NULL)
{
VirtualCoupling = (Couplers[CouplerN].CouplingFlag == ctrain_virtual);
Vprev = V;
VprevC = Couplers[CouplerN].Connected->V;
switch (CouplerN)
{
case 0:
CCF =
ComputeCollision(
V, Couplers[CouplerN].Connected->V, TotalMass,
Couplers[CouplerN].Connected->TotalMass,
(Couplers[CouplerN].beta +
Couplers[CouplerN].Connected->Couplers[Couplers[CouplerN].ConnectedNr].beta) /
2.0,
VirtualCoupling) /
(dt);
break; // yB: ej ej ej, a po
case 1:
CCF =
ComputeCollision(
Couplers[CouplerN].Connected->V, V, Couplers[CouplerN].Connected->TotalMass,
TotalMass,
(Couplers[CouplerN].beta +
Couplers[CouplerN].Connected->Couplers[Couplers[CouplerN].ConnectedNr].beta) /
2.0,
VirtualCoupling) /
(dt);
break; // czemu tu jest +0.01??
}
AccS = AccS + (V - Vprev) / dt; // korekta przyspieszenia o si³y wynikaj¹ce ze zderzeñ?
Couplers[CouplerN].Connected->AccS =
Couplers[CouplerN].Connected->AccS + (Couplers[CouplerN].Connected->V - VprevC) / dt;
if ((Couplers[CouplerN].Dist > 0) && (!VirtualCoupling))
if (FuzzyLogic(abs(CCF), 5 * (Couplers[CouplerN].FmaxC + 1), p_coupldmg))
{ //! zerwanie sprzegu
if (SetFlag(DamageFlag, dtrain_coupling))
EventFlag = true;
if ((Couplers[CouplerN].CouplingFlag && ctrain_pneumatic > 0))
EmergencyBrakeFlag = true; // hamowanie nagle - zerwanie przewodow hamulcowych
Couplers[CouplerN].CouplingFlag = 0;
switch (CouplerN) // wyzerowanie flag podlaczenia ale ciagle sa wirtualnie polaczone
{
case 0:
Couplers[CouplerN].Connected->Couplers[1].CouplingFlag = 0;
break;
case 1:
Couplers[CouplerN].Connected->Couplers[0].CouplingFlag = 0;
break;
}
}
}
}
double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShape &Shape,
TTrackParam &Track, TTractionParam &ElectricTraction,
const TLocation &NewLoc, TRotation &NewRot)
{
const Vepsilon = 1e-5;
const Aepsilon = 1e-3; // ASBSpeed=0.8;
int b;
double Vprev, AccSprev, d;
// T_MoverParameters::ComputeMovement(dt, dt1, Shape, Track, ElectricTraction, NewLoc, NewRot);
// // najpierw kawalek z funkcji w pliku mover.pas
ClearPendingExceptions; // ma byc
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 (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;
}
Loc = NewLoc;
Rot = NewRot;
NewRot.Rx = 0;
NewRot.Ry = 0;
NewRot.Rz = 0;
if (dL == 0) // oblicz przesuniecie}
{
Vprev = V;
AccSprev = AccS;
// dt:=ActualTime-LastUpdatedTime; //przyrost czasu
// przyspieszenie styczne
AccS = (FTotal / TotalMass + AccSprev) /
2.0; // prawo Newtona ale z wygladzaniem (œrednia z poprzednim)
if (TestFlag(DamageFlag, dtrain_out))
AccS = -Sign(V) * g * 1; // random(0.0, 0.1)
// przyspieszenie normalne
if (abs(Shape.R) > 0.01)
AccN = sqr(V) / Shape.R + g * Shape.dHrail / TrackW; // Q: zamieniam SQR() na sqr()
else
AccN = g * Shape.dHrail / TrackW;
// szarpanie
if (FuzzyLogic((10 + Track.DamageFlag) * Mass * Vel / Vmax, 500000,
p_accn)) // Ra: czemu tu masa bez ³adunku?
AccV = sqrt((1 + Track.DamageFlag) * random(Trunc(50 * Mass / 1000000.0)) * Vel /
(Vmax * (10 + (Track.QualityFlag & 31)))); // TODO: Trunc na floor
else
AccV = AccV / 2.0;
if (AccV > 1.0)
AccN = AccN + (7 - random(2)) * (100.0 + Track.DamageFlag / 2.0) * AccV / 2000.0;
// wykolejanie na luku oraz z braku szyn
if (TestFlag(CategoryFlag, 1))
{
if (FuzzyLogic((AccN / g) * (1 + 0.1 * (Track.DamageFlag && dtrack_freerail)),
TrackW / Dim.H, 1) ||
TestFlag(Track.DamageFlag, dtrack_norail))
if (SetFlag(DamageFlag, dtrain_out))
{
EventFlag = true;
Mains = false;
RunningShape.R = 0;
if (TestFlag(Track.DamageFlag, dtrack_norail))
DerailReason = 1; // Ra: powód wykolejenia: brak szyn
else
DerailReason = 2; // Ra: powód wykolejenia: przewrócony na ³uku
}
// wykolejanie na poszerzeniu toru
if (FuzzyLogic(abs(Track.Width - TrackW), TrackW / 10.0, 1))
if (SetFlag(DamageFlag, dtrain_out))
{
EventFlag = true;
Mains = false;
RunningShape.R = 0;
DerailReason = 3; // Ra: powód wykolejenia: za szeroki tor
}
}
// wykolejanie wkutek niezgodnosci kategorii toru i pojazdu
if (!TestFlag(RunningTrack.CategoryFlag, CategoryFlag))
if (SetFlag(DamageFlag, dtrain_out))
{
EventFlag = true;
Mains = false;
DerailReason = 4; // Ra: powód wykolejenia: nieodpowiednia trajektoria
}
V = V + (3 * AccS - AccSprev) * dt / 2.0; // przyrost predkosci
if (TestFlag(DamageFlag, dtrain_out))
if (Vel < 1)
{
V = 0;
AccS = 0;
}
if ((V * Vprev <= 0) && (abs(FStand) > abs(FTrain))) // tlumienie predkosci przy hamowaniu
{ // zahamowany
V = 0;
// AccS:=0; //Ra 2014-03: ale si³a grawitacji dzia³a, wiêc nie mo¿e byæ zerowe
}
// { dL:=(V+AccS*dt/2)*dt; //przyrost dlugosci czyli
// przesuniecie
dL = (3 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha}
// ale jesli jest kolizja (zas. zach. pedu) to...}
for (b = 0; b < 1; b++)
if (Couplers[b].CheckCollision)
CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!!
} // liczone dL, predkosc i przyspieszenie
if (Power > 1.0) // w rozrz¹dczym nie (jest b³¹d w FIZ!) - Ra 2014-07: teraz we wszystkich
UpdatePantVolume(dt); // Ra 2014-07: obs³uga zbiornika rozrz¹du oraz pantografów
if (EngineType == WheelsDriven)
d = CabNo * dL; // na chwile dla testu
else
d = dL;
DistCounter = DistCounter + fabs(dL) / 1000.0;
dL = 0;
// koniec procedury, tu nastepuja dodatkowe procedury pomocnicze
// sprawdzanie i ewentualnie wykonywanie->kasowanie poleceñ
if (LoadStatus > 0) // czas doliczamy tylko jeœli trwa (roz)³adowanie
LastLoadChangeTime = LastLoadChangeTime + dt; // czas (roz)³adunku
RunInternalCommand();
// automatyczny rozruch
if (EngineType == ElectricSeriesMotor)
if (AutoRelayCheck())
SetFlag(SoundFlag, sound_relay);
if (EngineType == DieselEngine)
if (dizel_Update(dt))
SetFlag(SoundFlag, sound_relay);
// uklady hamulcowe:
if (VeselVolume > 0)
Compressor = CompressedVolume / VeselVolume;
else
{
Compressor = 0;
CompressorFlag = false;
};
ConverterCheck();
if (CompressorSpeed > 0.0) // sprê¿arka musi mieæ jak¹œ niezerow¹ wydajnoœæ
CompressorCheck(dt); //¿eby rozwa¿aæ jej za³¹czenie i pracê
UpdateBrakePressure(dt);
UpdatePipePressure(dt);
UpdateBatteryVoltage(dt);
UpdateScndPipePressure(dt); // druga rurka, youBy
// hamulec antypoœlizgowy - wy³¹czanie
if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) // ASBSpeed=0.8
Hamulec->ASB(0);
// SetFlag(BrakeStatus,-b_antislip);
BrakeSlippingTimer = BrakeSlippingTimer + dt;
// sypanie piasku - wy³¹czone i piasek siê nie koñczy - b³êdy AI
// if AIControllFlag then
// if SandDose then
// if Sand>0 then
// begin
// Sand:=Sand-NPoweredAxles*SandSpeed*dt;
// if Random<dt then SandDose:=false;
// end
// else
// begin
// SandDose:=false;
// Sand:=0;
// end;
// czuwak/SHP
// if (Vel>10) and (not DebugmodeFlag) then
if (!DebugModeFlag)
SecuritySystemCheck(dt1);
return d;
};
double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape,
TTrackParam &Track, const TLocation &NewLoc,
TRotation &NewRot)
{ // trzeba po ma³u przenosiæ tu tê funkcjê
double Vprev, AccSprev, d;
int b;
// T_MoverParameters::FastComputeMovement(dt, Shape, Track, NewLoc, NewRot);
ClearPendingExceptions; // nie bylo
Loc = NewLoc;
Rot = NewRot;
NewRot.Rx = 0;
NewRot.Ry = 0;
NewRot.Rz = 0;
if (dL == 0) // oblicz przesuniecie
{
Vprev = V;
AccSprev = AccS;
// dt =ActualTime-LastUpdatedTime; //przyrost czasu
// przyspieszenie styczne
AccS = (FTotal / TotalMass + AccSprev) /
2.0; // prawo Newtona ale z wygladzaniem (œrednia z poprzednim)
if (TestFlag(DamageFlag, dtrain_out))
AccS = -Sign(V) * g * 1; // * random(0.0, 0.1)
// przyspieszenie normalne}
// if Abs(Shape.R)>0.01 then
// AccN:=SQR(V)/Shape.R+g*Shape.dHrail/TrackW
// else AccN:=g*Shape.dHrail/TrackW;
// szarpanie}
if (FuzzyLogic((10 + Track.DamageFlag) * Mass * Vel / Vmax, 500000, p_accn))
{
AccV = sqrt((1 + Track.DamageFlag) * random(int(floor(50 * Mass / 1000000.0))) * Vel /
(Vmax * (10 + (Track.QualityFlag & 31)))); // Trunc na floor, czy dobrze?
}
else
AccV = AccV / 2.0;
if (AccV > 1.0)
AccN = AccN + (7 - random(2)) * (100.0 + Track.DamageFlag / 2.0) * AccV / 2000.0;
// {wykolejanie na luku oraz z braku szyn}
// if TestFlag(CategoryFlag,1) then
// begin
// if FuzzyLogic((AccN/g)*(1+0.1*(Track.DamageFlag and
// dtrack_freerail)),TrackW/Dim.H,1)
// or TestFlag(Track.DamageFlag,dtrack_norail) then
// if SetFlag(DamageFlag,dtrain_out) then
// begin
// EventFlag:=true;
// MainS:=false;
// RunningShape.R:=0;
// end;
// {wykolejanie na poszerzeniu toru}
// if FuzzyLogic(Abs(Track.Width-TrackW),TrackW/10,1) then
// if SetFlag(DamageFlag,dtrain_out) then
// begin
// EventFlag:=true;
// MainS:=false;
// RunningShape.R:=0;
// end;
// end;
// {wykolejanie wkutek niezgodnosci kategorii toru i pojazdu}
// if not TestFlag(RunningTrack.CategoryFlag,CategoryFlag) then
// if SetFlag(DamageFlag,dtrain_out) then
// begin
// EventFlag:=true;
// MainS:=false;
// end;
V = V + (3.0 * AccS - AccSprev) * dt / 2.0; // przyrost predkosci
if (TestFlag(DamageFlag, dtrain_out))
if (Vel < 1)
{
V = 0;
AccS = 0; // Ra 2014-03: ale si³a grawitacji dzia³a, wiêc nie mo¿e byæ zerowe
}
if ((V * Vprev <= 0) && (abs(FStand) > abs(FTrain))) // tlumienie predkosci przy hamowaniu
{ // zahamowany}
V = 0;
AccS = 0;
}
dL = (3 * V - Vprev) * dt / 2.0; // metoda Adamsa-Bashfortha
// ale jesli jest kolizja (zas. zach. pedu) to...
for (b = 0; b < 1; b++)
if (Couplers[b].CheckCollision)
CollisionDetect(b, dt); // zmienia niejawnie AccS, V !!!
} // liczone dL, predkosc i przyspieszenie
// QQQ
if (Power > 1.0) // w rozrz¹dczym nie (jest b³¹d w FIZ!)
UpdatePantVolume(dt); // Ra 2014-07: obs³uga zbiornika rozrz¹du oraz pantografów
if (EngineType == WheelsDriven)
d = CabNo * dL; // na chwile dla testu
else
d = dL;
DistCounter = DistCounter + fabs(dL) / 1000.0;
dL = 0;
// koniec procedury, tu nastepuja dodatkowe procedury pomocnicze
// sprawdzanie i ewentualnie wykonywanie->kasowanie poleceñ
if (LoadStatus > 0) // czas doliczamy tylko jeœli trwa (roz)³adowanie
LastLoadChangeTime = LastLoadChangeTime + dt; // czas (roz)³adunku
RunInternalCommand();
if (EngineType == DieselEngine)
if (dizel_Update(dt))
SetFlag(SoundFlag, sound_relay);
// uklady hamulcowe:
if (VeselVolume > 0)
Compressor = CompressedVolume / VeselVolume;
else
{
Compressor = 0;
CompressorFlag = false;
};
ConverterCheck();
if (CompressorSpeed > 0.0) // sprê¿arka musi mieæ jak¹œ niezerow¹ wydajnoœæ
CompressorCheck(dt); //¿eby rozwa¿aæ jej za³¹czenie i pracê
UpdateBrakePressure(dt);
UpdatePipePressure(dt);
UpdateScndPipePressure(dt); // druga rurka, youBy
UpdateBatteryVoltage(dt);
// hamulec antyposlizgowy - wy³¹czanie
if ((BrakeSlippingTimer > 0.8) && (ASBType != 128)) // ASBSpeed=0.8
Hamulec->ASB(0);
BrakeSlippingTimer = BrakeSlippingTimer + dt;
return d;
};
double TMoverParameters::ShowEngineRotation(int VehN)
{ // pokazywanie obrotów silnika, równie¿ dwóch dalszych pojazdów (3×SN61)
int b;
switch (VehN)
{ // numer obrotomierza
case 1:
return fabs(enrot);
case 2:
for (b = 0; b <= 1; ++b)
if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
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, ctrain_controll))
if (Couplers[b].Connected->Power > 0.01)
if (TestFlag(Couplers[b].Connected->Couplers[b].CouplingFlag, ctrain_controll))
if (Couplers[b].Connected->Couplers[b].Connected->Power > 0.01)
return fabs(Couplers[b].Connected->Couplers[b].Connected->enrot);
break;
};
return 0.0;
};
void TMoverParameters::ConverterCheck()
{ // sprawdzanie przetwornicy
if (ConverterAllow && Mains)
ConverterFlag = true;
else
ConverterFlag = false;
};
int TMoverParameters::ShowCurrent(int AmpN)
{ // odczyt ampera¿u
switch (EngineType)
{
case ElectricInductionMotor:
switch (AmpN)
{ // do asynchronicznych
case 1:
return WindingRes * Mm / Vadd;
case 2:
return dizel_fill * WindingRes;
default:
return ShowCurrentP(AmpN); // T_MoverParameters::
}
break;
case DieselElectric:
return fabs(Im);
break;
default:
return ShowCurrentP(AmpN); // T_MoverParameters::
}
};
// *************************************************************************************************
// queuedEU
// *************************************************************************************************
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::IncMainCtrl(int CtrlSpeed)
{
bool OK = false;
if ((MainCtrlPosNo > 0) && (CabNo != 0))
{
if (MainCtrlPos < MainCtrlPosNo)
{
if ((TrainType != dt_ET22) ||
((TrainType == dt_ET22) &&
(ScndCtrlPos ==
0))) // w ET22 nie da siê krêciæ nastawnikiem przy w³¹czonym boczniku
switch (EngineType)
{
case None:
case Dumb:
case DieselElectric:
case ElectricInductionMotor:
{
if (((CtrlSpeed == 1) && (TrainType != dt_EZT)) ||
((CtrlSpeed == 1) && (TrainType == dt_EZT) && (ActiveDir != 0)))
{ // w EZT nie da siê za³¹czyæ pozycji bez ustawienia kierunku
MainCtrlPos++;
OK = true;
}
else if (((CtrlSpeed > 1) && (TrainType != dt_EZT)) ||
((CtrlSpeed > 1) && (TrainType == dt_EZT) && (ActiveDir != 0)))
OK = (IncMainCtrl(1) && IncMainCtrl(CtrlSpeed - 1));
break;
};
case ElectricSeriesMotor:
{
if ((CtrlSpeed == 1) && (ActiveDir != 0))
{
MainCtrlPos++;
OK = true;
if (Imax == ImaxHi)
if (RList[MainCtrlPos].Bn > 1)
{
if (TrainType == dt_ET42)
{
MainCtrlPos--;
OK = false;
}
if (MaxCurrentSwitch(false))
SetFlag(
SoundFlag,
sound_relay); // wylaczanie wysokiego rozruchu // Q TODO:
// if (EngineType=ElectricSeriesMotor) and (MainCtrlPos=1)
// then
// MainCtrlActualPos:=1;
//
}
if ((CtrlSpeed == 1) && (ActiveDir == -1) && (RList[MainCtrlPos].Bn > 1) &&
(TrainType != dt_PseudoDiesel))
{ // blokada wejœcia na równoleg³¹ podczas jazdy do ty³u
MainCtrlPos--;
OK = false;
}
//
// if (TrainType == "et40")
// if (Abs(Im) > IminHi)
// {
// MainCtrlPos--; //Blokada nastawnika po przekroczeniu minimalnego pradu
// OK = false;
// }
//}
if (DynamicBrakeFlag)
if (TrainType == dt_ET42)
if (MainCtrlPos > 20)
{
MainCtrlPos--;
OK = false;
}
}
else if ((CtrlSpeed > 1) && (ActiveDir != 0) && (TrainType != dt_ET40))
{ // szybkie przejœcie na bezoporow¹
while ((RList[MainCtrlPos].R > 0) && IncMainCtrl(1))
// OK:=true ; {takie chamskie, potem poprawie} <-Ra: kto mia³ to
// poprawiæ i po co?
if (ActiveDir == -1)
while ((RList[MainCtrlPos].Bn > 1) && IncMainCtrl(1))
MainCtrlPos--;
OK = false;
// if (TrainType=dt_ET40) then
// while Abs (Im)>IminHi do
// dec(MainCtrlPos);
// OK:=false ;
//
if (DynamicBrakeFlag)
if (TrainType == dt_ET42)
while (MainCtrlPos > 20)
MainCtrlPos--;
OK = false;
}
// return OK;
break;
};
case DieselEngine:
{
if (CtrlSpeed == 1)
{
MainCtrlPos++;
OK = true;
if (MainCtrlPos > 0)
CompressorAllow = true;
else
CompressorAllow = false;
}
else if (CtrlSpeed > 1)
{
while (MainCtrlPos < MainCtrlPosNo)
IncMainCtrl(1);
OK = true;
}
break;
};
case WheelsDriven:
{
OK = AddPulseForce(CtrlSpeed);
break;
};
} // switch EngineType of
}
else // MainCtrlPos>=MainCtrlPosNo
if (CoupledCtrl) // wspólny wa³ nastawnika jazdy i bocznikowania
{
if (ScndCtrlPos < ScndCtrlPosNo) // 3<3 -> false
{
ScndCtrlPos++;
OK = true;
}
else
OK = false;
}
if (OK)
{
SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); //???
SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo);
}
}
else // nie ma sterowania
OK = false;
// if OK then LastRelayTime:=0;
// 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;
}
// *****************************************************************************
// Q: 20160710
// *****************************************************************************
bool TMoverParameters::DecMainCtrl(int CtrlSpeed)
{
bool OK = false;
if ((MainCtrlPosNo > 0) && (CabNo != 0))
{
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 None:
case Dumb:
case DieselElectric:
case ElectricInductionMotor:
{
if (((CtrlSpeed == 1) &&
/*(ScndCtrlPos==0) and*/ (EngineType != DieselElectric)) ||
((CtrlSpeed == 1) && (EngineType == DieselElectric)))
{
MainCtrlPos--;
OK = true;
}
else if (CtrlSpeed > 1)
OK = (DecMainCtrl(1) && DecMainCtrl(2)); // CtrlSpeed-1);
break;
}
case 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 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 == WheelsDriven)
OK = AddPulseForce(-CtrlSpeed);
else
OK = false;
if (OK)
{
/*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); // hmmmm...???!!!
/*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo);
}
}
else
OK = false;
// 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;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::IncScndCtrl(int CtrlSpeed)
{
bool OK = false;
if ((MainCtrlPos == 0) && (CabNo != 0) && (TrainType == dt_ET42) && (ScndCtrlPos == 0) &&
(DynamicBrakeFlag))
{
OK = DynamicBrakeSwitch(false);
}
else if ((ScndCtrlPosNo > 0) && (CabNo != 0) &&
!((TrainType == dt_ET42) &&
((Imax == ImaxHi) || ((DynamicBrakeFlag) && (MainCtrlPos > 0)))))
{
// if (RList[MainCtrlPos].R=0) and (MainCtrlPos>0) and (ScndCtrlPos<ScndCtrlPosNo) and
// (not CoupledCtrl) then
if ((ScndCtrlPos < ScndCtrlPosNo) && (!CoupledCtrl) &&
((EngineType != DieselElectric) || (!AutoRelayFlag)))
{
if (CtrlSpeed == 1)
{
ScndCtrlPos++;
}
else if (CtrlSpeed > 1)
{
ScndCtrlPos = ScndCtrlPosNo; // takie chamskie, potem poprawie
}
OK = true;
}
else // nie mozna zmienic
OK = false;
if (OK)
{
/*OK:=*/SendCtrlToNext("MainCtrl", MainCtrlPos, CabNo); //???
/*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo);
}
}
else // nie ma sterowania
OK = false;
// if OK then LastRelayTime:=0;
// hunter-101012: poprawka
if (OK)
if (LastRelayTime > CtrlDelay)
LastRelayTime = 0;
return OK;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::DecScndCtrl(int CtrlSpeed)
{
bool OK = false;
if ((MainCtrlPos == 0) && (CabNo != 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) && (CabNo != 0))
{
if ((ScndCtrlPos > 0) && (!CoupledCtrl) &&
((EngineType != 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, CabNo); //???
/*OK:=*/SendCtrlToNext("ScndCtrl", ScndCtrlPos, CabNo);
}
}
else
OK = false;
// if OK then LastRelayTime:=0;
// hunter-101012: poprawka
if (OK)
if (LastRelayTime > CtrlDownDelay)
LastRelayTime = 0;
return OK;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::CabActivisation(void) // za³¹czenie rozrz¹du
{
bool OK = false;
OK = (CabNo == 0); // numer kabiny, z której jest sterowanie
if (OK)
{
CabNo = ActiveCab; // sterowanie jest z kabiny z obsad¹
DirAbsolute = ActiveDir * CabNo;
SendCtrlToNext("CabActivisation", 1, CabNo);
}
return OK;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::CabDeactivisation(void) // wy³¹czenie rozrz¹du
{
bool OK = false;
OK = (CabNo == ActiveCab); // o ile obsada jest w kabinie ze sterowaniem
if (OK)
{
CabNo = 0;
DirAbsolute = ActiveDir * CabNo;
DepartureSignal = false; // nie buczeæ z nieaktywnej kabiny
SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0!
}
return OK;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::AddPulseForce(int Multipler)
{
bool APF;
if ((EngineType == WheelsDriven) && (EnginePowerSource.SourceType == InternalSource) &&
(EnginePowerSource.PowerType == BioPower))
{
ActiveDir = CabNo;
DirAbsolute = ActiveDir * CabNo;
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;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::SandDoseOn(void)
{
bool SDO;
if (SandCapacity > 0)
{
SDO = true;
if (SandDose)
SandDose = false;
else if (Sand > 0)
SandDose = true;
if (CabNo != 0)
SendCtrlToNext("SandDoseOn", 1, CabNo);
}
else
SDO = false;
return SDO;
}
void TMoverParameters::SSReset(void)
{
SecuritySystem.SystemTimer = 0;
if (TestFlag(SecuritySystem.Status, s_aware))
{
SecuritySystem.SystemBrakeCATimer = 0;
SecuritySystem.SystemSoundCATimer = 0;
SetFlag(SecuritySystem.Status, -s_aware);
SetFlag(SecuritySystem.Status, -s_CAalarm);
SetFlag(SecuritySystem.Status, -s_CAebrake);
// EmergencyBrakeFlag = false; //YB-HN
SecuritySystem.VelocityAllowed = -1;
}
else if (TestFlag(SecuritySystem.Status, s_active))
{
SecuritySystem.SystemBrakeSHPTimer = 0;
SecuritySystem.SystemSoundSHPTimer = 0;
SetFlag(SecuritySystem.Status, -s_active);
SetFlag(SecuritySystem.Status, -s_SHPalarm);
SetFlag(SecuritySystem.Status, -s_SHPebrake);
// EmergencyBrakeFlag = false; //YB-HN
SecuritySystem.VelocityAllowed = -1;
}
}
// *****************************************************************************
// Q: 20160710
// *****************************************************************************
// hunter-091012: rozbicie alarmow, dodanie testu czuwaka
bool TMoverParameters::SecuritySystemReset(void) // zbijanie czuwaka/SHP
{
// zbijanie czuwaka/SHP
bool SSR = false;
// with SecuritySystem do
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0))
{
SSR = true;
if ((TrainType == dt_EZT) ||
(ActiveDir != 0)) // Ra 2014-03: w EZT nie trzeba ustawiaæ kierunku
if (!TestFlag(SecuritySystem.Status, s_CAebrake) ||
!TestFlag(SecuritySystem.Status, s_SHPebrake))
SSReset();
// else
// if EmergencyBrakeSwitch(false) then
// Reset;
}
else
SSR = false;
// SendCtrlToNext('SecurityReset',0,CabNo);
return SSR;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
void TMoverParameters::SecuritySystemCheck(double dt)
{
// Ra: z CA/SHP w EZT jest ten problem, ¿e w rozrz¹dczym nie ma kierunku, a w silnikowym nie ma
// obsady
// poza tym jest zdefiniowany we wszystkich 3 cz³onach EN57
// SecuritySystem SS;
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0) &&
(Battery)) // Ra: EZT ma teraz czuwak w rozrz¹dczym
{
// CA
if (Vel >=
SecuritySystem
.AwareMinSpeed) // domyœlnie predkoœæ wiêksza od 10% Vmax, albo podanej jawnie w FIZ
{
SecuritySystem.SystemTimer = SecuritySystem.SystemTimer + dt;
if (TestFlag(SecuritySystem.SystemType, 1) &&
TestFlag(SecuritySystem.Status, s_aware)) // jeœli œwieci albo miga
SecuritySystem.SystemSoundCATimer = SecuritySystem.SystemSoundCATimer + dt;
if (TestFlag(SecuritySystem.SystemType, 1) &&
TestFlag(SecuritySystem.Status, s_CAalarm)) // jeœli buczy
SecuritySystem.SystemBrakeCATimer = SecuritySystem.SystemBrakeCATimer + dt;
if (TestFlag(SecuritySystem.SystemType, 1))
if ((SecuritySystem.SystemTimer > SecuritySystem.AwareDelay) &&
(SecuritySystem.AwareDelay >= 0)) //-1 blokuje
if (!SetFlag(SecuritySystem.Status, s_aware)) // juz wlaczony sygnal swietlny
if ((SecuritySystem.SystemSoundCATimer > SecuritySystem.SoundSignalDelay) &&
(SecuritySystem.SoundSignalDelay >= 0))
if (!SetFlag(SecuritySystem.Status,
s_CAalarm)) // juz wlaczony sygnal dzwiekowy
if ((SecuritySystem.SystemBrakeCATimer >
SecuritySystem.EmergencyBrakeDelay) &&
(SecuritySystem.EmergencyBrakeDelay >= 0))
SetFlag(SecuritySystem.Status, s_CAebrake);
// SHP
if (TestFlag(SecuritySystem.SystemType, 2) &&
TestFlag(SecuritySystem.Status, s_active)) // jeœli œwieci albo miga
SecuritySystem.SystemSoundSHPTimer = SecuritySystem.SystemSoundSHPTimer + dt;
if (TestFlag(SecuritySystem.SystemType, 2) &&
TestFlag(SecuritySystem.Status, s_SHPalarm)) // jeœli buczy
SecuritySystem.SystemBrakeSHPTimer = SecuritySystem.SystemBrakeSHPTimer + dt;
if (TestFlag(SecuritySystem.SystemType, 2) && TestFlag(SecuritySystem.Status, s_active))
if ((Vel > SecuritySystem.VelocityAllowed) && (SecuritySystem.VelocityAllowed >= 0))
SetFlag(SecuritySystem.Status, s_SHPebrake);
else if (((SecuritySystem.SystemSoundSHPTimer > SecuritySystem.SoundSignalDelay) &&
(SecuritySystem.SoundSignalDelay >= 0)) ||
((Vel > SecuritySystem.NextVelocityAllowed) &&
(SecuritySystem.NextVelocityAllowed >= 0)))
if (!SetFlag(SecuritySystem.Status,
s_SHPalarm)) // juz wlaczony sygnal dzwiekowy}
if ((SecuritySystem.SystemBrakeSHPTimer >
SecuritySystem.EmergencyBrakeDelay) &&
(SecuritySystem.EmergencyBrakeDelay >= 0))
SetFlag(SecuritySystem.Status, s_SHPebrake);
} // else SystemTimer:=0;
// TEST CA
if (TestFlag(SecuritySystem.Status, s_CAtest)) // jeœli œwieci albo miga
SecuritySystem.SystemBrakeCATestTimer = SecuritySystem.SystemBrakeCATestTimer + dt;
if (TestFlag(SecuritySystem.SystemType, 1))
if (TestFlag(SecuritySystem.Status, s_CAtest)) // juz wlaczony sygnal swietlny
if ((SecuritySystem.SystemBrakeCATestTimer > SecuritySystem.EmergencyBrakeDelay) &&
(SecuritySystem.EmergencyBrakeDelay >= 0))
s_CAtestebrake = true;
// wdrazanie hamowania naglego
// if TestFlag(Status,s_SHPebrake) or TestFlag(Status,s_CAebrake) or
// (s_CAtestebrake=true) then
// EmergencyBrakeFlag:=true; //YB-HN
}
else if (!Battery)
{ // wy³¹czenie baterii deaktywuje sprzêt
// SecuritySystem.Status = 0; //deaktywacja czuwaka
}
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::BatterySwitch(bool State)
{
bool BS = false;
// Ra: ukrotnienie za³¹czania baterii jest jak¹œ fikcj¹...
if (Battery != State)
{
Battery = State;
}
if (Battery == true)
SendCtrlToNext("BatterySwitch", 1, CabNo);
else
SendCtrlToNext("BatterySwitch", 0, CabNo);
BS = true;
if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/
SecuritySystem.Status = (SecuritySystem.Status || s_waiting); // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wy³¹czenie czuwaka
return BS;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::EpFuseSwitch(bool State)
{
if (EpFuse != State)
{
EpFuse = State;
return true;
}
else
return false;
// if (EpFuse == true) SendCtrlToNext("EpFuseSwitch", 1, CabNo)
// else SendCtrlToNext("EpFuseSwitch", 0, CabNo);
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::DirectionBackward(void)
{
bool DB = false;
if ((ActiveDir == 1) && (MainCtrlPos == 0) && (TrainType == dt_EZT))
if (MinCurrentSwitch(false))
{
DB = true; //
return DB; // exit; TODO: czy dobrze przetlumaczone?
}
if ((MainCtrlPosNo > 0) && (ActiveDir > -1) && (MainCtrlPos == 0))
{
if (EngineType == WheelsDriven)
CabNo--;
// else
ActiveDir--;
DirAbsolute = ActiveDir * CabNo;
if (DirAbsolute != 0)
if (Battery) // jeœli bateria jest ju¿ za³¹czona
BatterySwitch(true); // to w ten oto durny sposób aktywuje siê CA/SHP
DB = true;
SendCtrlToNext("Direction", ActiveDir, CabNo);
}
else
DB = false;
return DB;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
bool TMoverParameters::AntiSlippingButton(void)
{
bool OK = false;
OK = SandDoseOn();
return (AntiSlippingBrake() || OK);
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::MainSwitch(bool State)
{
bool MS = false;
MS = false; // Ra: przeniesione z koñca
if ((Mains != State) && (MainCtrlPosNo > 0))
{
if ((State == false) ||
((ScndCtrlPos == 0) && (ConvOvldFlag == false) && (LastSwitchingTime > CtrlDelay) &&
!TestFlag(DamageFlag, dtrain_out)))
{
if (Mains) // jeœli by³ za³¹czony
SendCtrlToNext("MainSwitch", int(State),
CabNo); // wys³anie wy³¹czenia do pozosta³ych?
Mains = State;
if (Mains) // jeœli zosta³ za³¹czony
SendCtrlToNext("MainSwitch", int(State),
CabNo); // wyslanie po wlaczeniu albo przed wylaczeniem
MS = true; // wartoϾ zwrotna
LastSwitchingTime = 0;
if ((EngineType == DieselEngine) && Mains)
{
dizel_enginestart = State;
}
// if (State=false) then //jeœli wy³¹czony
// begin
// SetFlag(SoundFlag,sound_relay); //hunter-091012: przeniesione do Train.cpp, zeby sie
// nie zapetlal
// if (SecuritySystem.Status<>12) then
// SecuritySystem.Status:=0; //deaktywacja czuwaka; Ra: a nie bateri¹?
// end
// else
// if (SecuritySystem.Status<>12) then
// SecuritySystem.Status:=s_waiting; //aktywacja czuwaka
}
}
// else MainSwitch:=false;
return MS;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::ConverterSwitch(bool State)
{
bool CS = false; // Ra: normalnie chyba false?
if (ConverterAllow != State)
{
ConverterAllow = State;
CS = true;
if (CompressorPower == 2)
CompressorAllow = ConverterAllow;
}
if (ConverterAllow == true)
SendCtrlToNext("ConverterSwitch", 1, CabNo);
else
SendCtrlToNext("ConverterSwitch", 0, CabNo);
return CS;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::CompressorSwitch(bool State)
{
bool CS = false; // Ra: normalnie chyba tak?
// if State=true then
// if ((CompressorPower=2) and (not ConverterAllow)) then
// State:=false; //yB: to juz niepotrzebne
if ((CompressorAllow != State) && (CompressorPower < 2))
{
CompressorAllow = State;
CS = true;
}
if (CompressorAllow == true)
SendCtrlToNext("CompressorSwitch", 1, CabNo);
else
SendCtrlToNext("CompressorSwitch", 0, CabNo);
return CS;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::IncBrakeLevelOld(void)
{
bool IBLO = false;
if ((BrakeCtrlPosNo > 0) /*and (LocalBrakePos=0)*/)
{
if (BrakeCtrlPos < BrakeCtrlPosNo)
{
BrakeCtrlPos++;
// BrakeCtrlPosR = BrakeCtrlPos;
// youBy: wywalilem to, jak jest EP, to sa przenoszone sygnaly nt. co ma robic, a nie
// poszczegolne pozycje;
// wystarczy spojrzec na Knorra i Oerlikona EP w EN57; mogly ze soba
// wspolapracowac
//{
// if (BrakeSystem==ElectroPneumatic)
// if (BrakePressureActual.BrakeType==ElectroPneumatic)
// {
// BrakeStatus = ord(BrakeCtrlPos > 0);
// SendCtrlToNext("BrakeCtrl", BrakeCtrlPos, CabNo);
// }
// else SendCtrlToNext("BrakeCtrl", -2, CabNo);
// else
// if (!TestFlag(BrakeStatus,b_dmg))
// BrakeStatus = b_on;}
// youBy: EP po nowemu
IBLO = true;
if ((BrakePressureActual.PipePressureVal < 0) &&
(BrakePressureTable[BrakeCtrlPos - 1].PipePressureVal > 0))
LimPipePress = PipePress;
if (BrakeSystem == ElectroPneumatic)
if (BrakeSubsystem != ss_K)
{
if ((BrakeCtrlPos * BrakeCtrlPos) == 1)
{
// SendCtrlToNext('Brake',BrakeCtrlPos,CabNo);
// SetFlag(BrakeStatus,b_epused);
}
else
{
// SendCtrlToNext('Brake',0,CabNo);
// SetFlag(BrakeStatus,-b_epused);
}
}
}
else
{
IBLO = false;
// if (BrakeSystem == Pneumatic)
// EmergencyBrakeSwitch(true);
}
}
else
IBLO = false;
return IBLO;
}
// *****************************************************************************
// Q: 20160711
// *****************************************************************************
bool TMoverParameters::DecBrakeLevelOld(void)
{
bool DBLO = false;
if ((BrakeCtrlPosNo > 0) /*&& (LocalBrakePos == 0)*/)
{
if (BrakeCtrlPos > -1 - int(BrakeHandle == FV4a))
{
BrakeCtrlPos--;
// BrakeCtrlPosR:=BrakeCtrlPos;
if (EmergencyBrakeFlag)
{
EmergencyBrakeFlag = false; //!!!
SendCtrlToNext("Emergency_brake", 0, CabNo);
}
// youBy: wywalilem to, jak jest EP, to sa przenoszone sygnaly nt. co ma robic, a nie
// poszczegolne pozycje;
// wystarczy spojrzec na Knorra i Oerlikona EP w EN57; mogly ze soba
// wspolapracowac
/*
if (BrakeSystem == ElectroPneumatic)
if (BrakePressureActual.BrakeType == ElectroPneumatic)
{
// BrakeStatus =ord(BrakeCtrlPos > 0);
SendCtrlToNext("BrakeCtrl",BrakeCtrlPos,CabNo);
}
else SendCtrlToNext('BrakeCtrl',-2,CabNo);
// else}
// if (not TestFlag(BrakeStatus,b_dmg) and (not
TestFlag(BrakeStatus,b_release))) then
// BrakeStatus:=b_off; {luzowanie jesli dziala oraz nie byl wlaczony
odluzniacz
*/
// youBy: EP po nowemu
DBLO = true;
// if ((BrakePressureTable[BrakeCtrlPos].PipePressureVal<0.0) &&
// (BrakePressureTable[BrakeCtrlPos+1].PipePressureVal > 0))
// LimPipePress:=PipePress;
if (BrakeSystem == ElectroPneumatic)
if (BrakeSubsystem != ss_K)
{
if ((BrakeCtrlPos * BrakeCtrlPos) == 1)
{
// SendCtrlToNext("Brake", BrakeCtrlPos, CabNo);
// SetFlag(BrakeStatus, b_epused);
}
else
{
// SendCtrlToNext("Brake", 0, CabNo);
// SetFlag(BrakeStatus, -b_epused);
}
}
// for b:=0 to 1 do {poprawic to!}
// with Couplers[b] do
// if CouplingFlag and ctrain_controll=ctrain_controll then
// Connected^.BrakeCtrlPos:=BrakeCtrlPos;
//
}
else
DBLO = false;
}
else
DBLO = false;
return DBLO;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::IncLocalBrakeLevel(int CtrlSpeed)
{
bool IBL;
if ((LocalBrakePos < LocalBrakePosNo) /*and (BrakeCtrlPos<1)*/)
{
while ((LocalBrakePos < LocalBrakePosNo) && (CtrlSpeed > 0))
{
LocalBrakePos++;
CtrlSpeed--;
}
IBL = true;
}
else
IBL = false;
UnBrake = true;
return IBL;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::DecLocalBrakeLevel(int CtrlSpeed)
{
bool DBL;
if (LocalBrakePos > 0)
{
while ((CtrlSpeed > 0) && (LocalBrakePos > 0))
{
LocalBrakePos--;
CtrlSpeed--;
}
DBL = true;
}
else
DBL = false;
UnBrake = true;
return DBL;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::IncLocalBrakeLevelFAST(void)
{
bool ILBLF;
if (LocalBrakePos < LocalBrakePosNo)
{
LocalBrakePos = LocalBrakePosNo;
ILBLF = true;
}
else
ILBLF = false;
UnBrake = true;
return ILBLF;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::DecLocalBrakeLevelFAST(void)
{
bool DLBLF;
if (LocalBrakePos > 0)
{
LocalBrakePos = 0;
DLBLF = true;
}
else
DLBLF = false;
UnBrake = true;
return DLBLF;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
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;
return IMBL;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::DecManualBrakeLevel(int CtrlSpeed)
{
bool DMBL;
if (ManualBrakePos > 0)
{
while ((CtrlSpeed > 0) && (ManualBrakePos > 0))
{
ManualBrakePos--;
CtrlSpeed--;
}
DMBL = true;
}
else
DMBL = false;
return DMBL;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::DynamicBrakeSwitch(bool Switch)
{
int b;
bool DBS;
if ((DynamicBrakeType == dbrake_switch) && (MainCtrlPos == 0))
{
DynamicBrakeFlag = Switch;
DBS = true;
for (b = 0; b < 1; b++)
// with Couplers[b] do
if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
Couplers[b].Connected->DynamicBrakeFlag = DynamicBrakeFlag;
// end;
// if (DynamicBrakeType=dbrake_passive) and (TrainType=dt_ET42) then
// begin
// DynamicBrakeFlag:=false;
// DynamicBrakeSwitch:=false;
}
else
DBS = false;
return DBS;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::EmergencyBrakeSwitch(bool Switch)
{
bool EBS;
if ((BrakeSystem != Individual) && (BrakeCtrlPosNo > 0))
{
if ((!EmergencyBrakeFlag) && Switch)
{
EmergencyBrakeFlag = Switch;
EBS = true;
}
else
{
if ((abs(V) < 0.1) &&
(Switch == false)) // odblokowanie hamulca bezpieczenistwa tylko po zatrzymaniu
{
EmergencyBrakeFlag = Switch;
EBS = true;
}
else
EBS = false;
}
}
else
EBS = false; // nie ma hamulca bezpieczenstwa gdy nie ma hamulca zesp.
return EBS;
}
// *************************************************************************************************
// Q: 20160710
// *************************************************************************************************
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;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::BrakeReleaser(int state)
{
bool OK;
Hamulec->Releaser(state);
if (CabNo != 0) // rekurencyjne wys³anie do nastêpnego
OK = SendCtrlToNext("BrakeReleaser", state, CabNo);
return OK;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::SwitchEPBrake(int state)
{
bool OK;
double temp;
OK = false;
if ((BrakeHandle == St113) && (ActiveCab != 0))
{
// if(state > 0)
// temp = (Handle as TSt113).GetCP // TODO: przetlumaczyc
// else
temp = 0;
Hamulec->SetEPS(temp);
SendCtrlToNext("Brake", temp, CabNo);
}
// OK:=SetFlag(BrakeStatus,((2*State-1)*b_epused));
// SendCtrlToNext('Brake',(state*(2*BrakeCtrlPos-1)),CabNo);
return OK;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
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;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::DecBrakePress(double &brake, double PressLimit, double dp)
{
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
return DBP;
}
// *************************************************************************************************
// Q: 20160711
// *************************************************************************************************
bool TMoverParameters::BrakeDelaySwitch(int BDS)
{
bool rBDS;
// if (BrakeCtrlPosNo > 0)
if (Hamulec->SetBDF(BDS))
{
BrakeDelayFlag = BDS;
rBDS = true;
BrakeStatus = (BrakeStatus & 191);
// kopowanie nastawy hamulca do kolejnego czlonu - do przemyœlenia
if (CabNo != 0)
SendCtrlToNext("BrakeDelay", BrakeDelayFlag, CabNo);
}
else
rBDS = false;
return rBDS;
}
// *************************************************************************************************
// Q: 20160712
// *************************************************************************************************
bool TMoverParameters::IncBrakeMult(void)
{
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;
return IBM;
}
// *************************************************************************************************
// Q: 20160712
// *************************************************************************************************
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;
return DBM;
}
// *************************************************************************************************
// Q: 20160712
// *************************************************************************************************
void TMoverParameters::UpdateBrakePressure(double dt)
{
const LBDelay = 5.0; // stala czasowa hamulca
double Rate, Speed, dp, sm;
dpLocalValve = 0;
dpBrake = 0;
BrakePress = Hamulec->GetBCP();
// BrakePress:=(Hamulec as TEst4).ImplsRes.pa;
Volume = Hamulec->GetBRP();
}
// *************************************************************************************************
// Q: 20160712
// *************************************************************************************************
void TMoverParameters::CompressorCheck(double dt)
{
// if (CompressorSpeed>0.0) then //ten warunek zosta³ sprawdzony przy wywo³aniu funkcji
if (VeselVolume > 0)
{
if (MaxCompressor - MinCompressor < 0.0001)
{
// if (Mains && (MainCtrlPos > 1))
if (CompressorAllow && Mains && (MainCtrlPos > 0))
{
if (Compressor < MaxCompressor)
if ((EngineType == DieselElectric) && (CompressorPower > 0))
CompressedVolume = CompressedVolume +
dt * CompressorSpeed * (2 * MaxCompressor - Compressor) /
MaxCompressor * (DElist[MainCtrlPos].RPM /
DElist[MainCtrlPosNo].RPM);
else
{
CompressedVolume =
CompressedVolume +
dt * CompressorSpeed * (2 * MaxCompressor - Compressor) / MaxCompressor;
TotalCurrent =
0.0015 *
Voltage; // tymczasowo tylko obci¹¿enie sprê¿arki, tak z 5A na sprê¿arkê
}
else
{
CompressedVolume = CompressedVolume * 0.8;
SetFlag(SoundFlag, sound_relay);
SetFlag(SoundFlag, sound_loud);
}
}
}
else
{
if (CompressorFlag) // jeœli sprê¿arka za³¹czona
{ // sprawdziæ mo¿liwe warunki wy³¹czenia sprê¿arki
if (CompressorPower == 5) // jeœli zasilanie z s¹siedniego cz³onu
{ // zasilanie sprê¿arki w cz³onie ra z cz³onu silnikowego (sprzêg 1)
if (Couplers[1].Connected != NULL)
CompressorFlag =
(Couplers[1].Connected->CompressorAllow &&
Couplers[1].Connected->ConverterFlag && Couplers[1].Connected->Mains);
else
CompressorFlag = false; // bez tamtego cz³onu nie zadzia³a
}
else if (CompressorPower == 4) // jeœli zasilanie z poprzedniego cz³onu
{ // zasilanie sprê¿arki w cz³onie ra z cz³onu silnikowego (sprzêg 1)
if (Couplers[0].Connected != NULL)
CompressorFlag =
(Couplers[0].Connected->CompressorAllow &&
Couplers[0].Connected->ConverterFlag && Couplers[0].Connected->Mains);
else
CompressorFlag = false; // bez tamtego cz³onu nie zadzia³a
}
else
CompressorFlag = ((CompressorAllow) &&
((ConverterFlag) || (CompressorPower == 0)) && (Mains));
if (Compressor >
MaxCompressor) // wy³¹cznik ciœnieniowy jest niezale¿ny od sposobu zasilania
CompressorFlag = false;
}
else // jeœli nie za³¹czona
if ((Compressor < MinCompressor) &&
(LastSwitchingTime > CtrlDelay)) // jeœli nie za³¹czona, a ciœnienie za ma³e
{ // za³¹czenie przy ma³ym ciœnieniu
if (CompressorPower == 5) // jeœli zasilanie z nastêpnego cz³onu
{ // zasilanie sprê¿arki w cz³onie ra z cz³onu silnikowego (sprzêg 1)
if (Couplers[1].Connected != NULL)
CompressorFlag =
(Couplers[1].Connected->CompressorAllow &&
Couplers[1].Connected->ConverterFlag && Couplers[1].Connected->Mains);
else
CompressorFlag = false; // bez tamtego cz³onu nie zadzia³a
}
else if (CompressorPower == 4) // jeœli zasilanie z poprzedniego cz³onu
{ // zasilanie sprê¿arki w cz³onie ra z cz³onu silnikowego (sprzêg 1)
if (Couplers[0].Connected != NULL)
CompressorFlag =
(Couplers[0].Connected->CompressorAllow &&
Couplers[0].Connected->ConverterFlag && Couplers[0].Connected->Mains);
else
CompressorFlag = false; // bez tamtego cz³onu nie zadzia³a
}
else
CompressorFlag = ((CompressorAllow) &&
((ConverterFlag) || (CompressorPower == 0)) && (Mains));
if (CompressorFlag) // jeœli zosta³a za³¹czona
LastSwitchingTime = 0; // to trzeba ograniczyæ ponowne w³¹czenie
}
// for b:=0 to 1 do //z Megapacka
// with Couplers[b] do
// if TestFlag(CouplingFlag,ctrain_scndpneumatic) then
// Connected.CompressorFlag:=CompressorFlag;
if (CompressorFlag)
if ((EngineType == DieselElectric) && (CompressorPower > 0))
CompressedVolume = CompressedVolume +
dt * CompressorSpeed * (2 * MaxCompressor - Compressor) /
MaxCompressor *
(DElist[MainCtrlPos].RPM / DElist[MainCtrlPosNo].RPM);
else
{
CompressedVolume =
CompressedVolume +
dt * CompressorSpeed * (2 * MaxCompressor - Compressor) / MaxCompressor;
if ((CompressorPower == 5) && (Couplers[1].Connected != NULL))
Couplers[1].Connected->TotalCurrent =
0.0015 * Couplers[1].Connected->Voltage; // tymczasowo tylko obci¹¿enie
// sprê¿arki, tak z 5A na
// sprê¿arkê
else if ((CompressorPower == 4) && (Couplers[0].Connected != NULL))
Couplers[0].Connected->TotalCurrent =
0.0015 * Couplers[0].Connected->Voltage; // tymczasowo tylko obci¹¿enie
// sprê¿arki, tak z 5A na
// sprê¿arkê
else
TotalCurrent =
0.0015 *
Voltage; // tymczasowo tylko obci¹¿enie sprê¿arki, tak z 5A na sprê¿arkê
}
}
}
}
// *************************************************************************************************
// Q: 20160712
// *************************************************************************************************
void TMoverParameters::UpdatePipePressure(double dt)
{
const LBDelay = 100;
const kL = 0.5;
double dV;
TMoverParameters *c; // T_MoverParameters
double temp;
int b;
PipePress = Pipe->P();
// PPP:=PipePress;
dpMainValve = 0;
if ((BrakeCtrlPosNo > 1) && (ActiveCab != 0))
// with BrakePressureTable[BrakeCtrlPos] do
{
dpLocalValve = LocHandle->GetPF(LocalBrakePos / LocalBrakePosNo, Hamulec->GetBCP(),
ScndPipePress, dt, 0);
if ((BrakeHandle == FV4a) &&
((PipePress < 2.75) && ((Hamulec->GetStatus() && b_rls) == 0)) &&
(BrakeSubsystem == ss_LSt) && (TrainType != dt_EZT))
temp = PipePress + 0.00001;
else
temp = ScndPipePress;
Handle->SetReductor(BrakeCtrlPos2);
dpMainValve = Handle->GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress);
if (dpMainValve < 0) // && (PipePressureVal > 0.01) //50
if (Compressor > ScndPipePress)
{
CompressedVolume = CompressedVolume + dpMainValve / 1500;
Pipe2->Flow(dpMainValve / 3);
}
else
Pipe2->Flow(dpMainValve);
}
// if(EmergencyBrakeFlag)and(BrakeCtrlPosNo=0)then //ulepszony hamulec bezp.
if ((EmergencyBrakeFlag) || (TestFlag(SecuritySystem.Status, s_SHPebrake)) ||
(TestFlag(SecuritySystem.Status, s_CAebrake)) ||
(s_CAtestebrake == true)) // ulepszony hamulec bezp.
dpMainValve = dpMainValve / 1 +
PF(0, PipePress, 0.15, 0.25) *
dt; // Q: dodalem 4 paraMETR 0.25 bo wywalalo ze za malo parametrow
// 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
// if (Hamulec is typeid(TWest)) return 0;
switch (BrakeValve)
{
case W:
{
if (BrakeLocHandle != NoHandle)
{
LocBrakePress = LocHandle->GetCP();
//(Hamulec as TWest).SetLBP(LocBrakePress);
static_cast<TWest *>(Hamulec)->SetLBP(LocBrakePress);
}
if (MBPM < 2)
//(Hamulec as TWest).PLC(MaxBrakePress[LoadFlag])
static_cast<TWest *>(Hamulec)->PLC(MaxBrakePress[LoadFlag]);
else
//(Hamulec as TWest).PLC(TotalMass);
static_cast<TWest *>(Hamulec)->PLC(TotalMass);
break;
}
case LSt:
case EStED:
{
LocBrakePress = LocHandle->GetCP();
for (int b = 0; b < 1; 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 = Max0R(Couplers[b].Connected->LocHandle->GetCP(), LocBrakePress);
if ((DynamicBrakeFlag) && (EngineType == ElectricInductionMotor))
{
if (Vel > 10)
LocBrakePress = 0;
else if (Vel > 5)
LocBrakePress = (10 - Vel) / 5 * LocBrakePress;
}
//(Hamulec as TLSt).SetLBP(LocBrakePress);
static_cast<TLSt *>(Hamulec)->SetLBP(LocBrakePress);
break;
}
case CV1_L_TR:
{
LocBrakePress = LocHandle->GetCP();
//(Hamulec as TCV1L_TR).SetLBP(LocBrakePress);
static_cast<TCV1L_TR *>(Hamulec)->SetLBP(LocBrakePress);
break;
}
// EP2: (Hamulec as TEStEP2).PLC(TotalMass);
case ESt3AL2:
case NESt3:
case ESt4:
case ESt3:
{
if (MBPM < 2)
//(Hamulec as TNESt3).PLC(MaxBrakePress[LoadFlag])
static_cast<TNESt3 *>(Hamulec)->PLC(MaxBrakePress[LoadFlag]);
else
//(Hamulec as TNESt3).PLC(TotalMass);
static_cast<TNESt3 *>(Hamulec)->PLC(TotalMass);
LocBrakePress = LocHandle->GetCP();
//(Hamulec as TNESt3).SetLBP(LocBrakePress);
static_cast<TNESt3 *>(Hamulec)->SetLBP(LocBrakePress);
break;
}
case KE:
{
LocBrakePress = LocHandle->GetCP();
//(Hamulec as TKE).SetLBP(LocBrakePress);
static_cast<TKE *>(Hamulec)->SetLBP(LocBrakePress);
if (MBPM < 2)
//(Hamulec as TKE).PLC(MaxBrakePress[LoadFlag])
static_cast<TKE *>(Hamulec)->PLC(MaxBrakePress[LoadFlag]);
else
//(Hamulec as TKE).PLC(TotalMass);
static_cast<TKE *>(Hamulec)->PLC(TotalMass);
break;
}
} // switch
if ((BrakeHandle == FVel6) && (ActiveCab != 0))
{
if ((Battery) && (ActiveDir != 0) &&
(EpFuse)) // tu powinien byc jeszcze bezpiecznik EP i baterie -
// temp = (Handle as TFVel6).GetCP
temp = static_cast<TFVel6 *>(Handle)->GetCP();
else
temp = 0;
Hamulec->SetEPS(temp);
SendCtrlToNext("Brake", temp,
CabNo); // Ra 2014-11: na tym siê wysypuje, ale nie wiem, w jakich warunkach
}
Pipe->Act();
PipePress = Pipe->P();
if ((BrakeStatus & 128) == 128) // jesli hamulec wy³¹czony
temp = 0; // odetnij
else
temp = 1; // po³¹cz
Pipe->Flow(temp * Hamulec->GetPF(temp * PipePress, dt, Vel) + GetDVc(dt));
if (ASBType == 128)
Hamulec->ASB(int(SlippingWheels));
dpPipe = 0;
// yB: jednokrokowe liczenie tego wszystkiego
Pipe->Act();
PipePress = Pipe->P();
dpMainValve = dpMainValve / (100 * dt); // normalizacja po czasie do syczenia;
if (PipePress < -1)
{
PipePress = -1;
Pipe->CreatePress(-1);
Pipe->Act();
}
if (CompressedVolume < 0)
CompressedVolume = 0;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
void TMoverParameters::UpdateScndPipePressure(double dt)
{
const Spz = 0.5067;
// 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_scndpneumatic))
{
c = Couplers[0].Connected; // skrot
dv1 = 0.5 * dt * PF(ScndPipePress, c->ScndPipePress, Spz * 0.75, 0.25);
if (dv1 * dv1 > 0.00000000000001)
c->Physic_ReActivation();
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, 0.25);
if (dv2 * dv2 > 0.00000000000001)
c->Physic_ReActivation();
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, 0.25);
Couplers[0].Connected->Pipe2->Flow(+dV);
Couplers[1].Connected->Pipe2->Flow(-dV);
}
Pipe2->Flow(Hamulec->GetHPFlow(ScndPipePress, dt));
if (((Compressor > ScndPipePress) && (CompressorSpeed > 0.0001)) || (TrainType == dt_EZT))
{
dV = PF(Compressor, ScndPipePress, Spz, 0.25) * dt;
CompressedVolume = CompressedVolume + dV / 1000;
Pipe2->Flow(-dV);
}
Pipe2->Flow(dv1 + dv2);
Pipe2->Act();
ScndPipePress = Pipe2->P();
if (ScndPipePress < -1)
{
ScndPipePress = -1;
Pipe2->CreatePress(-1);
Pipe2->Act();
}
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
double TMoverParameters::GetDVc(double dt)
{
// 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.015 / Spg * Dim.L), 0.25);
if (dv1 * dv1 > 0.00000000000001)
c->Physic_ReActivation();
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.015 / Spg * Dim.L), 0.25);
if (dv2 * dv2 > 0.00000000000001)
c->Physic_ReActivation();
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.25) *
0;
Couplers[0].Connected->Pipe->Flow(+dV);
Couplers[1].Connected->Pipe->Flow(-dV);
}
// suma
return dv2 + dv1;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
void TMoverParameters::ComputeConstans(void)
{
double BearingF, RollF, HideModifier;
double Curvature; // Ra 2014-07: odwrotnoϾ promienia
TotalCurrent = 0; // Ra 2014-04: tu zerowanie, aby EZT mog³o pobieraæ pr¹d innemu cz³onowi
TotalMass = ComputeMass();
TotalMassxg = TotalMass * g; // TotalMass*g
BearingF = 2 * (DamageFlag && dtrain_bearing);
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 = RollF + BearingF / 200.0;
// if (NPoweredAxles > 0)
// RollF = RollF * 1.5; //dodatkowe lozyska silnikow
if (NPoweredAxles > 0) // drobna optymalka
{
RollF = 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) + (Cx * Dim.W * Dim.H);
Curvature = abs(RunningShape.R); // zero oznacza nieskoñczony promieñ
if (Curvature > 0.0)
Curvature = 1.0 / Curvature;
// 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;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
double TMoverParameters::ComputeMass(void)
{
double M;
if (Load > 0)
{ // zak³adamy, ¿e ³adunek jest pisany ma³ymi literami
if (LoadQuantity == "tonns")
M = Load * 1000;
else if (LoadType == "passengers")
M = Load * 80;
else if (LoadType == "luggage")
M = Load * 100;
else if (LoadType == "cars")
M = Load * 800;
else if (LoadType == "containers")
M = Load * 8000;
else if (LoadType == "transformers")
M = Load * 50000;
else
M = Load * 1000;
}
else
M = 0;
// Ra: na razie tak, ale nie wszêdzie masy wiruj¹ce siê wliczaj¹
return Mass + M + Mred;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
void TMoverParameters::ComputeTotalForce(double dt, double dt1, bool FullVer)
{
int b;
if (PhysicActivation)
{
// EventFlag:=false; {jesli cos sie zlego
// wydarzy to ustawiane na true}
// SoundFlag:=0; {jesli ma byc jakis dzwiek
// to zapalany jet odpowiedni bit}
// to powinno byc zerowane na zewnatrz
// juz zoptymalizowane:
FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // si³a oporów ruchu
Vel = abs(V) * 3.6; // prêdkoœæ w km/h
nrot = v2n(); // przeliczenie prêdkoœci liniowej na obrotow¹
if (TestFlag(BrakeMethod, bp_MHS) && (PipePress < 3.0) && (Vel > 45) &&
TestFlag(BrakeDelayFlag, bdelay_M)) // ustawione na sztywno na 3 bar
FStand = FStand + /*(RunningTrack.friction)**/ TrackBrakeForce; // doliczenie hamowania
// hamulcem szynowym
// w charakterystykach jest wartoœæ si³y hamowania zamiast nacisku
// if(FullVer=true) then
// begin //ABu: to dla optymalizacji, bo chyba te rzeczy wystarczy sprawdzac 1 raz na
// klatke?
LastSwitchingTime = LastSwitchingTime + dt1;
if (EngineType == ElectricSeriesMotor)
LastRelayTime = LastRelayTime + dt1;
// end;
if (Mains && /*(abs(CabNo) < 2) &&*/ (EngineType ==
ElectricSeriesMotor)) // potem ulepszyc! pantogtrafy!
{ // Ra 2014-03: uwzglêdnienie kierunku jazdy w napiêciu na silnikach, a powinien byæ
// zdefiniowany nawrotnik
if (CabNo == 0)
Voltage = RunningTraction.TractionVoltage * ActiveDir;
else
Voltage = RunningTraction.TractionVoltage * DirAbsolute; // ActiveDir*CabNo;
} // bo nie dzialalo
else
Voltage = 0;
if (Mains && /*(abs(CabNo) < 2) &&*/ (
EngineType == ElectricInductionMotor)) // potem ulepszyc! pantogtrafy!
Voltage = RunningTraction.TractionVoltage;
// end;
if (Power > 0)
FTrain = TractionForce(dt);
else
FTrain = 0;
Fb = BrakeForce(RunningTrack);
if (Max0R(abs(FTrain), Fb) > TotalMassxg * Adhesive(RunningTrack.friction)) // poslizg
SlippingWheels = true;
if (SlippingWheels)
{
// TrainForce:=TrainForce-Fb;
nrot = ComputeRotatingWheel((FTrain - Fb * Sign(V) - FStand) / NAxles -
Sign(nrot * PI * WheelDiameter - V) *
Adhesive(RunningTrack.friction) * TotalMass,
dt, nrot);
FTrain = Sign(FTrain) * TotalMassxg * Adhesive(RunningTrack.friction);
Fb = Min0R(Fb, TotalMassxg * Adhesive(RunningTrack.friction));
}
// else SlippingWheels:=false;
// FStand:=0;
for (b = 0; b < 1; b++)
if (Couplers[b].Connected != NULL) /*and (Couplers[b].CouplerType<>Bare) and
(Couplers[b].CouplerType<>Articulated)*/
{ // doliczenie si³ z innych pojazdów
Couplers[b].CForce = CouplerForce(b, dt);
FTrain = FTrain + Couplers[b].CForce;
}
else
Couplers[b].CForce = 0;
// FStand:=Fb+FrictionForce(RunningShape.R,RunningTrack.DamageFlag);
FStand = Fb + FStand;
FTrain =
FTrain + TotalMassxg * RunningShape.dHtrack; // doliczenie sk³adowej stycznej grawitacji
//!niejawne przypisanie zmiennej!
FTotal = FTrain - Sign(V) * FStand;
}
// McZapkie-031103: sprawdzanie czy warto liczyc fizyke i inne updaty
// ABu 300105: cos tu mieszalem , dziala teraz troche lepiej, wiec zostawiam
// zakomentowalem PhysicActivationFlag bo cos nie dzialalo i fizyka byla liczona zawsze.
// if (PhysicActivationFlag)
//{
if ((CabNo == 0) && (Vel < 0.0001) && (abs(AccS) < 0.0001) && (TrainType != dt_EZT))
{
if (!PhysicActivation)
{
if (Couplers[0].Connected != NULL)
if ((Couplers[0].Connected->Vel > 0.0001) ||
(abs(Couplers[0].Connected->AccS) > 0.0001))
Physic_ReActivation();
if (Couplers[1].Connected != NULL)
if ((Couplers[1].Connected->Vel > 0.0001) ||
(abs(Couplers[1].Connected->AccS) > 0.0001))
Physic_ReActivation();
}
if (LastSwitchingTime > 5) // 10+Random(100) then
PhysicActivation = false; // zeby nie brac pod uwage braku V po uruchomieniu programu
}
else
PhysicActivation = true;
//};
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
double TMoverParameters::BrakeForce(const TTrackParam &Track)
{
double K, Fb, NBrakeAxles, sm;
// const OerlikonForceFactor=1.5;
K = 0;
if (NPoweredAxles > 0)
NBrakeAxles = NPoweredAxles;
else
NBrakeAxles = NAxles;
switch (LocalBrake)
{
case NoBrake:
K = 0;
case ManualBrake:
K = MaxBrakeForce * ManualBrakeRatio();
case HydraulicBrake:
K = MaxBrakeForce * LocalBrakeRatio();
case PneumaticBrake:
if (Compressor < MaxBrakePress[3])
K = MaxBrakeForce * LocalBrakeRatio() / 2.0;
else
K = 0;
}
if (MBrake == true)
{
K = MaxBrakeForce * ManualBrakeRatio();
}
// 0.03
u = ((BrakePress * P2FTrans) - BrakeCylSpring) * BrakeCylMult[0] - BrakeSlckAdj;
if (u * BrakeRigEff > Ntotal) // histereza na nacisku klockow
Ntotal = u * BrakeRigEff;
else
{
u = (BrakePress * P2FTrans) * BrakeCylMult[0] - BrakeSlckAdj;
if (u * (2 - 1 * BrakeRigEff) < Ntotal) // histereza na nacisku klockow
Ntotal = u * (2 - 1 * BrakeRigEff);
}
if (NBrakeAxles * NBpA > 0)
{
if (Ntotal > 0) // nie luz
K = K + Ntotal; // w kN
K = K * BrakeCylNo / (NBrakeAxles * NBpA); // w kN na os
}
if ((BrakeSystem == Pneumatic) || (BrakeSystem == ElectroPneumatic))
{
u = Hamulec->GetFC(Vel, K);
UnitBrakeForce = u * K * 1000; // sila na jeden klocek w N
}
else
UnitBrakeForce = K * 1000;
if ((NBpA * UnitBrakeForce > TotalMassxg * Adhesive(RunningTrack.friction) / NAxles) &&
(abs(V) > 0.001))
// poslizg
{
// Fb = Adhesive(Track.friction) * Mass * g;
SlippingWheels = true;
}
//{ else
// begin
//{ SlippingWheels:=false;}
// 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 * Max0R(1, NBpA);
// u:=((BrakePress*P2FTrans)-BrakeCylSpring*BrakeCylMult[BCMFlag]/BrakeCylNo-0.83*BrakeSlckAdj/(BrakeCylNo))*BrakeCylNo;
// { end; }
return Fb;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
double TMoverParameters::FrictionForce(double R, int TDamage)
{
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
// *************************************************************************************************
double TMoverParameters::Adhesive(double staticfriction)
{
double adhesive;
// ABu: male przerobki, tylko czy to da jakikolwiek skutek w FPS?
// w kazdym razie zaciemni kod na pewno :)
if (SlippingWheels == false)
{
if (SandDose)
adhesive = (Max0R(staticfriction * (100.0 + Vel) / ((50.0 + Vel) * 11.0), 0.048)) *
(11.0 - 2.0 * Random(0.0, 1.0));
else
adhesive = (staticfriction * (100.0 + Vel) / ((50.0 + Vel) * 10)) *
(11.0 - 2.0 * Random(0.0, 1.0));
}
else
{
if (SandDose)
adhesive = (0.048) * (11 - 2 * Random(0.0, 1.0));
else
adhesive = (staticfriction * 0.02) * (11 - 2 * Random(0.0, 1.0));
}
// WriteLog(FloatToStr(adhesive)); // tutaj jest na poziomie 0.2 - 0.3
return adhesive;
}
// poprawka dla liczenia sil przy ustawieniu przeciwnym obiektow:
/*
double DirPatch(int Coupler1, int Coupler2)
{
if (Coupler1 != Coupler2) return 1;
else return -1;
}
double DirF(int CouplerN)
{
double rDirF;
switch (CouplerN)
{
case 0: return -1; break;
case 1: return 1; break;
default: return 0;
}
// if (CouplerN == 0) return -1;
// else if (CouplerN == 0) return 1;
// else return 0;
}
*/
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
double TMoverParameters::CouplerForce(int CouplerN, double dt)
{
// wyliczenie si³y na sprzêgu
double tempdist, newdist, distDelta, CF, dV, absdV, Fmax, BetaAvg;
int CNext;
const MaxDist = 405.0; // ustawione + 5 m, bo skanujemy do 400 m
const MinDist = 0.5; // ustawione +.5 m, zeby nie rozlaczac przy malych odleglosciach
const MaxCount = 1500;
bool rCF;
CF = 0;
// distDelta:=0; //Ra: value never used
CNext = Couplers[CouplerN].ConnectedNr;
// if (Couplers[CouplerN].CForce == 0) //nie bylo uzgadniane wiec policz
Couplers[CouplerN].CheckCollision = false;
newdist = Couplers[CouplerN].CoupleDist; // odleg³oœæ od sprzêgu s¹siada
// newdist:=Distance(Loc,Connected^.Loc,Dim,Connected^.Dim);
if (CouplerN == 0)
{
// ABu: bylo newdist+10*((...
tempdist = ((Couplers[CouplerN].Connected->dMoveLen *
DirPatch(0, Couplers[CouplerN].ConnectedNr)) -
dMoveLen);
newdist = newdist + 10.0 * tempdist;
// tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu
}
else
{
// ABu: bylo newdist+10*((...
tempdist = ((dMoveLen - (Couplers[CouplerN].Connected->dMoveLen *
DirPatch(1, Couplers[CouplerN].ConnectedNr))));
newdist = newdist + 10.0 * tempdist;
// tempdist:=tempdist+CoupleDist; //ABu: proby szybkiego naprawienia bledu
}
// blablabla
// ABu: proby znalezienia problemu ze zle odbijajacymi sie skladami
//***if (Couplers[CouplerN].CouplingFlag=ctrain_virtual) and (newdist>0) then
if ((Couplers[CouplerN].CouplingFlag == ctrain_virtual) && (Couplers[CouplerN].CoupleDist > 0))
{
CF = 0; // kontrola zderzania sie - OK
ScanCounter++;
if ((newdist > MaxDist) || ((ScanCounter > MaxCount) && (newdist > MinDist)))
//***if (tempdist>MaxDist) or ((ScanCounter>MaxCount)and(tempdist>MinDist)) then
{ // zerwij kontrolnie wirtualny sprzeg
// Connected.Couplers[CNext].Connected:=nil; //Ra: ten pod³¹czony niekoniecznie jest
// wirtualny
Couplers[CouplerN].Connected = NULL;
ScanCounter = random(500); // Q: TODO: cy dobrze przetlumaczone?
// WriteLog(FloatToStr(ScanCounter));
}
}
else
{
if (Couplers[CouplerN].CouplingFlag == ctrain_virtual)
{
BetaAvg = Couplers[CouplerN].beta;
Fmax = (Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB) * CouplerTune;
}
else // usrednij bo wspolny sprzeg
{
BetaAvg =
(Couplers[CouplerN].beta + Couplers[CouplerN].Connected->Couplers[CNext].beta) /
2.0;
Fmax = (Couplers[CouplerN].FmaxC + Couplers[CouplerN].FmaxB +
Couplers[CouplerN].Connected->Couplers[CNext].FmaxC +
Couplers[CouplerN].Connected->Couplers[CNext].FmaxB) *
CouplerTune / 2.0;
}
dV = V - DirPatch(CouplerN, CNext) * Couplers[CouplerN].Connected->V;
absdV = abs(dV);
if ((newdist < -0.001) && (Couplers[CouplerN].Dist >= -0.001) &&
(absdV > 0.010)) // 090503: dzwieki pracy zderzakow
{
if (SetFlag(SoundFlag, sound_bufferclamp))
if (absdV > 0.5)
SetFlag(SoundFlag, sound_loud);
}
else if ((newdist > 0.002) && (Couplers[CouplerN].Dist <= 0.002) &&
(absdV > 0.005)) // 090503: dzwieki pracy sprzegu
{
if (Couplers[CouplerN].CouplingFlag > 0)
if (SetFlag(SoundFlag, sound_couplerstretch))
if (absdV > 0.1)
SetFlag(SoundFlag, sound_loud);
}
distDelta =
abs(newdist) - abs(Couplers[CouplerN].Dist); // McZapkie-191103: poprawka na histereze
Couplers[CouplerN].Dist = newdist;
if (Couplers[CouplerN].Dist > 0)
{
if (distDelta > 0)
CF = (-(Couplers[CouplerN].SpringKC +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKC) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) -
Fmax * dV * BetaAvg;
else
CF = (-(Couplers[CouplerN].SpringKC +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKC) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) * BetaAvg -
Fmax * dV * BetaAvg;
// liczenie sily ze sprezystosci sprzegu
if (Couplers[CouplerN].Dist >
(Couplers[CouplerN].DmaxC +
Couplers[CouplerN].Connected->Couplers[CNext].DmaxC)) // zderzenie
//***if tempdist>(DmaxC+Connected^.Couplers[CNext].DmaxC) then {zderzenie}
Couplers[CouplerN].CheckCollision = true;
}
if (Couplers[CouplerN].Dist < 0)
{
if (distDelta > 0)
CF = (-(Couplers[CouplerN].SpringKB +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKB) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) -
Fmax * dV * BetaAvg;
else
CF = (-(Couplers[CouplerN].SpringKB +
Couplers[CouplerN].Connected->Couplers[CNext].SpringKB) *
Couplers[CouplerN].Dist / 2.0) *
DirF(CouplerN) * BetaAvg -
Fmax * dV * BetaAvg;
// liczenie sily ze sprezystosci zderzaka
if (-Couplers[CouplerN].Dist >
(Couplers[CouplerN].DmaxB +
Couplers[CouplerN].Connected->Couplers[CNext].DmaxB)) // zderzenie
//***if -tempdist>(DmaxB+Connected^.Couplers[CNext].DmaxB)/10 then {zderzenie}
{
Couplers[CouplerN].CheckCollision = true;
if ((Couplers[CouplerN].CouplerType == Automatic) &&
(Couplers[CouplerN].CouplingFlag ==
0)) // sprzeganie wagonow z samoczynnymi sprzegami}
// CouplingFlag:=ctrain_coupler+ctrain_pneumatic+ctrain_controll+ctrain_passenger+ctrain_scndpneumatic;
Couplers[CouplerN].CouplingFlag =
ctrain_coupler + ctrain_pneumatic + ctrain_controll; // EN57
}
}
}
if (Couplers[CouplerN].CouplingFlag != ctrain_virtual)
// uzgadnianie prawa Newtona
Couplers[CouplerN].Connected->Couplers[1 - CouplerN].CForce = -CF;
return CF;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
double TMoverParameters::TractionForce(double dt)
{ // oblicza sile trakcyjna lokomotywy (dla elektrowozu tez calkowity prad)
double PosRatio, dmoment, dtrans, tmp, tmpV;
int i;
Ft = 0;
dtrans = 0;
dmoment = 0;
// tmpV =Abs(nrot * WheelDiameter / 2);
// youBy
if (EngineType == DieselElectric)
{
tmp = DElist[MainCtrlPos].RPM / 60.0;
if ((Heating) && (HeatingPower > 0) && (MainCtrlPosNo > MainCtrlPos))
{
i = MainCtrlPosNo;
while (DElist[i - 2].RPM / 60.0 > tmp)
i = i - 1;
tmp = DElist[i].RPM / 60.0;
}
if (enrot != tmp * int(ConverterFlag))
if (abs(tmp * int(ConverterFlag) - enrot) < 0.001)
enrot = tmp * int(ConverterFlag);
else if ((enrot < DElist[0].RPM * 0.01) && (ConverterFlag))
enrot = enrot + (tmp * int(ConverterFlag) - enrot) * dt / 5.0;
else
enrot = enrot + (tmp * int(ConverterFlag) - enrot) * 1.5 * dt;
}
else if (EngineType != DieselEngine)
enrot = Transmision.Ratio * nrot;
else // dla 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, ActiveDir * 1 * dtrans * nrot, dt); // oblicza tez
// enrot
}
eAngle = eAngle + enrot * dt;
if (eAngle > Pirazy2)
// eAngle = Pirazy2 - eAngle; <- ABu: a nie czasem tak, jak nizej?
eAngle = eAngle - Pirazy2;
// hunter-091012: przeniesione z if ActiveDir<>0 (zeby po zejsciu z kierunku dalej spadala
// predkosc wentylatorow)
if (EngineType == ElectricSeriesMotor)
{
switch (RVentType) // wentylatory rozruchowe}
{
case 1:
{
if (ActiveDir != 0)
RventRot = RventRot + (RVentnmax - RventRot) * RVentSpeed * dt;
else
RventRot = RventRot * (1 - RVentSpeed * dt);
break;
}
case 2:
{
if ((abs(Itot) > RVentMinI) && (RList[MainCtrlActualPos].R > RVentCutOff))
RventRot =
RventRot +
(RVentnmax * abs(Itot) / (ImaxLo * RList[MainCtrlActualPos].Bn) - RventRot) *
RVentSpeed * dt;
else if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag))
RventRot = RventRot + (RVentnmax * Im / ImaxLo - RventRot) * RVentSpeed * dt;
else
{
RventRot = RventRot * (1 - RVentSpeed * dt);
if (RventRot < 0.1)
RventRot = 0;
}
break;
}
break;
}
}
if (ActiveDir != 0)
switch (EngineType)
{
case Dumb:
{
PosRatio = (MainCtrlPos + ScndCtrlPos) / (MainCtrlPosNo + ScndCtrlPosNo + 0.01);
if (Mains && (ActiveDir != 0) && (CabNo != 0))
{
if (Vel > 0.1)
{
Ft = Min0R(1000.0 * Power / abs(V), Ftmax) * PosRatio;
}
else
Ft = Ftmax * PosRatio;
Ft = Ft * DirAbsolute; // ActiveDir*CabNo;
}
else
Ft = 0;
EnginePower = 1000 * Power * PosRatio;
break;
} // Dumb
case WheelsDriven:
{
if (EnginePowerSource.SourceType == InternalSource)
if (EnginePowerSource.PowerType == BioPower)
Ft = Sign(sin(eAngle)) * PulseForce * Transmision.Ratio;
PulseForceTimer = PulseForceTimer + dt;
if (PulseForceTimer > CtrlDelay)
{
PulseForce = 0;
if (PulseForceCount > 0)
PulseForceCount--;
}
EnginePower = Ft * (1 + Vel);
break;
} // WheelsDriven
case ElectricSeriesMotor:
{
// enrot:=Transmision.Ratio*nrot;
// yB: szereg dwoch sekcji w ET42
if ((TrainType == dt_ET42) && (Imax == ImaxHi))
Voltage = Voltage / 2.0;
Mm = Momentum(current(enrot, Voltage)); // oblicza tez prad p/slinik
// double qMm = Momentum(qcurrent(enrot, Voltage)); // Q: funkcja w C++ - porownanie
// poprawnosci
if (TrainType == dt_ET42)
{
if (Imax == ImaxHi)
Voltage = Voltage * 2;
if ((DynamicBrakeFlag) && (abs(Im) > 300)) // przeiesione do mover.cpp
FuseOff();
}
if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag))
{
if (((Vadd + abs(Im)) > 760) || (static_cast<TLSt *>(Hamulec)->GetEDBCP() < 0.25))
{
Vadd = Vadd - 500 * dt;
if (Vadd < 1)
Vadd = 0;
}
else if ((DynamicBrakeFlag) && ((Vadd + abs(Im)) < 740))
{
Vadd = Vadd + 70 * dt;
Vadd = Min0R(Max0R(Vadd, 60), 400);
}
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 (abs(Im) > Imax)
Vhyp = 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
//-if (Mains) then //nie wchodziæ w funkcjê bez potrzeby
//- if (Abs(Voltage)<EnginePowerSource.CollectorParameters.MinV) or
//(Abs(Voltage)>EnginePowerSource.CollectorParameters.MaxV) then
//- if MainSwitch(false) then
//- EventFlag:=true; //wywalanie szybkiego z powodu niew³aœciwego napiêcia
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;
Fw = Mw * 2.0 / WheelDiameter;
Ft = Fw * NPoweredAxles; // sila trakcyjna
break;
}
case DieselEngine:
{
EnginePower = dmoment * enrot;
if (MainCtrlPos > 1)
dmoment =
dmoment -
dizel_Mstand * (0.2 * enrot / nmax); // dodatkowe opory z powodu sprezarki}
Mm = dizel_engage * dmoment;
Mw = Mm * dtrans; // dmoment i dtrans policzone przy okazji enginerotation
Fw = Mw * 2.0 / WheelDiameter;
Ft = Fw * NPoweredAxles; // sila trakcyjna
Ft = Ft * DirAbsolute; // ActiveDir*CabNo;
break;
}
/*
case DieselElectric: //youBy
{
// tmpV:=V*CabNo*ActiveDir;
tmpV =nrot*Pirazy2*0.5*WheelDiameter*DirAbsolute; //*CabNo*ActiveDir;
//jazda manewrowa
if (ShuntMode)
{
Voltage =(SST[MainCtrlPos].Umax * AnPos) + (SST[MainCtrlPos].Umin * (1 -
AnPos));
tmp = (SST[MainCtrlPos].Pmax * AnPos) + (SST[MainCtrlPos].Pmin * (1 - AnPos));
Ft = tmp * 1000.0 / (abs(tmpV)+1.6);
PosRatio = 1;
}
else //jazda ciapongowa
{
tmp = Min0R(DElist[MainCtrlPos].GenPower,Power-HeatingPower*int(Heating));
PosRatio = DElist[MainCtrlPos].GenPower / DElist[MainCtrlPosNo].GenPower;
//stosunek mocy teraz do mocy max
if ((MainCtrlPos>0) && (ConverterFlag))
if (tmpV <
(Vhyp*(Power-HeatingPower*int(Heating))/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
//Ft:=(Ftmax - (Ftmax - (1000.0 * DEList[MainCtrlPosNo].genpower /
(Vhyp+Vadd) / PowerCorRatio)) * (tmpV/Vhyp)) * PosRatio //wersja z Megapacka
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; //ActiveDir * CabNo; //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 = Voltage * Im/1000.0;
if (EnginePower > tmp)
{
EnginePower = tmp*1000.0;
Voltage = EnginePower / Im;
}
if (EnginePower < tmp)
Ft = Ft * EnginePower / tmp;
}
else
{
if (abs(Im) > DElist[MainCtrlPos].Imax)
{ //nie ma nadmiarowego, tylko Imax i zwarcie na pradnicy
Ft = Ft/Im*DElist[MainCtrlPos].Imax;
Im = DElist[MainCtrlPos].Imax;
}
if (Im > 0) //jak pod obciazeniem
if (Flat) //ograniczenie napiecia w pradnicy - plaszczak u gory
Voltage = 1000.0 * tmp / abs(Im);
else //charakterystyka pradnicy obcowzbudnej (elipsa) - twierdzenie
Pitagorasa
{ //sqr() TODO: sqr
Voltage = sqrt(abs(sqrt(DElist[MainCtrlPos].Umax) -
sqrt(DElist[MainCtrlPos].Umax*Im/DElist[MainCtrlPos].Imax)))*(MainCtrlPos-1)+
(1-Im/DElist[MainCtrlPos].Imax)*DElist[MainCtrlPos].Umax*(MainCtrlPosNo-MainCtrlPos);
Voltage = Voltage/(MainCtrlPosNo-1);
Voltage = Min0R(Voltage,(1000.0 * tmp / abs(Im)));
if (Voltage<(Im*0.05)) Voltage = Im*0.05;
}
if ((Voltage > DElist[MainCtrlPos].Umax) || (Im == 0)) //gdy wychodzi za duze
napiecie
Voltage = DElist[MainCtrlPos].Umax * int(ConverterFlag); //albo przy biegu
jalowym (jest cos takiego?)
EnginePower = Voltage * Im / 1000.0;
if ((tmpV > 2) && (EnginePower < tmp))
Ft =Ft*EnginePower/tmp;
}
//--if (Imax>1) and (Im>Imax) then FuseOff; //przeniesione do mover.cpp
if (FuseFlag) Voltage = 0;
//przekazniki bocznikowania, kazdy inny dla kazdej pozycji
if ((MainCtrlPos == 0) || (ShuntMode))
ScndCtrlPos = 0;
else if (AutoRelayFlag)
switch (RelayType)
{
case 0:
{
if (Im <= (MPTRelay[ScndCtrlPos].Iup*PosRatio)) and
(ScndCtrlPos<ScndCtrlPosNo) then
inc(ScndCtrlPos);
if (Im >= (MPTRelay[ScndCtrlPos].Idown*PosRatio)) and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
}
case 1:
{
if (MPTRelay[ScndCtrlPos].Iup<Vel) and (ScndCtrlPos<ScndCtrlPosNo) then
inc(ScndCtrlPos);
if (MPTRelay[ScndCtrlPos].Idown>Vel) and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
}
case 2:
{
if (MPTRelay[ScndCtrlPos].Iup<Vel) and (ScndCtrlPos<ScndCtrlPosNo) and
(EnginePower<(tmp*0.99)) then
inc(ScndCtrlPos);
if (MPTRelay[ScndCtrlPos].Idown<Im) and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
}
case 41:
{
if (MainCtrlPos=MainCtrlPosNo) and (tmpV*3.6>MPTRelay[ScndCtrlPos].Iup)
and (ScndCtrlPos<ScndCtrlPosNo)then
begin inc(ScndCtrlPos); enrot:=enrot*0.73; end;
if (Im>MPTRelay[ScndCtrlPos].Idown)and (ScndCtrlPos>0) then
dec(ScndCtrlPos);
}
case 45:
{
//wzrastanie
if (MainCtrlPos>11) and (ScndCtrlPos<ScndCtrlPosNo) then
if (ScndCtrlPos=0) then
if (MPTRelay[ScndCtrlPos].Iup>Im) then
inc(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos].Iup<Vel) then
inc(ScndCtrlPos);
//malenie
if(ScndCtrlPos>0)and(MainCtrlPos<12)then
if (ScndCtrlPos=ScndCtrlPosNo)then
if (MPTRelay[ScndCtrlPos].Idown<Im)then
dec(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos].Idown>Vel)then
dec(ScndCtrlPos);
if (MainCtrlPos<11)and(ScndCtrlPos>2) then ScndCtrlPos:=2;
if (MainCtrlPos<9)and(ScndCtrlPos>0) then ScndCtrlPos:=0;
}
case 46:
{
//wzrastanie
if (MainCtrlPos>9) and (ScndCtrlPos<ScndCtrlPosNo) then
if (ScndCtrlPos) mod 2 = 0 then
if (MPTRelay[ScndCtrlPos].Iup>Im) then
inc(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos-1].Iup>Im) and (MPTRelay[ScndCtrlPos].Iup<Vel)
then
inc(ScndCtrlPos);
//malenie
if (MainCtrlPos<10) and (ScndCtrlPos>0)then
if (ScndCtrlPos) mod 2 = 0 then
if (MPTRelay[ScndCtrlPos].Idown<Im)then
dec(ScndCtrlPos)
else
else
if (MPTRelay[ScndCtrlPos+1].Idown<Im) and
(MPTRelay[ScndCtrlPos].Idown>Vel)then
dec(ScndCtrlPos);
if (MainCtrlPos<9)and(ScndCtrlPos>2) then ScndCtrlPos:=2;
if (MainCtrlPos<6)and(ScndCtrlPos>0) then ScndCtrlPos:=0;
}
} //switch RelayType
} // DieselElectric
*/
/*
case ElectricInductionMotor:
{
if (Voltage>1800) and (MainS) then
begin
if ((Hamulec as TLSt).GetEDBCP<0.25)and(LocHandle.GetCP<0.25) then
DynamicBrakeFlag:=false
else if ((BrakePress>0.25) and ((Hamulec as TLSt).GetEDBCP>0.25)) or
(LocHandle.GetCP>0.25) then
DynamicBrakeFlag:=true;
if(DynamicBrakeFlag)then
begin
if eimv[eimv_Fmax]*sign(V)*DirAbsolute<-1 then
PosRatio:=-sign(V)*DirAbsolute*eimv[eimv_Fr]/(eimc[eimc_p_Fh]*Max0R((Hamulec
as TLSt).GetEDBCP,LocHandle.GetCP)/MaxBrakePress[0]{dizel_fill})
else
PosRatio:=0;
PosRatio:=round(20*Posratio)/20;
if PosRatio<19.5/20 then PosRatio:=PosRatio*0.9;
(Hamulec as TLSt).SetED(PosRatio);
PosRatio:=-Max0R((Hamulec as
TLSt).GetEDBCP,LocHandle.GetCP)/MaxBrakePress[0]*Max0R(0,Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0])));
tmp:=5;
end
else
begin
PosRatio:=(MainCtrlPos/MainCtrlPosNo);
PosRatio:=1.0*(PosRatio*0+1)*PosRatio;
(Hamulec as TLSt).SetED(0);
if (PosRatio>dizel_fill) then tmp:=1 else tmp:=4; //szybkie malenie, powolne
wzrastanie
end;
if SlippingWheels
then
begin
PosRatio:=0;
tmp:=10;
//--SandDoseOn; // przeniesione do mover.cpp
end;//przeciwposlizg
dizel_fill:=dizel_fill+Max0R(Min0R(PosRatio-dizel_fill,0.1),-0.1)*2*(tmp{2{+4*int(PosRatio<dizel_fill)})*dt;
//wartoœæ zadana/procent czegoœ
if(DynamicBrakeFlag)then tmp:=eimc[eimc_f_Uzh] else tmp:=eimc[eimc_f_Uzmax];
eimv[eimv_Uzsmax]:=Min0R(Voltage-eimc[eimc_f_DU],tmp);
eimv[eimv_fkr]:=eimv[eimv_Uzsmax]/eimc[eimc_f_cfu];
if(DynamicBrakeFlag)then
eimv[eimv_Pmax]:=eimc[eimc_p_Ph]
else
eimv[eimv_Pmax]:=Min0R(eimc[eimc_p_Pmax],0.001*Voltage*(eimc[eimc_p_Imax]-eimc[eimc_f_I0])*Pirazy2*eimc[eimc_s_cim]/eimc[eimc_s_p]/eimc[eimc_s_cfu]);
eimv[eimv_FMAXMAX]:=0.001*SQR(Min0R(eimv[eimv_fkr]/Max0R(abs(enrot)*eimc[eimc_s_p]+eimc[eimc_s_dfmax]*eimv[eimv_ks],eimc[eimc_s_dfmax]),1)*eimc[eimc_f_cfu]/eimc[eimc_s_cfu])*(eimc[eimc_s_dfmax]*eimc[eimc_s_dfic]*eimc[eimc_s_cim])*Transmision.Ratio*NPoweredAxles*2/WheelDiameter;
if(DynamicBrakeFlag)then
// if(Vel>eimc[eimc_p_Vh0])then
eimv[eimv_Fmax]:=-sign(V)*(DirAbsolute)*Min0R(eimc[eimc_p_Ph]*3.6/Vel,-eimc[eimc_p_Fh]*dizel_fill)//*Min0R(1,(Vel-eimc[eimc_p_Vh0])/(eimc[eimc_p_Vh1]-eimc[eimc_p_Vh0]))
// else
// eimv[eimv_Fmax]:=0
else
eimv[eimv_Fmax]:=Min0R(Min0R(3.6*eimv[eimv_Pmax]/Max0R(Vel,1),eimc[eimc_p_F0]-Vel*eimc[eimc_p_a1]),eimv[eimv_FMAXMAX])*dizel_fill;
eimv[eimv_ks]:=eimv[eimv_Fmax]/eimv[eimv_FMAXMAX];
eimv[eimv_df]:=eimv[eimv_ks]*eimc[eimc_s_dfmax];
eimv[eimv_fp]:=DirAbsolute*enrot*eimc[eimc_s_p]+eimv[eimv_df];
//
eimv[eimv_U]:=Max0R(eimv[eimv_Uzsmax],Min0R(eimc[eimc_f_cfu]*eimv[eimv_fp],eimv[eimv_Uzsmax]));
// eimv[eimv_pole]:=eimv[eimv_U]/(eimv[eimv_fp]*eimc[eimc_s_cfu]);
if(abs(eimv[eimv_fp])<=eimv[eimv_fkr])then
eimv[eimv_pole]:=eimc[eimc_f_cfu]/eimc[eimc_s_cfu]
else
eimv[eimv_pole]:=eimv[eimv_Uzsmax]/eimc[eimc_s_cfu]/abs(eimv[eimv_fp]);
eimv[eimv_U]:=eimv[eimv_pole]*eimv[eimv_fp]*eimc[eimc_s_cfu];
eimv[eimv_Ic]:=(eimv[eimv_fp]-DirAbsolute*enrot*eimc[eimc_s_p])*eimc[eimc_s_dfic]*eimv[eimv_pole];
eimv[eimv_If]:=eimv[eimv_Ic]*eimc[eimc_s_icif];
eimv[eimv_M]:=eimv[eimv_pole]*eimv[eimv_Ic]*eimc[eimc_s_cim];
eimv[eimv_Ipoj]:=(eimv[eimv_Ic]*NPoweredAxles*eimv[eimv_U])/(Voltage-eimc[eimc_f_DU])+eimc[eimc_f_I0];
eimv[eimv_Pm]:=ActiveDir*eimv[eimv_M]*NPoweredAxles*enrot*Pirazy2/1000;
eimv[eimv_Pe]:=eimv[eimv_Ipoj]*Voltage/1000;
eimv[eimv_eta]:=eimv[eimv_Pm]/eimv[eimv_Pe];
Im:=eimv[eimv_If];
Itot:=eimv[eimv_Ipoj];
EnginePower:=Abs(eimv[eimv_Ic]*eimv[eimv_U]*NPoweredAxles)/1000;
tmpV:=eimv[eimv_fp];
if (abs(eimv[eimv_If])>1) or (abs(tmpV)>0.1) then
begin
if abs(tmpV)<32 then RventRot:=1.0 else
if abs(tmpV)<39 then RventRot:=0.33*abs(tmpV)/32 else
RventRot:=0.25*abs(tmpV)/39;//}
end
else RVentRot:=0;
Mm:=eimv[eimv_M]*DirAbsolute;
Mw:=Mm*Transmision.Ratio;
Fw:=Mw*2.0/WheelDiameter;
Ft:=Fw*NPoweredAxles;
eimv[eimv_Fr]:=DirAbsolute*Ft/1000;
// RventRot;
end
else
begin
Im:=0;Mm:=0;Mw:=0;Fw:=0;Ft:=0;Itot:=0;dizel_fill:=0;EnginePower:=0;
(Hamulec as TLSt).SetED(0);RventRot:=0.0;
end;
} // ElectricInductionMotor
*/
// None: begin end;
} // case EngineType
return Ft;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
double TMoverParameters::ComputeRotatingWheel(double WForce, double dt, double n)
{
double newn, eps;
bool CRW;
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;
}
CRW = newn;
return CRW;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::FuseFlagCheck(void)
{
int b;
bool FFC;
FFC = false;
if (Power > 0.01)
FFC = FuseFlag;
// Q: TODO: zakomentowalem bo nie widzi funkcji
//- else //pobor pradu jezeli niema mocy
//- for (b=0; b < 1; b++)
//- if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
//- if (Couplers[b].Connected->Power > 0.01)
//- FFC = Couplers[b].Connected->FuseFlagCheck();
return FFC;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::FuseOn(void)
{
bool FO = false;
if ((MainCtrlPos == 0) && (ScndCtrlPos == 0) && (TrainType != dt_ET40) && Mains)
{ // w ET40 jest blokada nastawnika, ale czy dzia³a dobrze?
SendCtrlToNext("FuseSwitch", 1, CabNo);
if (((EngineType == ElectricSeriesMotor) || ((EngineType == DieselElectric))) && FuseFlag)
{
FuseFlag = false; // wlaczenie ponowne obwodu
FO = true;
SetFlag(SoundFlag, sound_relay);
SetFlag(SoundFlag, sound_loud);
}
}
return FO;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
void TMoverParameters::FuseOff(void)
{
if (!FuseFlag)
{
FuseFlag = true;
EventFlag = true;
SetFlag(SoundFlag, sound_relay);
SetFlag(SoundFlag, sound_loud);
}
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
double TMoverParameters::v2n(void)
{
// przelicza predkosc liniowa na obrotowa
const dmgn = 0.5;
double n, deltan;
n = V / (PI * WheelDiameter); // predkosc obrotowa wynikajaca z liniowej [obr/s]
deltan = n - nrot; //"pochodna" prêdkoœci obrotowej
if (SlippingWheels)
if (abs(deltan) < 0.01)
SlippingWheels = false; // wygaszenie poslizgu
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;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
double TMoverParameters::Momentum(double I)
{
// liczy moment sily wytwarzany przez silnik elektryczny}
int SP;
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));
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
double TMoverParameters::MomentumF(double I, double Iw, int SCP)
{
// umozliwia dokladne sterowanie wzbudzeniem
return (MotorParam[SCP].mfi * I *
Max0R(abs(Iw) / (abs(Iw) + MotorParam[SCP].mIsat) - MotorParam[SCP].mfi0, 0));
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::CutOffEngine(void)
{
bool COE = false; // Ra: wartoœæ domyœlna, sprawdziæ to trzeba
if ((NPoweredAxles > 0) && (CabNo == 0) && (EngineType == ElectricSeriesMotor))
{
if (SetFlag(DamageFlag, -dtrain_engine))
{
NPoweredAxles = NPoweredAxles / 2; // bylo div czyli mod?
COE = true;
}
}
return COE;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::MaxCurrentSwitch(bool State)
{
bool MCS = false;
if (EngineType == ElectricSeriesMotor)
if (ImaxHi > ImaxLo)
{
if (State && (Imax == ImaxLo) && (RList[MainCtrlPos].Bn < 2) &&
!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
{
Imax = ImaxHi;
MCS = true;
if (CabNo != 0)
SendCtrlToNext("MaxCurrentSwitch", 1, CabNo);
}
if (!State)
if (Imax == ImaxHi)
if (!((TrainType == dt_ET42) && (MainCtrlPos > 0)))
{
Imax = ImaxLo;
MCS = true;
if (CabNo != 0)
SendCtrlToNext("MaxCurrentSwitch", 0, CabNo);
}
}
return MCS;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::MinCurrentSwitch(bool State)
{
bool MCS = false;
if (((EngineType == ElectricSeriesMotor) && (IminHi > IminLo)) || (TrainType == dt_EZT))
{
if (State && (Imin == IminLo))
{
Imin = IminHi;
MCS = true;
if (CabNo != 0)
SendCtrlToNext("MinCurrentSwitch", 1, CabNo);
}
if ((!State) && (Imin == IminHi))
{
Imin = IminLo;
MCS = true;
if (CabNo != 0)
SendCtrlToNext("MinCurrentSwitch", 0, CabNo);
}
}
return MCS;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::ResistorsFlagCheck(void)
{
int b;
bool RFC = false;
if (Power > 0.01)
RFC = ResistorsFlag;
// Q: TODO: zakomentowalem bo nie widzi funkcji, do czasu przenesienia TCoupling do mover.h
else // pobor pradu jezeli niema mocy
RFC = false; // po przeniesieniu usunac te linie
//- for (b=0; b<1; b++)
//- if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
//- if (Couplers[b].Connected->Power > 0.01)
//- RFC = Couplers[b].Connected->ResistorsFlagCheck();
return RFC;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::AutoRelaySwitch(bool State)
{
bool ARS;
if ((AutoRelayType == 2) && (AutoRelayFlag != State))
{
AutoRelayFlag = State;
ARS = true;
SendCtrlToNext("AutoRelaySwitch", int(State), CabNo);
}
else
ARS = false;
return ARS;
}
// *************************************************************************************************
// Q: 20160724
// *************************************************************************************************
bool TMoverParameters::AutoRelayCheck(void)
{
bool OK; // b:int;
bool ARFASI, ARFASI2; // sprawdzenie wszystkich warunkow (AutoRelayFlag, AutoSwitch, Im<Imin)
bool ARC;
// Ra 2014-06: dla SN61 nie dzia³a prawid³owo
// rozlaczanie stycznikow liniowych
if ((!Mains) || (FuseFlag) || (MainCtrlPos == 0) || (BrakePress > 2.1) ||
(ActiveDir == 0)) // hunter-111211: wylacznik cisnieniowy
{
StLinFlag = false; // yBARC - rozlaczenie stycznikow liniowych
OK = false;
if (!DynamicBrakeFlag)
{
Im = 0;
Itot = 0;
ResistorsFlag = false;
}
}
ARFASI2 = ((!AutoRelayFlag) || ((MotorParam[ScndCtrlActualPos].AutoSwitch) &&
(abs(Im) < Imin))); // wszystkie warunki w jednym
ARFASI = ((!AutoRelayFlag) || ((RList[MainCtrlActualPos].AutoSwitch) && (abs(Im) < Imin)) ||
((!RList[MainCtrlActualPos].AutoSwitch) &&
(RList[MainCtrlActualPos].Relay < MainCtrlPos))); // wszystkie warunki w jednym
// brak PSR na tej pozycji dzia³a PSR i pr¹d poni¿ej progu
// na tej pozycji nie dzia³a PSR i pozycja walu ponizej
// chodzi w tym wszystkim o to, ¿eby mo¿na by³o zatrzymaæ rozruch na
// jakiejœ pozycji wpisuj¹c Autoswitch=0 i wymuszaæ
// przejœcie dalej przez danie nastawnika na dalsz¹ pozycjê - tak to do
// tej pory dzia³a³o i na tym siê opiera fizyka ET22-2k
{
if (StLinFlag)
{
if ((RList[MainCtrlActualPos].R == 0) &&
((ScndCtrlActualPos > 0) || (ScndCtrlPos > 0)) &&
(!(CoupledCtrl) || (RList[MainCtrlActualPos].Relay == MainCtrlPos)))
{ // zmieniaj scndctrlactualpos
//{ //scnd bez samoczynnego rozruchu
if (ScndCtrlActualPos < ScndCtrlPos)
{
if ((LastRelayTime > CtrlDelay) && (ARFASI2))
{
ScndCtrlActualPos++;
OK = true;
}
}
else if (ScndCtrlActualPos > ScndCtrlPos)
{
if ((LastRelayTime > CtrlDownDelay) && (TrainType != dt_EZT))
{
ScndCtrlActualPos--;
OK = true;
}
}
else
OK = false;
// }
}
else
{ // zmieniaj mainctrlactualpos
if ((ActiveDir < 0) && (TrainType != dt_PseudoDiesel))
if (RList[MainCtrlActualPos + 1].Bn > 1)
{
OK = false;
// return ARC;// bbylo exit; //Ra: to powoduje, ¿e EN57 nie wy³¹cza siê przy
// IminLo
}
{ // main bez samoczynnego rozruchu
if ((RList[MainCtrlActualPos].Relay < MainCtrlPos) ||
(RList[MainCtrlActualPos + 1].Relay == MainCtrlPos) ||
((TrainType == dt_ET22) && (DelayCtrlFlag)))
{
if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) &&
(!(MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1))
{
MainCtrlActualPos++;
// MainCtrlActualPos:=MainCtrlPos; //hunter-111012:
// szybkie wchodzenie na bezoporowa (303E)
OK = true;
SetFlag(SoundFlag, sound_manyrelay);
SetFlag(SoundFlag, sound_loud);
}
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_manyrelay);
SetFlag(SoundFlag, sound_loud);
}
else if ((RList[MainCtrlActualPos].R > 0) &&
(RList[MainCtrlActualPos - 1].R ==
0)) // wejscie na drugi uklad
{
SetFlag(SoundFlag, sound_manyrelay);
}
}
}
else if (RList[MainCtrlActualPos].Relay > MainCtrlPos)
{
if ((RList[MainCtrlPos].R == 0) && (MainCtrlPos > 0) &&
(!(MainCtrlPos == MainCtrlPosNo)) && (FastSerialCircuit == 1))
{
MainCtrlActualPos--;
// MainCtrlActualPos:=MainCtrlPos; //hunter-111012:
// szybkie wchodzenie na bezoporowa (303E)
OK = true;
SetFlag(SoundFlag, sound_manyrelay);
}
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_manyrelay);
}
}
}
else if ((RList[MainCtrlActualPos].R > 0) && (ScndCtrlActualPos > 0))
{
if (LastRelayTime > CtrlDownDelay)
{
ScndCtrlActualPos--; // boczniki nie dzialaja na poz. oporowych
OK = true;
}
}
else
OK = false;
}
}
}
else // not StLinFlag
{
OK = false;
// ybARC - tutaj sa wszystkie warunki, jakie musza byc spelnione, zeby mozna byla
// zalaczyc styczniki liniowe
if (((MainCtrlPos == 1) || ((TrainType == dt_EZT) && (MainCtrlPos > 0))) &&
(!FuseFlag) && (Mains) && /*(BrakePress < 1.0) &&*/ (MainCtrlActualPos == 0) &&
(ActiveDir != 0))
{ //^^ TODO: sprawdzic BUG, prawdopodobnie w CreateBrakeSys()
DelayCtrlFlag = true;
if (LastRelayTime >= InitialCtrlDelay)
{
StLinFlag = true; // ybARC - zalaczenie stycznikow liniowych
MainCtrlActualPos = 1;
DelayCtrlFlag = false;
SetFlag(SoundFlag, sound_relay);
SetFlag(SoundFlag, sound_loud);
OK = true;
}
}
else
DelayCtrlFlag = false;
if ((!StLinFlag) && ((MainCtrlActualPos > 0) || (ScndCtrlActualPos > 0)))
if ((TrainType == dt_EZT) && (CoupledCtrl)) // EN57 wal jednokierunkowy calosciowy
{
if (MainCtrlActualPos == 1)
{
MainCtrlActualPos = 0;
OK = true;
}
else if (LastRelayTime > CtrlDownDelay)
{
if (MainCtrlActualPos < RlistSize)
MainCtrlActualPos++; // dojdz do konca
else if (ScndCtrlActualPos < ScndCtrlPosNo)
ScndCtrlActualPos++; // potem boki
else
{ // i sie przewroc na koniec
MainCtrlActualPos = 0;
ScndCtrlActualPos = 0;
}
OK = true;
}
}
else if (CoupledCtrl) // wal kulakowy dwukierunkowy
{
if (LastRelayTime > CtrlDownDelay)
{
if (ScndCtrlActualPos > 0)
ScndCtrlActualPos--;
else
MainCtrlActualPos--;
OK = true;
}
}
else
{
MainCtrlActualPos = 0;
ScndCtrlActualPos = 0;
OK = true;
}
}
if (OK)
LastRelayTime = 0;
return OK;
}
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::PantFront(bool State)
{
double pf1;
bool PF;
if ((Battery ==
true) /* and ((TrainType<>dt_ET40)or ((TrainType=dt_ET40) and (EnginePowerSource.CollectorsNo>1)))*/)
{
PF = true;
if (State == true)
pf1 = 1;
else
pf1 = 0;
if (PantFrontUp != State)
{
PantFrontUp = State;
if (State == true)
{
PantFrontStart = 0;
SendCtrlToNext("PantFront", 1, CabNo);
}
else
{
PF = false;
PantFrontStart = 1;
SendCtrlToNext("PantFront", 0, CabNo);
//{Ra: nie ma potrzeby opuszczaæ obydwu na raz, jak mozemy ka¿dy osobno
// if (TrainType == dt_EZT) && (ActiveCab == 1)
// {
// PantRearUp = false;
// PantRearStart = 1;
// SendCtrlToNext("PantRear", 0, CabNo);
// }
//}
}
}
else
SendCtrlToNext("PantFront", pf1, CabNo);
}
return PF;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::PantRear(bool State)
{
double pf1;
bool PR;
if (Battery == true)
{
PR = true;
if (State == true)
pf1 = 1;
else
pf1 = 0;
if (PantRearUp != State)
{
PantRearUp = State;
if (State == true)
{
PantRearStart = 0;
SendCtrlToNext("PantRear", 1, CabNo);
}
else
{
PR = false;
PantRearStart = 1;
SendCtrlToNext("PantRear", 0, CabNo);
}
}
else
SendCtrlToNext("PantRear", pf1, CabNo);
}
return PR;
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
bool TMoverParameters::dizel_EngageSwitch(double state)
{
if ((EngineType == DieselEngine) && (state <= 1) && (state >= 0) &&
(state != dizel_engagestate))
{
dizel_engagestate = state;
return true;
}
else
return false;
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
bool TMoverParameters::dizel_EngageChange(double dt)
{
// zmienia parametr do ktorego dazy sprzeglo
const engagedownspeed = 0.9;
const engageupspeed = 0.5;
double engagespeed; // 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;
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
bool TMoverParameters::dizel_AutoGearCheck(void)
{
bool OK;
OK = false;
if (MotorParam[ScndCtrlActualPos].AutoSwitch && Mains)
{
if (RList[MainCtrlPos].Mn == 0)
{
if (dizel_engagestate > 0)
dizel_EngageSwitch(0);
if ((MainCtrlPos == 0) && (ScndCtrlActualPos > 0))
dizel_automaticgearstatus = -1;
}
else
{
if (MotorParam[ScndCtrlActualPos].AutoSwitch &&
(dizel_automaticgearstatus == 0)) // sprawdz czy zmienic biegi
{
if ((Vel > MotorParam[ScndCtrlActualPos].mfi) &&
(ScndCtrlActualPos < ScndCtrlPosNo))
{
dizel_automaticgearstatus = 1;
OK = true;
}
else if ((Vel < MotorParam[ScndCtrlActualPos].fi) && (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 (dizel_automaticgearstatus == 0) // ustaw cisnienie w silowniku sprzegla}
switch (RList[MainCtrlPos].Mn)
{
case 1:
dizel_EngageSwitch(0.5);
case 2:
dizel_EngageSwitch(1.0);
default:
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;
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
bool TMoverParameters::dizel_Update(double dt)
{ // odœwie¿a informacje o silniku
const fillspeed = 2;
bool DU;
// dizel_Update:=false;
if (dizel_enginestart && (LastSwitchingTime >= InitialCtrlDelay))
{
dizel_enginestart = false;
LastSwitchingTime = 0;
enrot = dizel_nmin / 2.0; // TODO: dac zaleznie od temperatury i baterii
}
/*OK=*/dizel_EngageChange(dt);
// if AutoRelayFlag then Poprawka na SM03
DU = dizel_AutoGearCheck();
// dizel_fill:=(dizel_fill+dizel_fillcheck(MainCtrlPos))/2;
dizel_fill = dizel_fill + fillspeed * dt * (dizel_fillcheck(MainCtrlPos) - dizel_fill);
// dizel_Update:=OK;
return DU;
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
double TMoverParameters::dizel_fillcheck(int mcp)
{ // oblicza napelnienie, uzwglednia regulator obrotow
double realfill, nreg;
realfill = 0;
nreg = 0;
if (Mains && (MainCtrlPosNo > 0))
{
if (dizel_enginestart &&
(LastSwitchingTime >= 0.9 * InitialCtrlDelay)) // wzbogacenie przy rozruchu
realfill = 1;
else
realfill = RList[mcp].R; // napelnienie zalezne od MainCtrlPos
if (dizel_nmax_cutoff > 0)
{
switch (RList[MainCtrlPos].Mn)
{
case 0:
case 1:
nreg = dizel_nmin;
case 2:
if (dizel_automaticgearstatus == 0)
nreg = dizel_nmax;
else
nreg = dizel_nmin;
default:
realfill = 0; // sluczaj
}
if (enrot > nreg)
realfill = realfill * (3.9 - 3.0 * abs(enrot) / nreg);
if (enrot > dizel_nmax_cutoff)
realfill = realfill * (9.8 - 9.0 * abs(enrot) / dizel_nmax_cutoff);
if (enrot < dizel_nmin)
realfill = realfill * (1 + (dizel_nmin - abs(enrot)) / dizel_nmin);
}
}
if (realfill < 0)
realfill = 0;
if (realfill > 1)
realfill = 1;
return realfill;
}
// *************************************************************************************************
// Q: 20160715
// *************************************************************************************************
double TMoverParameters::dizel_Momentum(double dizel_fill, double n, double dt)
{ // liczy moment sily wytwarzany przez silnik spalinowy}
double Moment, enMoment, eps, newn, friction;
double DM;
// friction =dizel_engagefriction*(11-2*random)/10;
friction = dizel_engagefriction;
if (enrot > 0)
{ // sqr TODO: sqr c++
Moment = dizel_Mmax * dizel_fill -
(dizel_Mmax - dizel_Mnmax * dizel_fill) *
sqr(enrot / (dizel_nmax - dizel_nMmax * dizel_fill)) -
dizel_Mstand; // Q: zamieniam SQR() na sqr()
// Moment:=Moment*(1+sin(eAngle*4))-dizel_Mstand*(1+cos(eAngle*4));}
}
else
Moment = -dizel_Mstand;
if (enrot < dizel_nmin / 10.0)
if (eAngle < PI / 2.0)
Moment = Moment - dizel_Mstand; // wstrzymywanie przy malych obrotach
//!! abs
if (abs(abs(n) - enrot) < 0.1)
{
if ((Moment) > (dizel_engageMaxForce * dizel_engage * dizel_engageDia * friction *
2)) // zerwanie przyczepnosci sprzegla
enrot = enrot + dt * Moment / dizel_AIM;
else
{
dizel_engagedeltaomega = 0;
enrot = abs(n); // jest przyczepnosc tarcz
}
}
else
{
if ((enrot == 0) && (Moment < 0))
newn = 0;
else
{
//!! abs
dizel_engagedeltaomega = enrot - n; // sliganie tarcz
enMoment = Moment -
Sign(dizel_engagedeltaomega) * dizel_engageMaxForce * dizel_engage *
dizel_engageDia * friction;
Moment = Sign(dizel_engagedeltaomega) * dizel_engageMaxForce * dizel_engage *
dizel_engageDia * friction;
dizel_engagedeltaomega = abs(enrot - abs(n));
eps = enMoment / dizel_AIM;
newn = enrot + eps * dt;
if ((newn * enrot <= 0) && (eps * enrot < 0))
newn = 0;
}
enrot = newn;
}
DM = Moment;
if ((enrot == 0) && (!dizel_enginestart))
Mains = false;
return DM;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::LoadingDone(double LSpeed, std::string LoadInit)
{
// test zakoñczenia za³adunku/roz³adunku
long LoadChange;
bool LD;
ClearPendingExceptions; // zabezpieczenie dla Trunc()
// LoadingDone:=false; //nie zakoñczone
if (LoadInit != "") // nazwa ³adunku niepusta
{
if (Load > MaxLoad)
LoadChange = abs(int(LSpeed * LastLoadChangeTime /
2.0)); // prze³adowanie? // trunc zamieniam na int()
else
LoadChange = abs(int(LSpeed * LastLoadChangeTime));
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
Load = Load - LoadChange; // zmniejszenie iloœci ³adunku
CommandIn.Value1 =
CommandIn.Value1 - LoadChange; // zmniejszenie iloœci do roz³adowania
if (Load < 0)
Load = 0; //³adunek nie mo¿e byæ ujemny
if ((Load == 0) || (CommandIn.Value1 < 0)) // pusto lub roz³adowano ¿¹dan¹ iloœæ
LoadStatus = 4; // skoñczony roz³adunek
if (Load == 0)
LoadType = ""; // jak nic nie ma, to nie ma te¿ nazwy
}
}
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
LoadType = LoadInit; // nazwa
Load = Load + LoadChange; // zwiêkszenie ³adunku
CommandIn.Value1 = CommandIn.Value1 - LoadChange;
if ((Load >= MaxLoad * (1 + OverLoadFactor)) || (CommandIn.Value1 < 0))
LoadStatus = 4; // skoñczony za³adunek
}
}
else
LoadStatus = 4; // zerowa prêdkoœæ zmiany, to koniec
}
LD = (LoadStatus >= 4);
return LD;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::DoorBlockedFlag(void)
{
// if (DoorBlocked=true) and (Vel<5.0) then
bool DBF = false;
if ((DoorBlocked == true) && (Vel >= 5.0))
DBF = true;
return DBF;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::DoorLeft(bool State)
{
bool DL;
if ((DoorLeftOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
{
DL = true;
DoorLeftOpened = State;
if (State == true)
{
if (CabNo > 0)
SendCtrlToNext("DoorOpen", 1, CabNo); // 1=lewe, 2=prawe
else
SendCtrlToNext("DoorOpen", 2, CabNo); // zamiana
CompressedVolume = CompressedVolume - 0.003;
}
else
{
if (CabNo > 0)
SendCtrlToNext("DoorClose", 1, CabNo);
else
SendCtrlToNext("DoorClose", 2, CabNo);
}
}
else
DL = false;
return DL;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::DoorRight(bool State)
{
bool DR;
if ((DoorRightOpened != State) && (DoorBlockedFlag() == false) && (Battery == true))
{
DR = true;
DoorRightOpened = State;
if (State == true)
{
if (CabNo > 0)
SendCtrlToNext("DoorOpen", 2, CabNo); // 1=lewe, 2=prawe
else
SendCtrlToNext("DoorOpen", 1, CabNo); // zamiana
CompressedVolume = CompressedVolume - 0.003;
}
else
{
if (CabNo > 0)
SendCtrlToNext("DoorClose", 2, CabNo);
else
SendCtrlToNext("DoorClose", 1, CabNo);
}
}
else
DR = false;
return DR;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
bool TMoverParameters::ChangeOffsetH(double DeltaOffset)
{
bool COH;
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;
}
// *************************************************************************************************
// Q: 20160713
// *************************************************************************************************
std::string TMoverParameters::EngineDescription(int what)
{
std::string outstr;
outstr = "";
switch (what)
{
case 0:
{
if (DamageFlag == 255)
outstr = "Totally destroyed!";
else
{
if (TestFlag(DamageFlag, dtrain_thinwheel))
if (Power > 0.1)
outstr = "Thin wheel,";
else
outstr = "Load shifted,";
if (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!";
if (outstr == "")
outstr = "OK!";
}
};
default:
outstr = "Invalid qualifier";
}
return outstr;
}
// *************************************************************************************************
// Q: 20160709
// *************************************************************************************************
double TMoverParameters::GetTrainsetVoltage(void)
{
double volt;
volt = 0.0;
if (Couplers[1].Connected != NULL)
if (TestFlag(Couplers[1].CouplingFlag, ctrain_power)) // czy jest sprzêg WN
{ // najczêœciej silnikowy jest z ty³u
if (Couplers[1].Connected->PantFrontVolt != 0.0)
volt = Couplers[1].Connected->PantFrontVolt;
else if (Couplers[1].Connected->PantRearVolt != 0.0)
volt = Couplers[1].Connected->PantRearVolt;
}
if (volt == 0.0)
if (Couplers[0].Connected != NULL)
if (TestFlag(Couplers[0].CouplingFlag, ctrain_power)) // czy jest sprzêg WN
{
if (Couplers[0].Connected->PantFrontVolt != 0.0)
volt = Couplers[0].Connected->PantFrontVolt;
else if (Couplers[0].Connected->PantRearVolt != 0.0)
volt = Couplers[0].Connected->PantRearVolt;
}
// WriteLog("GTV");
return volt;
}
// *************************************************************************************************
//
// *************************************************************************************************
bool TMoverParameters::Physic_ReActivation(void) // DO PRZETLUMACZENIA NA KONCU
{
bool pr;
if (PhysicActivation)
return false;
else
{
PhysicActivation = true;
LastSwitchingTime = 0;
return true;
}
}
// *************************************************************************************************
// FUNKCJE PARSERA WCZYTYWANIA PLIKU FIZYKI POJAZDU
// *************************************************************************************************
std::string p0, p1, p2, p3, p4, p5, p6, p7;
std::string xline, sectionname, lastsectionname;
std::string vS;
int vI;
double vD;
bool startBPT;
bool startMPT;
bool startRLIST;
int MPTLINE, RLISTLINE, BPTLINE;
std::vector<std::string> x;
std::string aCategory, aType;
double aMass, aMred, aVmax, aPWR, aHeatingP, aLightP;
int aSandCap;
std::string bLoadQ, bLoadAccepted;
double bLoadSpeed, bUnLoadSpeed, bOverLoadFactor, cL, cW, cH, cCx, cFloor;
int bMaxLoad;
std::string dAxle, dBearingType;
double dD, dDl, dDt, dAIM, dTw, dAd, dBd, dRmin;
std::string eBrakeValve, eBM, eCompressorPower;
double eMBF, eTBF, eMaxBP, eMedMaxBP, eTareMaxBP, eMaxLBP, eMaxASBP, eRM, eBCR, eBCD, eBCM, eBCMlo,
eBCMhi, eVv, eMinCP, eMaxCP, eBCS, eBSA, eBRE, eHiPP, eLoPP, eCompressorSpeed;
int eNBpA, eBVV, eBCN, eSize;
std::string fCType;
double fkB, fDmaxB, fFmaxB, fkC, fDmaxC, fFmaxC, fbeta;
int fAllowedFlag;
std::string gBrakeSystem, gASB, gLocalBrake, gDynamicBrake, gManualBrake, gScndS, gFSCircuit,
gAutoRelay, gBrakeDelays, gBrakeHandle, gLocBrakeHandle, gCoupledCtrl;
float gIniCDelay, gSCDelay, gSCDDelay, gMaxBPMass;
int gBCPN, gBDelay1, gBDelay2, gBDelay3, gBDelay4, gMCPN, gSCPN, gSCIM;
std::string hAwareSystem, hRadioStop;
double hAwareMinSpeed, hAwareDelay, hSoundSignalDelay, hEmergencyBrakeDelay;
std::string iLight, iLGeneratorEngine;
double iLMaxVoltage, iLMaxCurrent;
std::string jEnginePower, jSystemPower;
double jMaxVoltage, jMaxCurrent, jIntR, jMinH, jMaxH, jCSW, jMinV, jMaxV, jMinPress, jMaxPress;
int jCollectorsNo;
std::string kEngineType, kTrans;
double kWindingRes, knmax, kVolt;
// int kVolt;
double lCircuitRes;
int lImaxLo, lImaxHi, lIminLo, lIminHi;
std::string mRVent;
double mRVentnmax, mRVentCutOff;
int mSize;
double nMmax, nnMmax, nMnmax, nnmax, nnominalfill, nMstand;
int nSize;
/*inline int ti(std::string val)
{
return atoi(val.c_str());
}
inline double td(std::string val)
{
return atof(val.c_str());
}
std::string ts(std::string val)
{
// WriteLog("["+ val + "]");
return val;
// else return "unknown";
}
std::string tS(std::string val)
{
return ToUpper(val);
}*/
// *************************************************************************************************
// Q: 20160717
// *************************************************************************************************
int Pos(std::string str_find, std::string in)
{
size_t pos = in.find(str_find);
return (pos ? pos : 0);
}
// *************************************************************************************************
// Q: 20160717
// *************************************************************************************************
bool issection(std::string name)
{
sectionname = name;
if (xline.find(name) != string::npos)
{
lastsectionname = name;
return true;
}
else
return false;
}
// *************************************************************************************************
// Q: 20160717
// *************************************************************************************************
// Pobieranie wartosci z klucza i przypisanie jej do wlasciwego typu danych 1 - string, 2 - int, 3 -
// double
std::string getkeyval(int rettype, std::string key)
{
std::string keyname = key;
key = key + "=";
std::string kval, temp;
temp = xline;
int to;
if (Pos(key, xline) > 0) // jezeli jest klucz w swkcji...
{
int klen = key.length();
int kpos = Pos(key, xline) - 1;
temp.erase(0, kpos + klen);
if (temp.find(" ") != string::npos)
to = temp.find(" ");
else
to = 255;
kval = temp.substr(0, to);
if (kval != "")
kval = TrimSpace(kval); // wyciagnieta wartosc
sectionname = ExchangeCharInString(sectionname, (char)":", (char)"");
sectionname = ExchangeCharInString(sectionname, (char)".", (char)"");
//--WriteLog(sectionname + "." + keyname + " val= [" + kval + "]");
// if (rettype == 1) vS = kval;
// if (kval != "" && rettype == 2) vI = StrToInt(kval);
// if (kval != "" && rettype == 3) vD = StrToFloat(kval);
}
else
kval = ""; // gdy nie bylo klucza TODO: dodac do funkcji parametr z wartoscia fabryczna
// UWAGA! 0 moze powodowac bledy, przemyslec zwracanie wartosci gdy nie ma klucza!!!
// zwraca pusty klucz GF 2016-10-26
return kval;
}
int MARKERROR(int code, std::string type, std::string msg)
{
WriteLog(msg);
return code;
}
int s2NPW(string s)
{ // wylicza ilosc osi napednych z opisu ukladu osi
const char A = (char)"A" - (char)1;
int k;
int NPW = 0;
for (k = 0; k < s.length(); k++)
{
if (s[k] >= (char)"A" && s[k] <= (char)"Z")
NPW += s[k] - A;
}
return NPW;
}
int s2NNW(string s)
{ // wylicza ilosc osi nienapedzanych z opisu ukladu osi
const char Zero = (char)"0";
int k;
int NNW = 0;
for (k = 0; k < s.length(); k++)
{
if (s[k] >= (char)"1" && s[k] <= (char)"9")
NNW += s[k] - Zero;
}
return NNW;
}
// *************************************************************************************************
// Q: 20160717
// *************************************************************************************************
// parsowanie Motor Param Table
bool TMoverParameters::readMPT(int ln, std::string xline)
{
// bl, mfi, mIsat, mfi0, fi, Isat, fi0
bool as;
int bl;
startMPT = true;
if (ln > 0) // 0 to nazwa sekcji - MotorParamTable0:
{
//--WriteLog("MPT: " + xline);
x = Split(xline, ' ');
p0 = TrimSpace(x[0]);
p1 = TrimSpace(x[1]);
p2 = TrimSpace(x[2]);
p3 = TrimSpace(x[3]);
p4 = TrimSpace(x[4]);
p5 = TrimSpace(x[5]);
p6 = TrimSpace(x[6]);
if (AutoRelayType == 0)
as = false;
bl = atoi(p0.c_str()); // numer pozycji
MotorParam[bl].mfi = atof(p1.c_str());
MotorParam[bl].mIsat = atof(p2.c_str());
MotorParam[bl].mfi0 = atof(p3.c_str());
MotorParam[bl].fi = atof(p4.c_str());
MotorParam[bl].Isat = atof(p5.c_str());
MotorParam[bl].fi0 = atof(p6.c_str());
MotorParam[bl].AutoSwitch = as;
//--WriteLog(":::: " + p0 + "," + p1 + "," + p2 + "," + p3 + "," + p4 + "," + p5 + "," +
//p6);
}
MPTLINE++;
return true;
}
// *************************************************************************************************
// Q: 20160718
// *************************************************************************************************
// parsowanie RList
bool TMoverParameters::readRLIST(int ln, std::string xline)
{
char *xxx;
startRLIST = true;
if (ln > 0) // 0 to nazwa sekcji - RList:
{
// WriteLog("RLIST: " + xline);
xline = Tab2Sp(xline); // zamieniamy taby na spacje (ile tabow tyle spacji bedzie)
xxx = TrimAndReduceSpaces(xline.c_str()); // konwertujemy na *char i
// ograniczamy spacje pomiedzy
// parametrami do jednej
x = Split(xxx, ' '); // split je wskaznik na char jak i std::string
p0 = TrimSpace(x[0]);
p1 = TrimSpace(x[1]);
p2 = TrimSpace(x[2]);
p3 = TrimSpace(x[3]);
p4 = TrimSpace(x[4]);
p5 = TrimSpace(x[5]);
int k = ln - 1;
RlistSize = (mSize);
if (RlistSize > ResArraySize)
ConversionError = -4;
RList[k].Relay = atoi(p0.c_str()); // int
RList[k].R = atof(p1.c_str()); // double
RList[k].Bn = atoi(p2.c_str()); // int
RList[k].Mn = atoi(p3.c_str()); // int
RList[k].AutoSwitch = false; // p4.ToInt();
//--WriteLog("RLIST: " + p0 + "," + p1 + "," + p2 + "," + p3 + "," + p4);
}
RLISTLINE++;
return true;
}
// *************************************************************************************************
// Q: 20160721
// *************************************************************************************************
// parsowanie Brake Param Table
bool TMoverParameters::readBPT(int ln, std::string xline)
{
char *xxx;
startBPT = true;
int k;
if (ln > 0) // 0 to nazwa sekcji - Cntrl. - po niej jest tablica hamulcow
{
// WriteLog("BPT: " + xline);
xline = Tab2Sp(xline);
xxx = TrimAndReduceSpaces(xline.c_str());
x = Split(xxx, ' ');
p0 = TrimSpace(x[0]);
p1 = TrimSpace(x[1]);
p2 = TrimSpace(x[2]);
p3 = TrimSpace(x[3]);
p4 = TrimSpace(x[4]);
k = atoi(p0.c_str());
BrakePressureTable[k].PipePressureVal = atof(p1.c_str());
BrakePressureTable[k].BrakePressureVal = atof(p2.c_str());
BrakePressureTable[k].FlowSpeedVal = atof(p3.c_str());
if (p4 == "Pneumatic")
BrakePressureTable[k].BrakeType = Pneumatic;
else if (p4 == "ElectroPneumatic")
BrakePressureTable[k].BrakeType = ElectroPneumatic;
else
BrakePressureTable[k].BrakeType = Individual;
//-- WriteLog("BPT: " + p0 + "," + p1 + "," + p2 + "," + p3 + "," + p4);
}
BPTLINE++;
return true;
}
// *************************************************************************************************
// Q: 20160719
// *************************************************************************************************
void TMoverParameters::BrakeValveDecode(std::string s)
{
if (s == "W")
BrakeValve = W;
else if (s == "W_Lu_L")
BrakeValve = W_Lu_L;
else if (s == "W_Lu_XR")
BrakeValve = W_Lu_XR;
else if (s == "W_Lu_VI")
BrakeValve = W_Lu_VI;
else if (s == "K")
BrakeValve = W;
else if (s == "Kkg")
BrakeValve = Kkg;
else if (s == "Kkp")
BrakeValve = Kkp;
else if (s == "Kks")
BrakeValve = Kks;
else if (s == "Hikp1")
BrakeValve = Hikp1;
else if (s == "Hikss")
BrakeValve = Hikss;
else if (s == "Hikg1")
BrakeValve = Hikg1;
else if (s == "KE")
BrakeValve = KE;
else if (s == "EStED")
BrakeValve = EStED;
else if (Pos("ESt", s) > 0)
BrakeValve = ESt3;
else if (s == "LSt")
BrakeValve = LSt;
else if (s == "EP2")
BrakeValve = EP2;
else if (s == "EP1")
BrakeValve = EP1;
else if (s == "CV1")
BrakeValve = CV1;
else if (s == "CV1_L_TR")
BrakeValve = CV1_L_TR;
else
BrakeValve = Other;
}
// *************************************************************************************************
// Q: 20160719
// *************************************************************************************************
void TMoverParameters::BrakeSubsystemDecode()
{
BrakeSubsystem = ss_None;
switch (BrakeValve)
{
case W:
case W_Lu_L:
case W_Lu_VI:
case W_Lu_XR:
BrakeSubsystem = ss_W;
break;
case ESt3:
case ESt3AL2:
case ESt4:
case EP2:
case EP1:
BrakeSubsystem = ss_ESt;
break;
case KE:
BrakeSubsystem = ss_KE;
break;
case CV1:
case CV1_L_TR:
BrakeSubsystem = ss_Dako;
break;
case LSt:
case EStED:
BrakeSubsystem = ss_LSt;
break;
}
}
// *************************************************************************************************
// Q: 20160721
// *************************************************************************************************
TEngineTypes TMoverParameters::EngineDecode(std::string s)
{
if (s == "ElectricSeriesMotor")
return ElectricSeriesMotor;
else if (s == "DieselEngine")
return DieselEngine;
else if (s == "SteamEngine")
return SteamEngine;
else if (s == "WheelsDriven")
return WheelsDriven;
else if (s == "Dumb")
return Dumb;
else if (s == "DieselElectric")
return DieselElectric;
else // youBy: spal-ele
if (s == "DumbDE")
return DieselElectric;
else // youBy: spal-ele
if (s == "ElectricInductionMotor")
return ElectricInductionMotor;
// else if s='EZT' then {dla kibla}
// EngineDecode:=EZT }
else
return None;
}
// *************************************************************************************************
// Q: 20160719
// *************************************************************************************************
TPowerSource TMoverParameters::PowerSourceDecode(std::string s)
{
if (s == "Transducer")
return Transducer;
else if (s == "Generator")
return Generator;
else if (s == "Accu")
return Accumulator;
else if (s == "CurrentCollector")
return CurrentCollector;
else if (s == "PowerCable")
return PowerCable;
else if (s == "Heater")
return Heater;
else if (s == "Internal")
return InternalSource;
else
return NotDefined;
}
// *************************************************************************************************
// Q: 20160719
// *************************************************************************************************
TPowerType TMoverParameters::PowerDecode(std::string s)
{
if (s == "BioPower")
return BioPower;
else if (s == "BioPower")
return BioPower;
else if (s == "MechPower")
return MechPower;
else if (s == "ElectricPower")
return ElectricPower;
else if (s == "SteamPower")
return SteamPower;
else
return NoPower;
}
// *************************************************************************************************
// Q: 20160719
// *************************************************************************************************
void TMoverParameters::PowerParamDecode(std::string lines, std::string prefix,
TPowerParameters &PowerParamDecode)
{
// with PowerParamDecode do
// begin
switch (PowerParamDecode.SourceType)
{
//--case NotDefined : PowerType = PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerType=')));
//--case InternalSource : PowerType =
//PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerType=')));
//--case Transducer : InputVoltage =
//s2rE(DUE(ExtractKeyWord(lines,prefix+'TransducerInputV=')));
//--case Generator :
//GeneratorEngine:=EngineDecode(DUE(ExtractKeyWord(lines,prefix+'GeneratorEngine=')));
//--case Accumulator:
//--{
//-- RAccumulator.MaxCapacity:=s2r(DUE(ExtractKeyWord(lines,prefix+'Cap=')));
//-- s:=DUE(ExtractKeyWord(lines,prefix+'RS='));
//-- RAccumulator.RechargeSource:=PowerSourceDecode(s);
//--}
case CurrentCollector:
{
PowerParamDecode.CollectorParameters.CollectorsNo = (jCollectorsNo);
PowerParamDecode.CollectorParameters.MinH = (jMinH);
PowerParamDecode.CollectorParameters.MaxH = (jMaxH);
PowerParamDecode.CollectorParameters.CSW = (jCSW); // szerokoœæ czêœci roboczej
PowerParamDecode.CollectorParameters.MaxV = (jMaxVoltage);
// s:=jMinV; //napiêcie roz³¹czaj¹ce WS
if (jMinV == 0)
PowerParamDecode.CollectorParameters.MinV =
0.5 * PowerParamDecode.CollectorParameters.MaxV; // gdyby parametr nie podany
else
PowerParamDecode.CollectorParameters.MinV = (jMinV);
//-s:=ExtractKeyWord(lines,'InsetV='); //napiêcie wymagane do za³¹czenia WS
//-if s='' then
//- InsetV:=0.6*MaxV //gdyby parametr nie podany
//-else
//- InsetV:=s2rE(DUE(s));
// s:=ExtractKeyWord(lines,'MinPress='); //ciœnienie roz³¹czaj¹ce WS
if (jMinPress == 0)
PowerParamDecode.CollectorParameters.MinPress = 2.0; // domyœlnie 2 bary do za³¹czenia
// WS
else
PowerParamDecode.CollectorParameters.MinPress = (jMinPress);
// s:=ExtractKeyWord(lines,'MaxPress='); //maksymalne ciœnienie za reduktorem
if (jMaxPress == 0)
PowerParamDecode.CollectorParameters.MaxPress = 5.0 + 0.001 * (Random(50) - Random(50));
else
PowerParamDecode.CollectorParameters.MaxPress = (jMaxPress);
}
// case PowerCable:
//{
// RPowerCable.PowerTrans:=PowerDecode(DUE(ExtractKeyWord(lines,prefix+'PowerTrans=')));
// if RPowerCable.PowerTrans=SteamPower then
// RPowerCable.SteamPressure:=s2r(DUE(ExtractKeyWord(lines,prefix+'SteamPress=')));
//}
// case Heater :
//{
// //jeszcze nie skonczone!
//}
}
if ((PowerParamDecode.SourceType != Heater) && (PowerParamDecode.SourceType != InternalSource))
if (!((PowerParamDecode.SourceType == PowerCable) &&
(PowerParamDecode.RPowerCable.PowerTrans == SteamPower)))
{
//--MaxVoltage =s2rE(DUE(ExtractKeyWord(lines,prefix+'MaxVoltage=')));
//--MaxCurrent =s2r(DUE(ExtractKeyWord(lines,prefix+'MaxCurrent=')));
//--IntR =s2r(DUE(ExtractKeyWord(lines,prefix+'IntR=')));
}
}
// *************************************************************************************************
// Q: 20160717
// Funkcja pelniaca role pierwotnej LoadChkFile wywolywana w dynobj.cpp w double
// TDynamicObject::Init()
// Po niej wykonywana jest CreateBrakeSys(), ktora jest odpowiednikiem CheckLocomotiveParameters()
// *************************************************************************************************
bool TMoverParameters::LoadFIZ(std::string chkpath)
{
const int param_ok = 1;
const int wheels_ok = 2;
const int dimensions_ok = 4;
int ishash;
int bl, i, k;
int b, OKFlag;
std::string lines, s, appdir;
std::string APPDIR, filetocheck, line, node, key, file, CERR;
string wers;
bool noexist = false;
bool OK;
OKFlag = 0;
LineCount = 0;
ConversionError = 666;
BPTLINE = 0;
MPTLINE = 0;
RLISTLINE = 0;
Mass = 0;
file = chkpath + TypeName + ".fiz";
WriteLog("LOAD FIZ FROM " + file);
// if (!FileExists(file)) WriteLog("E8 - FIZ FILE NOT EXIST.");
// if (!FileExists(file)) return false;
// appdir = ExtractFilePath(ParamStr(0));
ifstream in(file.c_str());
if (!in.is_open())
{
WriteLog("E8 - FIZ FILE NOT EXIST.");
return false;
}
bool secBPT, secMotorParamTable0, secPower, secEngine, secParam, secLoad, secDimensions,
secWheels, secBrake, secBuffCoupl, secCntrl, secSecurity, secLight, secCircuit, secRList,
secDList, secWWList, secffList, secTurboPos;
ConversionError = 0;
// Zbieranie danych zawartych w pliku FIZ
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
while (getline(in, wers))
{
// wers.find('#');
xline = wers.c_str();
ishash = Pos("#", xline);
// if ((ishash == 1)) WriteLog("zakomentowane " + xline);
if ((ishash == 0))
{
if (xline.length() == 0)
startBPT = false; // Tablica parametyrow hamulca nie ma znacznika konca :(
if (issection("END-MPT"))
startMPT = false;
if (issection("END-RL"))
startRLIST = false;
if (issection("Param."))
{
secParam = true;
SetFlag(OKFlag, param_ok);
aCategory = getkeyval(1, "Category");
aType = ToUpper(getkeyval(1, "Type"));
aMass = atof(getkeyval(3, "M").c_str());
aMred = atof(getkeyval(3, "Mred").c_str());
aVmax = atof(getkeyval(3, "Vmax").c_str());
aPWR = atof(getkeyval(3, "PWR").c_str());
aSandCap = atoi(getkeyval(2, "SandCap").c_str());
aHeatingP = atof(getkeyval(3, "HeatingP").c_str());
aLightP = atof(getkeyval(3, "LightP").c_str());
}
if (issection("Load:"))
{
secLoad = true;
bMaxLoad = atoi(getkeyval(2, "MaxLoad").c_str());
bLoadQ = getkeyval(1, "LoadQ");
bLoadAccepted = getkeyval(1, "LoadAccepted");
bLoadSpeed = atof(getkeyval(3, "LoadSpeed").c_str());
bUnLoadSpeed = atof(getkeyval(3, "UnLoadSpeed").c_str());
bOverLoadFactor = atof(getkeyval(3, "OverLoadFactor").c_str());
}
if (issection("Dimensions:"))
{
secDimensions = true;
SetFlag(OKFlag, dimensions_ok);
cL = atof(getkeyval(3, "L").c_str());
cH = atof(getkeyval(3, "H").c_str());
cW = atof(getkeyval(3, "W").c_str());
cCx = atof(getkeyval(3, "Cx").c_str());
cFloor = atof(getkeyval(3, "Floor").c_str());
}
if (issection("Wheels:"))
{
secWheels = true;
dD = atof(getkeyval(3, "D").c_str());
dDl = atof(getkeyval(3, "Dl").c_str());
dDt = atof(getkeyval(3, "Dt").c_str());
dAIM = atof(getkeyval(3, "AIM").c_str());
dTw = atof(getkeyval(3, "Tw").c_str());
dAxle = getkeyval(1, "Axle");
dAd = atof(getkeyval(3, "Ad").c_str());
dBd = atof(getkeyval(3, "Bd").c_str());
dRmin = atof(getkeyval(3, "Rmin").c_str());
dBearingType = getkeyval(1, "BearingType");
}
if (issection("Brake:"))
{
secBrake = true;
eBrakeValve = getkeyval(1, "BrakeValve");
eNBpA = atoi(getkeyval(2, "NBpA").c_str());
eMBF = atof(getkeyval(3, "MBF").c_str());
eTBF = atof(getkeyval(3, "TBF").c_str());
eSize = atoi(getkeyval(3, "Size").c_str());
eMaxBP = atof(getkeyval(3, "MaxBP").c_str());
eMedMaxBP = atof(getkeyval(3, "MedMaxBP").c_str());
eTareMaxBP = atof(getkeyval(3, "TareMaxBP").c_str());
eMaxLBP = atof(getkeyval(3, "MaxLBP").c_str());
eMaxASBP = atof(getkeyval(3, "MaxASBP").c_str());
eRM = atof(getkeyval(3, "RM").c_str());
eBCN = atoi(getkeyval(2, "BCN").c_str());
eBCR = atof(getkeyval(3, "BCR").c_str());
eBCD = atof(getkeyval(3, "BCD").c_str());
eBCM = atof(getkeyval(3, "BCM").c_str());
eBCMlo = atof(getkeyval(3, "BCMlo").c_str());
eBCMhi = atof(getkeyval(3, "BCMhi").c_str());
eVv = atof(getkeyval(3, "Vv").c_str());
eMinCP = atof(getkeyval(3, "MinCP").c_str());
eMaxCP = atof(getkeyval(3, "MaxCP").c_str());
eBCS = atof(getkeyval(3, "BCS").c_str());
eBSA = atof(getkeyval(3, "BSA").c_str());
eBM = atof(getkeyval(1, "BM").c_str());
eBVV = atoi(getkeyval(2, "BVV").c_str());
eBRE = atof(getkeyval(3, "BRE").c_str());
eHiPP = atof(getkeyval(3, "HiPP").c_str());
eLoPP = atof(getkeyval(3, "LoPP").c_str());
eCompressorSpeed = atof(getkeyval(3, "CompressorSpeed").c_str());
eCompressorPower = atof(getkeyval(1, "CompressorPower").c_str());
}
if (issection("BuffCoupl.") || issection("BuffCoupl1."))
{
secBuffCoupl = true;
fCType = (getkeyval(1, "CType"));
fkB = atof(getkeyval(3, "kB").c_str());
fDmaxB = atof(getkeyval(3, "DmaxB").c_str());
fFmaxB = atof(getkeyval(3, "FmaxB").c_str());
fkC = atof(getkeyval(3, "kC").c_str());
fDmaxC = atof(getkeyval(3, "DmaxC").c_str());
fFmaxC = atof(getkeyval(3, "FmaxC").c_str());
fbeta = atof(getkeyval(3, "beta").c_str());
fAllowedFlag = atoi(getkeyval(2, "AllowedFlag").c_str());
}
if (issection("Cntrl."))
{
secCntrl = true;
gBrakeSystem = (getkeyval(1, "BrakeSystem"));
gBCPN = atoi(getkeyval(2, "BCPN").c_str());
gBDelay1 = atoi(getkeyval(2, "BDelay1").c_str());
gBDelay2 = atoi(getkeyval(2, "BDelay2").c_str());
gBDelay3 = atoi(getkeyval(2, "BDelay3").c_str());
gBDelay4 = atoi(getkeyval(2, "BDelay4").c_str());
gASB = (getkeyval(1, "ASB"));
gLocalBrake = (getkeyval(1, "LocalBrake"));
gDynamicBrake = (getkeyval(1, "DynamicBrake"));
// gManualBrake = (getkeyval(1, "ManualBrake"));
gFSCircuit = (getkeyval(1, "FSCircuit").c_str());
gMCPN = atoi(getkeyval(2, "MCPN").c_str());
gSCPN = atoi(getkeyval(2, "SCPN").c_str());
gSCIM = atoi(getkeyval(2, "SCIM").c_str());
gScndS = (getkeyval(1, "ScndS"));
gCoupledCtrl = (getkeyval(1, "CoupledCtrl"));
gAutoRelay = (getkeyval(1, "AutoRelay"));
gIniCDelay = atof(getkeyval(3, "IniCDelay").c_str());
gSCDelay = atof(getkeyval(3, "SCDelay").c_str());
gSCDDelay = atof(getkeyval(3, "SCDDelay").c_str());
gBrakeDelays = (getkeyval(1, "BrakeDelays"));
gBrakeHandle = (getkeyval(1, "BrakeHandle"));
gLocBrakeHandle = (getkeyval(1, "LocBrakeHandle"));
gMaxBPMass = atof(getkeyval(3, "MaxBPMass").c_str());
}
if (issection("Security:"))
{
secSecurity = true;
hAwareSystem = (getkeyval(1, "AwareSystem"));
hAwareMinSpeed = atof(getkeyval(3, "AwareMinSpeed").c_str());
hAwareDelay = atof(getkeyval(3, "AwareDelay").c_str());
hSoundSignalDelay = atof(getkeyval(3, "SoundSignalDelay").c_str());
hEmergencyBrakeDelay = atof(getkeyval(3, "EmergencyBrakeDelay").c_str());
hRadioStop = (getkeyval(1, "RadioStop"));
}
if (issection("Light:"))
{
secLight = true;
iLight = (getkeyval(1, "Light"));
iLGeneratorEngine = (getkeyval(1, "LGeneratorEngine"));
iLMaxVoltage = atof(getkeyval(3, "LMaxVoltage").c_str());
iLMaxCurrent = atof(getkeyval(3, "LMaxCurrent").c_str());
}
if (issection("Power:"))
{
secPower = true;
jEnginePower = (getkeyval(1, "EnginePower"));
jSystemPower = (getkeyval(1, "SystemPower"));
jCollectorsNo = atoi(getkeyval(2, "CollectorsNo").c_str());
jMaxVoltage = atof(getkeyval(3, "MaxVoltage").c_str());
jMaxCurrent = atof(getkeyval(3, "MaxCurrent").c_str());
jIntR = atof(getkeyval(3, "IntR").c_str());
jMinH = atof(getkeyval(3, "MinH").c_str());
jMaxH = atof(getkeyval(3, "MaxH").c_str());
jCSW = atof(getkeyval(3, "CSW").c_str());
jMinV = atof(getkeyval(3, "MinV").c_str());
jMinPress = atof(getkeyval(3, "MinPress").c_str());
jMaxPress = atof(getkeyval(3, "MaxPress").c_str());
}
if (issection("Engine:"))
{
secEngine = true;
kEngineType = (getkeyval(1, "EngineType"));
kTrans = (getkeyval(1, "Trans"));
kVolt = atof(getkeyval(3, "Volt").c_str());
kWindingRes = atof(getkeyval(3, "WindingRes").c_str());
knmax = atof(getkeyval(3, "nmax").c_str());
}
if (issection("Circuit:"))
{
secCircuit = true;
lCircuitRes = atof(getkeyval(3, "CircuitRes").c_str());
lImaxLo = atoi(getkeyval(2, "ImaxLo").c_str());
lImaxHi = atoi(getkeyval(2, "ImaxHi").c_str());
lIminLo = atoi(getkeyval(2, "IminLo").c_str());
lIminHi = atoi(getkeyval(2, "IminHi").c_str());
}
if (issection("RList:"))
{
secRList = true;
mSize = atoi(getkeyval(2, "Size").c_str());
mRVent = (getkeyval(1, "RVent"));
mRVentnmax = atof(getkeyval(3, "RVentnmax").c_str());
mRVentCutOff = atof(getkeyval(3, "RVentCutOff").c_str());
}
if (issection("DList:"))
{
secDList = true;
nMmax = atof(getkeyval(3, "Mmax").c_str());
nnMmax = atof(getkeyval(3, "nMmax").c_str());
nMnmax = atof(getkeyval(3, "Mnmax").c_str());
nnmax = atof(getkeyval(3, "nmax").c_str());
nnominalfill = atof(getkeyval(3, "nominalfill").c_str());
nMstand = atof(getkeyval(3, "Mstand").c_str());
nSize = atoi(getkeyval(2, "Size").c_str());
}
if (issection("WWList:"))
{
secWWList = true;
getkeyval(2, "Size");
}
if (issection("ffList:"))
{
secffList = true;
getkeyval(2, "Size");
}
if (issection("TurboPos:"))
{
secTurboPos = true;
getkeyval(2, "TurboPos");
}
if (issection("Cntrl.") || startBPT)
{
secBPT = true;
BrakeCtrlPosNo = gBCPN;
if (BrakeCtrlPosNo > 0)
readBPT(BPTLINE, xline); // np wagony nie maja BPT
}
if (issection("MotorParamTable0:") || startMPT)
{
secMotorParamTable0 = true;
readMPT(MPTLINE, xline);
}
if (issection("RList:") || startRLIST)
{
secRList = true;
readRLIST(RLISTLINE, xline);
}
} // is hash
} // while line
// Sprawdzenie poprawnosci wczytanych parametrow
// WriteLog("DATA TEST: " + aCategory + ", " + aType + ", " + bLoadQ + ", " + bLoadAccepted + ",
// " + dAxle + ", " + dBearingType + ", " + eBrakeValve + ", " + eBM + ", " + jEnginePower + ",
// " + kEngineType + ", " + mRVent );
// WriteLog(" ");
// WriteLog(" ");
// Operacje na zebranych parametrach - przypisywanie do wlasciwych zmiennych i ustawianie
// zaleznosci
if (aCategory == "train")
CategoryFlag = 1;
else if (aCategory == "road")
CategoryFlag = 2;
else if (aCategory == "ship")
CategoryFlag = 4;
else if (aCategory == "airplane")
CategoryFlag = 8;
else if (aCategory == "unimog")
CategoryFlag = 3;
else
ConversionError = MARKERROR(-7, "1", "Improper vechicle category");
Mass = aMass;
Mred = aMred;
Vmax = aVmax;
Power = aPWR;
HeatingPower = aHeatingP;
LightPower = aLightP;
SandCapacity = aSandCap;
TrainType = dt_Default;
if (aType == "PSEUDODIESEL")
aType = "PDIS";
if (aType == "EZT")
{
TrainType = dt_EZT;
IminLo = 1;
IminHi = 2;
Imin = 1;
}
else // wirtualne wartoœci dla rozrz¹dczego
if (aType == "ET41")
TrainType = dt_ET41;
else if (aType == "ET42")
TrainType = dt_ET42;
else if (aType == "ET22")
TrainType = dt_ET22;
else if (aType == "ET40")
TrainType = dt_ET40;
else if (aType == "EP05")
TrainType = dt_EP05;
else if (aType == "SN61")
TrainType = dt_SN61;
else if (aType == "PDIS")
TrainType = dt_PseudoDiesel;
else if (aType == "181")
TrainType = dt_181;
else if (aType == "182")
TrainType = dt_181; // na razie tak
MaxLoad = bMaxLoad;
LoadQuantity = bLoadQ;
OverLoadFactor = bOverLoadFactor;
LoadSpeed = bLoadSpeed;
UnLoadSpeed = bUnLoadSpeed;
Dim.L = cL;
Dim.W = cW;
Dim.H = cH;
Cx = cCx;
if (Cx == 0)
Cx = 0.3;
if (cFloor == -1)
{
if (Dim.H <= 2.0)
Floor = Dim.H; // gdyby nie by³o parametru, lepsze to ni¿ zero
else
Floor = 0.0; // zgodnoϾ wsteczna
}
else
Floor = cFloor;
// Axles
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
WheelDiameter = dD;
WheelDiameterL = dDl;
WheelDiameterT = dDt;
TrackW = dTw;
AxleInertialMoment = dAIM;
AxleArangement = dAxle;
NPoweredAxles = s2NPW(AxleArangement);
NAxles = NPoweredAxles + s2NNW(AxleArangement);
BearingType = 1;
ADist = dAd;
BDist = dBd;
if (WheelDiameterL == -1) // gdyby nie by³o parametru...
WheelDiameterL = WheelDiameter; //... lepsze to ni¿ zero
else
WheelDiameterL = dDl;
if (WheelDiameterT == -1) // gdyby nie by³o parametru...
WheelDiameterT = WheelDiameter; //... lepsze to ni¿ zero
else
WheelDiameterT = dDt;
if (AxleInertialMoment <= 0)
AxleInertialMoment = 1;
if (NAxles == 0)
ConversionError = MARKERROR(-1, "1", "0 axles, hover cat?");
if (dBearingType == "Roll")
BearingType = 1;
else
BearingType = 0;
/*
WriteLog("CompressorPower " + eCompressorPower);
WriteLog("NAxles " + IntToStr(NAxles));
WriteLog("BearingType " + dBearingType);
WriteLog("params " + BrakeValveParams);
WriteLog("NBpA " + IntToStr(NBpA));
WriteLog("MaxBrakeForce " + FloatToStr(MaxBrakeForce));
WriteLog("TrackBrakeForce " + FloatToStr(TrackBrakeForce));
WriteLog("MaxBrakePress[3] " + FloatToStr(MaxBrakePress[3]));
WriteLog("BrakeCylNo " + IntToStr(BrakeCylNo));
WriteLog("BCD " + FloatToStr(eBCD));
WriteLog("BCR " + FloatToStr(eBCR));
WriteLog("BCS " + FloatToStr(eBCS));
WriteLog("BrakeHandle " + gBrakeHandle);
WriteLog("BrakeLocHandle " + gLocBrakeHandle);
*/
// Brakes
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secBrake)
{
BrakeValveParams = eBrakeValve;
BrakeValveDecode(BrakeValveParams);
BrakeSubsystemDecode();
NBpA = eNBpA;
MaxBrakeForce = eMBF;
BrakeValveSize = eSize;
TrackBrakeForce = eTBF * 1000;
MaxBrakePress[3] = eMaxBP;
// WriteLog("eMaxBP " + FloatToStr(MaxBrakePress[3]));
if (MaxBrakePress[3] > 0)
{
BrakeCylNo = eBCN;
if (BrakeCylNo > 0)
{
MaxBrakePress[0] = eMaxLBP;
if (MaxBrakePress[0] < 0.01)
MaxBrakePress[0] = MaxBrakePress[3];
MaxBrakePress[1] = eTareMaxBP;
MaxBrakePress[2] = eMedMaxBP;
MaxBrakePress[4] = eMaxASBP;
if (MaxBrakePress[4] < 0.01)
MaxBrakePress[4] = 0;
BrakeCylRadius = eBCR;
BrakeCylDist = eBCD;
BrakeCylSpring = eBCS;
BrakeSlckAdj = eBSA;
if (eBRE != 0)
BrakeRigEff = eBRE;
else
BrakeRigEff = 1;
BrakeCylMult[0] = eBCM;
BrakeCylMult[1] = eBCMlo;
BrakeCylMult[2] = eBCMhi;
P2FTrans = 100 * PI * sqr(BrakeCylRadius); // w kN/bar Q: zamieniam SQR() na
// sqr()
if ((BrakeCylMult[1] > 0) || (MaxBrakePress[1] > 0))
LoadFlag = 1;
else
LoadFlag = 0; // Q: zamieniam SQR() na sqr()
BrakeVolume = PI * sqr(BrakeCylRadius) * BrakeCylDist * BrakeCylNo;
BrakeVVolume = eBVV;
if (eBM == "P10-Bg")
BrakeMethod = bp_P10Bg;
else if (eBM == "P10-Bgu")
BrakeMethod = bp_P10Bgu;
else if (eBM == "FR513")
BrakeMethod = bp_FR513;
else if (eBM == "Cosid")
BrakeMethod = bp_Cosid;
else if (eBM == "P10yBg")
BrakeMethod = bp_P10yBg;
else if (eBM == "P10yBgu")
BrakeMethod = bp_P10yBgu;
else if (eBM == "Disk1")
BrakeMethod = bp_D1;
else if (eBM == "Disk1+Mg")
BrakeMethod = bp_D1 + bp_MHS;
else if (eBM == "Disk2")
BrakeMethod = bp_D2;
else
BrakeMethod = 0;
if (eRM != 0)
RapidMult = eRM;
else
RapidMult = 1;
}
else
ConversionError = MARKERROR(-5, "1", "0 brake cylinder units");
}
else
P2FTrans = 0;
// WriteLog("eBM=" + eBM + ", " + IntToStr(0));
if (eHiPP != 0)
CntrlPipePress = eHiPP;
else
CntrlPipePress =
5 + 0.001 * (Random(10) - Random(10)); // Ra 2014-07: trochê niedok³adnoœci
HighPipePress = CntrlPipePress;
if (eHiPP != 0)
LowPipePress = eLoPP;
else
LowPipePress = Min0R(HighPipePress, 3.5);
DeltaPipePress = HighPipePress - LowPipePress;
VeselVolume = eVv;
if (VeselVolume == 0)
VeselVolume = 0.01;
MinCompressor = eMinCP;
MaxCompressor = eMaxCP;
CompressorSpeed = eCompressorSpeed;
if (eCompressorPower == "Converter")
CompressorPower = 2;
else if (eCompressorPower == "Engine")
CompressorPower = 3;
else if (eCompressorPower == "Coupler1")
CompressorPower = 4;
else // w³¹czana w silnikowym EZT z przodu
if (eCompressorPower == "Coupler2")
CompressorPower = 5;
else // w³¹czana w silnikowym EZT z ty³u
if (eCompressorPower == "Main")
CompressorPower = 0;
// WriteLog("params " + BrakeValveParams);
// WriteLog("NBpA " + IntToStr(NBpA));
// WriteLog("MaxBrakeForce " + FloatToStr(MaxBrakeForce));
// WriteLog("TrackBrakeForce " + FloatToStr(TrackBrakeForce));
// WriteLog("MaxBrakePress[3] " + FloatToStr(MaxBrakePress[3]));
// WriteLog("BrakeCylNo " + IntToStr(BrakeCylNo));
}
// Couplers
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (fCType == "Automatic")
Couplers[0].CouplerType = Automatic;
else if (fCType == "Screw")
Couplers[0].CouplerType = Screw;
else if (fCType == "Chain")
Couplers[0].CouplerType = Chain;
else if (fCType == "Bare")
Couplers[0].CouplerType = Bare;
else if (fCType == "Articulated")
Couplers[0].CouplerType = Articulated;
else
Couplers[0].CouplerType = NoCoupler;
if (fAllowedFlag > 0)
Couplers[0].AllowedFlag = fAllowedFlag;
if (Couplers[0].AllowedFlag < 0)
Couplers[0].AllowedFlag = ((-Couplers[0].AllowedFlag) || ctrain_depot);
if ((Couplers[0].CouplerType != NoCoupler) && (Couplers[0].CouplerType != Bare) &&
(Couplers[0].CouplerType != Articulated))
{
Couplers[0].SpringKC = fkC * 1000;
Couplers[0].DmaxC = fDmaxC;
Couplers[0].FmaxC = fFmaxC * 1000;
Couplers[0].SpringKB = fkB * 1000;
Couplers[0].DmaxB = fDmaxB;
Couplers[0].FmaxB = fFmaxB * 1000;
Couplers[0].beta = fbeta;
}
else if (Couplers[0].CouplerType == Bare)
{
Couplers[0].SpringKC = 50 * Mass + Ftmax / 0.05;
Couplers[0].DmaxC = 0.05;
Couplers[0].FmaxC = 100 * Mass + 2 * Ftmax;
Couplers[0].SpringKB = 60 * Mass + Ftmax / 0.05;
Couplers[0].DmaxB = 0.05;
Couplers[0].FmaxB = 50 * Mass + 2 * Ftmax;
Couplers[0].beta = 0.3;
}
else if (Couplers[0].CouplerType == Articulated)
{
Couplers[0].SpringKC = 60 * Mass + 1000;
Couplers[0].DmaxC = 0.05;
Couplers[0].FmaxC = 20000000 + 2 * Ftmax;
Couplers[0].SpringKB = 70 * Mass + 1000;
Couplers[0].DmaxB = 0.05;
Couplers[0].FmaxB = 4000000 + 2 * Ftmax;
Couplers[0].beta = 0.55;
}
Couplers[1].SpringKC = Couplers[0].SpringKC;
Couplers[1].DmaxC = Couplers[0].DmaxC;
Couplers[1].FmaxC = Couplers[0].FmaxC;
Couplers[1].SpringKB = Couplers[0].SpringKB;
Couplers[1].DmaxB = Couplers[0].DmaxB;
Couplers[1].FmaxB = Couplers[0].FmaxB;
Couplers[1].beta = Couplers[0].beta;
Couplers[1].CouplerType = Couplers[0].CouplerType;
Couplers[1].AllowedFlag = Couplers[0].AllowedFlag;
// Controllers
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secCntrl)
{
if (gBrakeSystem == "Pneumatic")
BrakeSystem = Pneumatic;
else if (gBrakeSystem == "ElectroPneumatic")
BrakeSystem = ElectroPneumatic;
else
BrakeSystem = Individual;
if (BrakeSystem != Individual)
{
BrakeCtrlPosNo = gBCPN;
BrakeDelay[1] = gBDelay1;
// BrakeDelay[2] = gBDelay2;
// BrakeDelay[3] = gBDelay3;
// BrakeDelay[4] = gBDelay4;
if (gBrakeDelays == "GPR")
BrakeDelays = bdelay_G + bdelay_P + bdelay_R;
else if (gBrakeDelays == "PR")
BrakeDelays = bdelay_P + bdelay_R;
else if (gBrakeDelays == "GP")
BrakeDelays = bdelay_G + bdelay_P;
else if (gBrakeDelays == "R")
{
BrakeDelays = bdelay_R;
BrakeDelayFlag = bdelay_R;
}
else if (gBrakeDelays == "P")
{
BrakeDelays = bdelay_P;
BrakeDelayFlag = bdelay_P;
}
else if (gBrakeDelays == "G")
{
BrakeDelays = bdelay_G;
BrakeDelayFlag = bdelay_G;
}
else if (gBrakeDelays == "GPR+Mg")
BrakeDelays = bdelay_G + bdelay_P + bdelay_R + bdelay_M;
else if (gBrakeDelays == "PR+Mg")
BrakeDelays = bdelay_P + bdelay_R + bdelay_M;
if (gBrakeHandle == "FV4a")
BrakeHandle = FV4a;
else if (gBrakeHandle == "test")
BrakeHandle = testH;
else if (gBrakeHandle == "D2")
BrakeHandle = D2;
else if (gBrakeHandle == "M394")
BrakeHandle = M394;
else if (gBrakeHandle == "Knorr")
BrakeHandle = Knorr;
else if (gBrakeHandle == "Westinghouse")
BrakeHandle = West;
else if (gBrakeHandle == "FVel6")
BrakeHandle = FVel6;
else if (gBrakeHandle == "St113")
BrakeHandle = St113;
if (gLocBrakeHandle == "FD1")
BrakeLocHandle = FD1;
else if (gLocBrakeHandle == "Knorr")
BrakeLocHandle = Knorr;
else if (gLocBrakeHandle == "Westinghouse")
BrakeLocHandle = West;
if (gMaxBPMass != 0)
MBPM = gMaxBPMass * 1000;
if (BrakeCtrlPosNo > 0)
{
if (gASB == "Manual")
ASBType = 1;
else if (gASB == "Automatic")
ASBType = 2;
}
else
{
if (gASB == "Yes")
ASBType = 128;
}
} // BrakeSystem != individual
// WriteLog("gLocalBrake " + gLocalBrake);
// WriteLog("gManualBrake " + gManualBrake);
// WriteLog("gManualBrake " + gManualBrake);
if (gLocalBrake == "ManualBrake")
LocalBrake = ManualBrake;
else if (gLocalBrake == "PneumaticBrake")
LocalBrake = PneumaticBrake;
else if (gLocalBrake == "HydraulicBrake")
LocalBrake = HydraulicBrake;
else
LocalBrake = NoBrake;
if (gManualBrake == "Yes")
MBrake = true;
else
MBrake = false;
if (gDynamicBrake == "Passive")
DynamicBrakeType = dbrake_passive;
else if (gDynamicBrake == "Switch")
DynamicBrakeType = dbrake_switch;
else if (gDynamicBrake == "Reversal")
DynamicBrakeType = dbrake_reversal;
else if (gDynamicBrake == "Automatic")
DynamicBrakeType = dbrake_automatic;
else
DynamicBrakeType = dbrake_none;
MainCtrlPosNo = gMCPN;
ScndCtrlPosNo = gSCPN;
ScndInMain = bool(gSCIM);
if (gAutoRelay == "Optional")
AutoRelayType = 2;
else if (gAutoRelay == "Yes")
AutoRelayType = 1;
else
AutoRelayType = 0;
if (gCoupledCtrl == "Yes")
CoupledCtrl = true;
else // wspolny wal
CoupledCtrl = false;
if (gScndS == "Yes")
ScndS = true; // brak pozycji rownoleglej przy niskiej nastawie PSR}
else
ScndS = false;
InitialCtrlDelay = gIniCDelay;
CtrlDelay = gSCDelay;
if (gSCDDelay > 0)
CtrlDownDelay = gSCDDelay;
else
CtrlDownDelay = CtrlDelay; // hunter-101012: jesli nie ma SCDDelay;
if (gFSCircuit == "Yes")
FastSerialCircuit = 1;
else
FastSerialCircuit = 0;
}
// Security System
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secSecurity)
{
if (Pos("Active", hAwareSystem) > 0)
SetFlag(SecuritySystem.SystemType, 1);
if (Pos("CabSignal", hAwareSystem) > 0)
SetFlag(SecuritySystem.SystemType, 2);
if (hAwareDelay > 0)
SecuritySystem.AwareDelay = hAwareDelay;
if (hAwareMinSpeed > 0)
SecuritySystem.AwareMinSpeed = hAwareMinSpeed;
else
SecuritySystem.AwareMinSpeed = 0.1 * Vmax; // domyœlnie 10% Vmax
if (hSoundSignalDelay > 0)
SecuritySystem.SoundSignalDelay = hSoundSignalDelay;
if (hEmergencyBrakeDelay > 0)
SecuritySystem.EmergencyBrakeDelay = hEmergencyBrakeDelay;
if (Pos("Yes", hRadioStop) > 0)
SecuritySystem.RadioStop = true;
}
// Power
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secPower)
{
// WriteLog("EnginePower " + jEnginePower);
if (jEnginePower != "")
{
// s:=DUE(ExtractKeyWord(lines,'EnginePower='));
if (jEnginePower != "")
{
EnginePowerSource.SourceType = PowerSourceDecode(jEnginePower);
PowerParamDecode(xline, "", EnginePowerSource);
if ((EnginePowerSource.SourceType == Generator) &&
(EnginePowerSource.GeneratorEngine == WheelsDriven))
ConversionError = -666; // perpetuum mobile?}
if (Power == 0) // jeœli nie ma mocy, np. rozrz¹dcze EZT
EnginePowerSource.SourceType = NotDefined; // to silnik nie ma zasilania
}
else
EnginePowerSource.SourceType = NotDefined;
if (jSystemPower != "")
{
SystemPowerSource.SourceType = PowerSourceDecode(jSystemPower);
PowerParamDecode(xline, "", SystemPowerSource);
}
else
SystemPowerSource.SourceType = NotDefined;
}
jEnginePower = ""; // zeby nastepny pojad mial zresetowane na poczatku wczytywania
}
// Engine
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secEngine)
{
if (kEngineType != "")
{
EngineType = EngineDecode(kEngineType);
switch (EngineType)
{
case ElectricSeriesMotor:
{
NominalVoltage = kVolt;
x = Split(kTrans, ':'); // 18:79
p0 = TrimSpace(x[0]);
p1 = TrimSpace(x[1]);
Transmision.NToothW = atoi(p1.c_str());
Transmision.NToothM = atoi(p0.c_str());
// ToothW to drugi parametr czyli 79
// ToothM to pierwszy czyli 18
// WriteLog("trans " + IntToStr(Transmision.NToothW ) + "/" +
// IntToStr(Transmision.NToothM ));
// if (kTrans != "")
if (Transmision.NToothM > 0)
Transmision.Ratio = Transmision.NToothW / Transmision.NToothM;
else
Transmision.Ratio = 1;
WindingRes = kWindingRes;
if (WindingRes == 0)
WindingRes = 0.01;
// WriteLog("WindingRes " + FloatToStr(WindingRes));
nmax = knmax / 60.0;
// WriteLog("nmax " + FloatToStr(nmax ));
}
break;
} // switch
}
kTrans = "";
}
// Circuit
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secCircuit)
{
// s := DUE(ExtractKeyWord(lines, 'CircuitRes=')); writepaslog('CircuitRes', s);
CircuitRes = (lCircuitRes);
// s := DUE(ExtractKeyWord(lines, 'IminLo=')); writepaslog('IminLo', s);
IminLo = (lIminLo);
// s := DUE(ExtractKeyWord(lines, 'IminHi=')); writepaslog('IminHi', s);
IminHi = (lIminHi);
// s := DUE(ExtractKeyWord(lines, 'ImaxLo=')); writepaslog('ImaxLo', s);
ImaxLo = (lImaxLo);
// s := DUE(ExtractKeyWord(lines, 'ImaxHi=')); writepaslog('ImaxHi', s);
ImaxHi = (lImaxHi);
Imin = IminLo;
Imax = ImaxLo;
}
// RList
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (secRList)
{
RlistSize = (mSize);
if (mRVent == "Automatic")
RVentType = 2;
else if (mRVent == "Yes")
RVentType = 1;
else
RVentType = 0;
if (RVentType > 0)
{
RVentnmax = (mRVentnmax) / 60.0;
RVentCutOff = (mRVentCutOff);
}
}
if (ConversionError == 0)
OK = true;
else
OK = false;
// WriteLog("");
// WriteLog("----------------------------------------------------------------------------------------");
WriteLog("CERROR: " + to_string(ConversionError) + ", SUCCES: " + to_string(OK));
// WriteLogSS();
//WriteLog("");
return OK;
} // LoadFIZ()
// *************************************************************************************************
// Q: 20160717
// *************************************************************************************************
bool TMoverParameters::CheckLocomotiveParameters(bool ReadyFlag, int Dir)
{
bool OK;
int b;
int DefBrakeTable[8] = {15, 4, 25, 25, 13, 3, 12, 2};
OK = true;
AutoRelayFlag = (AutoRelayType == 1);
Sand = SandCapacity;
// WriteLog("aa = " + AxleArangement + " " + std::string( Pos("o", AxleArangement)) );
// if ((Pos("o", AxleArangement) > 0) && (EngineType == ElectricSeriesMotor))
// OK = (RList[1].Bn * RList[1].Mn == NPoweredAxles); //test poprawnosci ilosci osi
// indywidualnie napedzanych
// if ((Pos(LoadType, LoadAccepted) == 0) && (LoadType != ""))
// {
// WriteLog("Load Accepted fail");
// Load = 0;
// OK = false;
// }
// if (BrakeSystem == Individual)
// if (BrakeSubsystem != ss_None)
// {
// WriteLog("BrakeSubsystem fail");
// OK = false; //!
// }
// if ((BrakeVVolume == 0) && (MaxBrakePress[3] > 0) && (BrakeSystem != Individual))
// BrakeVVolume = MaxBrakePress[3] / (5 - MaxBrakePress[3]) * (BrakeCylRadius * BrakeCylRadius
// * BrakeCylDist * BrakeCylNo * PI) * 1000;
// if (BrakeVVolume == 0) BrakeVVolume = 0.01;
BrakeVVolume = 0.01; // q
switch (BrakeValve)
{
case W:
case K:
{
Hamulec = new TWest(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
// if(MBPM<2) //jesli przystawka wazaca
// (dynamic_cast<TWest*>(Hamulec))->SetLP(0,MaxBrakePress[3],0);
// else
// (dynamic_cast<TWest*>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case KE:
{
Hamulec = new TKE(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo,
BrakeDelays, BrakeMethod, NAxles, NBpA);
// (dynamic_cast<TKE*>(Hamulec))->SetRM(RapidMult);
// if(MBPM<2) //jesli przystawka wazaca
// (dynamic_cast<TKE*>(Hamulec))->SetLP(0, MaxBrakePress[3], 0);
// else
// (dynamic_cast<TKE*>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case NESt3:
case ESt3:
case ESt3AL2:
case ESt4:
{
Hamulec = new TNESt3(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
// (dynamic_cast<TNESt3*>(Hamulec))->SetSize(BrakeValveSize,BrakeValveParams);
// if(MBPM<2) //jesli przystawka wazaca
// (dynamic_cast<TNESt3*>(Hamulec))->SetLP(0, MaxBrakePress[3], 0);
// else
// (dynamic_cast<TNESt3*>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case LSt:
{
Hamulec = new TLSt(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo,
BrakeDelays, BrakeMethod, NAxles, NBpA);
//(dynamic_cast<TLSt*>(Hamulec))->SetRM(RapidMult);
break;
}
case EStED:
{
Hamulec = new TEStED(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
//(dynamic_cast<TEStED*>(Hamulec))->SetRM(RapidMult);
break;
}
case EP2:
{
Hamulec = new TEStEP2(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
//(dynamic_cast<TEStEP2*>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case CV1:
{
Hamulec = new TCV1(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo,
BrakeDelays, BrakeMethod, NAxles, NBpA);
break;
}
case CV1_L_TR:
{
Hamulec = new TCV1L_TR(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
break;
}
default:
Hamulec = new TBrake(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
}
// Hamulec->SetASBP(MaxBrakePress[4]);
switch (BrakeHandle)
{
case FV4a:
Handle = new TFV4aM();
break;
case FVel6:
Handle = new TFVel6();
break;
case testH:
Handle = new Ttest();
break;
case M394:
Handle = new TM394();
break;
case Knorr:
Handle = new TH14K1();
break;
case St113:
Handle = new TSt113();
break;
default:
Handle = new TDriverHandle();
}
switch (BrakeLocHandle)
{
case FD1:
{
LocHandle = new TFD1();
LocHandle->Init(MaxBrakePress[0]);
break;
}
case Knorr:
{
LocHandle = new TH1405();
LocHandle->Init(MaxBrakePress[0]);
break;
}
default:
LocHandle = new TDriverHandle();
}
// ustalanie srednicy przewodu glownego (lokomotywa lub napêdowy
if ((TestFlag(BrakeDelays, bdelay_G)) && ((!TestFlag(BrakeDelays, bdelay_R)) || (Power > 1)))
Spg = 0.792;
else
Spg = 0.507;
Pipe = new TReservoir();
Pipe2 = new TReservoir(); // zabezpieczenie, bo sie PG wywala... :(
Pipe->CreateCap((Max0R(Dim.L, 14) + 0.5) * Spg * 1); // dlugosc x przekroj x odejscia i takie
// tam
Pipe2->CreateCap((Max0R(Dim.L, 14) + 0.5) * Spg * 1);
if (LightsPosNo > 0)
LightsPos = LightsDefPos;
// to dac potem do init
if (ReadyFlag) // gotowy do drogi
{
WriteLog("Ready to depart");
CompressedVolume = VeselVolume * MinCompressor * (9.8) / 10;
ScndPipePress = CompressedVolume / VeselVolume;
PipePress = CntrlPipePress;
BrakePress = 0;
LocalBrakePos = 0;
if (CabNo == 0)
BrakeCtrlPos = floor(Handle->GetPos(bh_NP)); // Q: TODO: Trunc na floor
else
BrakeCtrlPos = floor(Handle->GetPos(bh_RP));
MainSwitch(false);
PantFront(true);
PantRear(true);
MainSwitch(true);
ActiveDir = 0; // Dir; //nastawnik kierunkowy - musi byæ ustawiane osobno!
DirAbsolute = ActiveDir * CabNo; // kierunek jazdy wzglêdem sprzêgów
LimPipePress = CntrlPipePress;
}
else
{ // zahamowany}
WriteLog("Bracked");
// Volume = BrakeVVolume * MaxBrakePress[3];
// CompressedVolume = VeselVolume * MinCompressor * 0.55;
// ScndPipePress = 5.1;
// PipePress = LowPipePress;
// PipeBrakePress = MaxBrakePress[3];
// BrakePress = MaxBrakePress[3];
// LocalBrakePos = 0;
// BrakeCtrlPos = floor(Handle->GetPos(bh_NP)); //Q: TODO: Trunc na floor
// LimPipePress = LowPipePress;
}
// ActFlowSpeed = 0;
// BrakeCtrlPosR = BrakeCtrlPos;
// if (BrakeLocHandle == Knorr)
// LocalBrakePos = 5;
// Pipe->CreatePress(PipePress);
// Pipe2->CreatePress(ScndPipePress);
// Pipe->Act();
// Pipe2->Act();
// EqvtPipePress = PipePress;
// Handle->Init(PipePress);
//--ComputeConstans(); // TODO:
//przeinesiono do mover.cpp
if (LoadFlag > 0)
{
if (Load < MaxLoad * 0.45)
{
IncBrakeMult();
IncBrakeMult();
DecBrakeMult(); // TODO: przeinesiono do mover.cpp
if (Load < MaxLoad * 0.35)
DecBrakeMult();
}
if (Load >= MaxLoad * 0.45)
{
IncBrakeMult(); // TODO: przeinesiono do mover.cpp
if (Load >= MaxLoad * 0.55)
IncBrakeMult();
}
}
// taki mini automat - powinno byc ladnie dobrze :)
// BrakeDelayFlag = bdelay_P;
// if ((TestFlag(BrakeDelays, bdelay_G)) && !(TestFlag(BrakeDelays, bdelay_R)))
// BrakeDelayFlag = bdelay_G;
// if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G)))
// BrakeDelayFlag = bdelay_R;
// yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)%
// for ( b=1; b<4; b++)
// {
// if (BrakeDelay[b] == 0)
// BrakeDelay[b] = DefBrakeTable[b];
// BrakeDelay[b] = BrakeDelay[b] * (2.5 + random(0.0, 0.2)) / 3.0;
// }
// if(TrainType == dt_ET22)
// CompressorPower = 0;
// Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag);
// ScndPipePress = Compressor;
WriteLog("OK=" + to_string(OK));
return OK;
}
// *************************************************************************************************
// Q: 20160717
// Funkcja pelniaca role pierwotnej CheckLocomotiveParameters(bool ReadyFlag, int Dir)
// wywolywana w dynobj.cpp w double TDynamicObject::Init()
// *************************************************************************************************
bool TMoverParameters::CreateBrakeSys()
{
WriteLog("check locomotive parameters...");
int b;
bool OK = true;
AutoRelayFlag = (AutoRelayType == 1);
Sand = SandCapacity;
// WriteLog("aa = " + AxleArangement + " " + std::string( Pos("o", AxleArangement)) );
if ((Pos("o", AxleArangement) > 0) && (EngineType == ElectricSeriesMotor))
OK = (RList[1].Bn * RList[1].Mn ==
NPoweredAxles); // test poprawnosci ilosci osi indywidualnie napedzanych
// WriteLogSS("aa ok", BoolToYN(OK));
if (BrakeSystem == Individual)
if (BrakeSubsystem != ss_None)
OK = false; //!
if ((BrakeVVolume == 0) && (MaxBrakePress[3] > 0) && (BrakeSystem != Individual))
BrakeVVolume = MaxBrakePress[3] / (5 - MaxBrakePress[3]) *
(BrakeCylRadius * BrakeCylRadius * BrakeCylDist * BrakeCylNo * PI) * 1000;
if (BrakeVVolume == 0)
BrakeVVolume = 0.01;
// WriteLog("BVV = " + FloatToStr(BrakeVVolume));
if ((TestFlag(BrakeDelays, bdelay_G)) &&
((!TestFlag(BrakeDelays, bdelay_R)) ||
(Power > 1))) // ustalanie srednicy przewodu glownego (lokomotywa lub napêdowy
Spg = 0.792;
else
Spg = 0.507;
// WriteLog("SPG = " + FloatToStr(Spg));
switch (BrakeValve)
{
case W:
case K:
{
WriteLog("XBT W, K");
Hamulec = new TWest(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
if (MBPM < 2) // jesli przystawka wazaca
(static_cast<TWest *>(Hamulec))->SetLP(0, MaxBrakePress[3], 0);
else
(static_cast<TWest *>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case KE:
{
WriteLog("XBT WKE");
Hamulec = new TKE(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo,
BrakeDelays, BrakeMethod, NAxles, NBpA);
(static_cast<TKE *>(Hamulec))->SetRM(RapidMult);
if (MBPM < 2) // jesli przystawka wazaca
(static_cast<TKE *>(Hamulec))->SetLP(0, MaxBrakePress[3], 0);
else
(static_cast<TKE *>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case NESt3:
case ESt3:
case ESt3AL2:
case ESt4:
{
WriteLog("XBT NESt3, ESt3, ESt3AL2, ESt4");
Hamulec = new TNESt3(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(static_cast<TNESt3 *>(Hamulec))->SetSize(BrakeValveSize, BrakeValveParams);
if (MBPM < 2) // jesli przystawka wazaca
(static_cast<TNESt3 *>(Hamulec))->SetLP(0, MaxBrakePress[3], 0);
else
(static_cast<TNESt3 *>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case LSt:
{
WriteLog("XBT LSt");
Hamulec = new TLSt(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo,
BrakeDelays, BrakeMethod, NAxles, NBpA);
(static_cast<TLSt *>(Hamulec))->SetRM(RapidMult);
break;
}
case EStED:
{
WriteLog("XBT EStED");
Hamulec = new TEStED(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(static_cast<TEStED *>(Hamulec))->SetRM(RapidMult);
break;
}
case EP2:
{
WriteLog("XBT EP2");
Hamulec = new TEStEP2(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
(static_cast<TEStEP2 *>(Hamulec))->SetLP(Mass, MBPM, MaxBrakePress[1]);
break;
}
case CV1:
{
WriteLog("XBT CV1");
Hamulec = new TCV1(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume, BrakeCylNo,
BrakeDelays, BrakeMethod, NAxles, NBpA);
break;
}
case CV1_L_TR:
{
WriteLog("XBT CV1_L_T");
Hamulec = new TCV1L_TR(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
break;
}
default:
Hamulec = new TBrake(MaxBrakePress[3], BrakeCylRadius, BrakeCylDist, BrakeVVolume,
BrakeCylNo, BrakeDelays, BrakeMethod, NAxles, NBpA);
}
Hamulec->SetASBP(MaxBrakePress[4]);
switch (BrakeHandle)
{
case FV4a:
Handle = new TFV4aM();
break;
case FVel6:
Handle = new TFVel6();
break;
case testH:
Handle = new Ttest();
break;
case M394:
Handle = new TM394();
break;
case Knorr:
Handle = new TH14K1();
break;
case St113:
Handle = new TSt113();
break;
default:
Handle = new TDriverHandle();
}
switch (BrakeLocHandle)
{
case FD1:
{
LocHandle = new TFD1();
LocHandle->Init(MaxBrakePress[0]);
break;
}
case Knorr:
{
LocHandle = new TH1405();
LocHandle->Init(MaxBrakePress[0]);
break;
}
default:
LocHandle = new TDriverHandle();
}
Pipe = new TReservoir();
Pipe2 = new TReservoir(); // zabezpieczenie, bo sie PG wywala... :(
Pipe->CreateCap((Max0R(Dim.L, 14) + 0.5) * Spg * 1); // dlugosc x przekroj x odejscia i takie
// tam
Pipe2->CreateCap((Max0R(Dim.L, 14) + 0.5) * Spg * 1);
if (LightsPosNo > 0)
LightsPos = LightsDefPos;
// checking ready flag
// to dac potem do init
bool ReadyFlag = true;
if (ReadyFlag) // gotowy do drogi
{
// WriteLog("Ready to depart");
CompressedVolume = VeselVolume * MinCompressor * (9.8) / 10;
ScndPipePress = CompressedVolume / VeselVolume;
PipePress = CntrlPipePress;
BrakePress = 0;
LocalBrakePos = 0;
if (CabNo == 0)
BrakeCtrlPos = floor(Handle->GetPos(bh_NP)); // Q: TODO: Trunc na floor
else
BrakeCtrlPos = floor(Handle->GetPos(bh_RP));
MainSwitch(false);
PantFront(true);
PantRear(true);
MainSwitch(true);
ActiveDir = 0; // Dir; //nastawnik kierunkowy - musi byæ ustawiane osobno!
DirAbsolute = ActiveDir * CabNo; // kierunek jazdy wzglêdem sprzêgów
LimPipePress = CntrlPipePress;
}
else
{ // zahamowany}
// WriteLog("Bracked");
// Volume = BrakeVVolume * MaxBrakePress[3];
// CompressedVolume = VeselVolume * MinCompressor * 0.55;
// ScndPipePress = 5.1;
// PipePress = LowPipePress;
// PipeBrakePress = MaxBrakePress[3];
// BrakePress = MaxBrakePress[3];
// LocalBrakePos = 0;
// BrakeCtrlPos = Trunc(Handle->GetPos(bh_NP)); //Q: TODO: Trunc na floor
// LimPipePress = LowPipePress;
}
ActFlowSpeed = 0;
BrakeCtrlPosR = BrakeCtrlPos;
// if(BrakeLocHandle==Knorr)
// LocalBrakePos =5;
Pipe->CreatePress(PipePress);
Pipe2->CreatePress(ScndPipePress);
Pipe->Act();
Pipe2->Act();
EqvtPipePress = PipePress;
Handle->Init(PipePress);
// taki mini automat - powinno byc ladnie dobrze :)
BrakeDelayFlag = bdelay_P;
if ((TestFlag(BrakeDelays, bdelay_G)) && !(TestFlag(BrakeDelays, bdelay_R)))
BrakeDelayFlag = bdelay_G;
if ((TestFlag(BrakeDelays, bdelay_R)) && !(TestFlag(BrakeDelays, bdelay_G)))
BrakeDelayFlag = bdelay_R;
int DefBrakeTable[8] = {15, 4, 25, 25, 13, 3, 12, 2};
// yB: jesli pojazdy nie maja zadeklarowanych czasow, to wsadz z przepisow +-16,(6)%
// for ( b=1; b<4; b++)
// {
// if (BrakeDelay[b] == 0)
// BrakeDelay[b] = DefBrakeTable[b];
// BrakeDelay[b] = BrakeDelay[b] * (2.5 + random(0.0, 0.2)) / 3.0;
// }
// if(TrainType == dt_ET22)
// CompressorPower = 0;
Hamulec->Init(PipePress, HighPipePress, LowPipePress, BrakePress, BrakeDelayFlag);
ScndPipePress = Compressor;
// WriteLogSS("OK=", BoolTo10(OK));
//WriteLog("");
return OK;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
void TMoverParameters::PutCommand(std::string NewCommand, double NewValue1, double NewValue2,
const TLocation &NewLocation)
{
CommandLast = NewCommand; // zapamiêtanie komendy
CommandIn.Command = NewCommand;
CommandIn.Value1 = NewValue1;
CommandIn.Value2 = NewValue2;
CommandIn.Location = NewLocation;
// czy uruchomic tu RunInternalCommand? nie wiem
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
double TMoverParameters::GetExternalCommand(std::string &Command)
{
Command = CommandOut;
return ValueOut;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
bool TMoverParameters::SendCtrlBroadcast(std::string CtrlCommand, double ctrlvalue)
{
int b;
bool OK;
OK = ((CtrlCommand != CommandIn.Command) && (ctrlvalue != CommandIn.Value1));
// if (OK)
// for (b=0; b<1; b++ )
// if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
// if (Couplers[b].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, DirF(b)))
// OK = (Couplers[b].Connected->RunInternalCommand() || OK);
return OK;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
bool TMoverParameters::SetInternalCommand(std::string NewCommand, double NewValue1,
double NewValue2)
{
bool SIC;
if ((CommandIn.Command == NewCommand) && (CommandIn.Value1 == NewValue1) &&
(CommandIn.Value2 == NewValue2))
SIC = false;
else
{
CommandIn.Command = NewCommand;
CommandIn.Value1 = NewValue1;
CommandIn.Value2 = NewValue2;
SIC = true;
LastLoadChangeTime = 0; // zerowanie czasu (roz)³adowania
}
return SIC;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
bool TMoverParameters::SendCtrlToNext(std::string CtrlCommand, double ctrlvalue, double dir)
{
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 = (dir != 0); // and Mains;
d = (1 + Sign(dir)) / 2; // dir=-1=>d=0, dir=1=>d=1 - wysy³anie tylko w ty³
//- if (OK) //musi byæ wybrana niezerowa kabina
// with Couplers[d] do //w³asny sprzêg od strony (d)
//- if (TestFlag(Couplers[d].CouplingFlag, ctrain_controll))
//- if (Couplers[d].ConnectedNr != d) //jeœli ten nastpêny jest zgodny z aktualnym
//- {
//- if (Couplers[d].Connected->SetInternalCommand(CtrlCommand, ctrlvalue, dir))
//- 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))
//- OK = (Couplers[d].Connected->RunInternalCommand() && OK); //tu jest rekurencja
return OK;
}
// *************************************************************************************************
// Q: 20160723
// *************************************************************************************************
// wys³anie komendy otrzymanej z kierunku CValue2 (wzglêdem sprzêgów: 1=przod,-1=ty³)
// Ra: Jest tu problem z rekurencj¹. Trzeba by oddzieliæ wykonywanie komend od mechanizmu
// ich propagacji w sk³adzie. Osobnym problemem mo¿e byæ propagacja tylko w jedn¹ stronê.
// Jeœli jakiœ cz³on jest wstawiony odwrotnie, to równie¿ odwrotnie musi wykonywaæ
// komendy zwi¹zane z kierunkami (PantFront, PantRear, DoorLeft, DoorRight).
// 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)
{
bool OK;
std::string testload;
OK = false;
ClearPendingExceptions();
/*
{test komend sterowania ukrotnionego}
if command='MainCtrl' then
begin
if MainCtrlPosNo>=Trunc(CValue1) then
MainCtrlPos:=Trunc(CValue1);
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='ScndCtrl' then
begin
if ScndCtrlPosNo>=Trunc(CValue1) then
ScndCtrlPos:=Trunc(CValue1);
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
(* else if command='BrakeCtrl' then
begin
if BrakeCtrlPosNo>=Trunc(CValue1) then
begin
BrakeCtrlPos:=Trunc(CValue1);
OK:=SendCtrlToNext(command,CValue1,CValue2);
end;
end *)
else if command='Brake' then //youBy - jak sie EP hamuje, to trza sygnal wyslac...
begin
Hamulec.SetEPS(CValue1);
//fBrakeCtrlPos:=BrakeCtrlPos; //to powinnno byæ w jednym miejscu, aktualnie w C++!!!
BrakePressureActual:=BrakePressureTable[BrakeCtrlPos];
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end //youby - odluzniacz hamulcow, przyda sie
else if command='BrakeReleaser' then
begin
//--OK:=BrakeReleaser(Round(CValue1)); //samo siê przesy³a dalej // TODO: funkcja
przeniesiona do mover.cpp
//OK:=SendCtrlToNext(command,CValue1,CValue2); //to robi³o kaskadê 2^n
end
else if command='MainSwitch' then
begin
if CValue1=1 then
begin
Mains:=true;
if (EngineType=DieselEngine) and Mains then
dizel_enginestart:=true;
end
else Mains:=false;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='Direction' then
begin
ActiveDir:=Trunc(CValue1);
DirAbsolute:=ActiveDir*CabNo;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='CabActivisation' then
begin
// OK:=Power>0.01;
case Trunc(CValue1*CValue2) of //CValue2 ma zmieniany znak przy niezgodnoœci sprzêgów
1 : CabNo:= 1;
-1 : CabNo:=-1;
else CabNo:=0; //gdy CValue1==0
end;
DirAbsolute:=ActiveDir*CabNo;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='AutoRelaySwitch' then
begin
if (CValue1=1) and (AutoRelayType=2) then AutoRelayFlag:=true
else AutoRelayFlag:=false;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='FuseSwitch' then
begin
if ((EngineType=ElectricSeriesMotor)or(EngineType=DieselElectric)) and FuseFlag and
(CValue1=1) and
(MainCtrlActualPos=0) and (ScndCtrlActualPos=0) and Mains then
{ if (EngineType=ElectricSeriesMotor) and (CValue1=1) and
(MainCtrlActualPos=0) and (ScndCtrlActualPos=0) and Mains then}
FuseFlag:=false; {wlaczenie ponowne obwodu}
// if ((EngineType=ElectricSeriesMotor)or(EngineType=DieselElectric)) and not FuseFlag and
(CValue1=0) and Mains then
// FuseFlag:=true;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='ConverterSwitch' then {NBMX}
begin
if (CValue1=1) then ConverterAllow:=true
else if (CValue1=0) then ConverterAllow:=false;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='BatterySwitch' then {NBMX}
begin
//--if (CValue1=1) then Battery:=true
//--else if (CValue1=0) then Battery:=false;
//--if (Battery) and (ActiveCab<>0) {or (TrainType=dt_EZT)} then
//-- SecuritySystem.Status:=SecuritySystem.Status or s_waiting //aktywacja czuwaka
//--else
//-- SecuritySystem.Status:=0; //wy³¹czenie czuwaka
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
// 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' then {NBMX}
begin
if (CValue1=1) then CompressorAllow:=true
else if (CValue1=0) then CompressorAllow:=false;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='DoorOpen' then {NBMX}
begin //Ra: uwzglêdniæ trzeba jeszcze zgodnoœæ sprzêgów
if (CValue2>0) then
begin //normalne ustawienie pojazdu
if (CValue1=1) OR (CValue1=3) then
DoorLeftOpened:=true;
if (CValue1=2) OR (CValue1=3) then
DoorRightOpened:=true;
end
else
begin //odwrotne ustawienie pojazdu
if (CValue1=2) OR (CValue1=3) then
DoorLeftOpened:=true;
if (CValue1=1) OR (CValue1=3) then
DoorRightOpened:=true;
end;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='DoorClose' then {NBMX}
begin //Ra: uwzglêdniæ trzeba jeszcze zgodnoœæ sprzêgów
if (CValue2>0) then
begin //normalne ustawienie pojazdu
if (CValue1=1) OR (CValue1=3) then
DoorLeftOpened:=false;
if (CValue1=2) OR (CValue1=3) then
DoorRightOpened:=false;
end
else
begin //odwrotne ustawienie pojazdu
if (CValue1=2) OR (CValue1=3) then
DoorLeftOpened:=false;
if (CValue1=1) OR (CValue1=3) then
DoorRightOpened:=false;
end;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='PantFront' then {Winger 160204}
begin //Ra: uwzglêdniæ trzeba jeszcze zgodnoœæ sprzêgów
//Czemu EZT ma byæ traktowane inaczej? Ukrotnienie ma, a cz³on mo¿e byæ odwrócony
if (TrainType=dt_EZT) then
begin //'ezt'
if (CValue1=1) then
begin
PantFrontUp:=true;
PantFrontStart:=0;
end
else if (CValue1=0) then
begin
PantFrontUp:=false;
PantFrontStart:=1;
end;
end
else
begin //nie 'ezt' - odwrotne ustawienie pantografów: ^-.-^ zamiast ^-.^-
(*
if (CValue1=1) then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantFrontUp:=true;
PantFrontStart:=0;
end
else
begin
PantRearUp:=true;
PantRearStart:=0;
end
else if (CValue1=0) then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantFrontUp:=false;
PantFrontStart:=1;
end
else
begin
PantRearUp:=false;
PantRearStart:=1;
end;
*)
end;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='PantRear' then {Winger 160204, ABu 310105 i 030305}
begin //Ra: uwzglêdniæ trzeba jeszcze zgodnoœæ sprzêgów
if (TrainType=dt_EZT) then
begin {'ezt'}
if (CValue1=1) then
begin
PantRearUp:=true;
PantRearStart:=0;
end
else if (CValue1=0) then
begin
PantRearUp:=false;
PantRearStart:=1;
end;
end
else
begin {nie 'ezt'}
(*
if (CValue1=1) then
{if ostatni polaczony sprz. sterowania}
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantRearUp:=true;
PantRearStart:=0;
end
else
begin
PantFrontUp:=true;
PantFrontStart:=0;
end
else if (CValue1=0) then
if (TestFlag(Couplers[1].CouplingFlag,ctrain_controll)and(CValue2= 1))
or(TestFlag(Couplers[0].CouplingFlag,ctrain_controll)and(CValue2=-1))
then
begin
PantRearUp:=false;
PantRearStart:=1;
end
else
begin
PantFrontUp:=false;
PantFrontStart:=1;
end;
*)
end;
//--OK:=SendCtrlToNext(command,CValue1,CValue2);
end
else if command='MaxCurrentSwitch' then
begin
//--OK:=MaxCurrentSwitch(CValue1=1);
end
else if command='MinCurrentSwitch' then
begin
//--OK:=MinCurrentSwitch(CValue1=1);
end
{test komend oddzialywujacych na tabor}
else if command='SetDamage' then
begin
if CValue2=1 then OK:=SetFlag(DamageFlag,Trunc(CValue1));
if CValue2=-1 then OK:=SetFlag(DamageFlag,-Trunc(CValue1));
end
else if command='Emergency_brake' then
begin
//-- if EmergencyBrakeSwitch(Trunc(CValue1)=1) then // moe ma w pas TODO:
//-- OK:=true
//-- else OK:=false;
end
else if command='BrakeDelay' then
begin
BrakeDelayFlag:=Trunc(CValue1);
OK:=true;
end
//--else if command='SandDoseOn' then
//-- begin
//-- if SandDoseOn then
//-- OK:=true
//-- else OK:=false;
//-- end
else if command='CabSignal' then {SHP,Indusi}
begin //Ra: to powinno dzia³aæ tylko w cz³onie obsadzonym
//-- if {(TrainType=dt_EZT)or} (ActiveCab<>0) and (Battery) and
TestFlag(SecuritySystem.SystemType,2) then //jeœli kabina jest obsadzona (silnikowy w EZT?)
//-- with SecuritySystem do
//-- begin
//-- VelocityAllowed:=Trunc(CValue1);
//-- NextVelocityAllowed:=Trunc(CValue2);
//-- SystemSoundSHPTimer:=0; //hunter-091012
//-- SetFlag(Status,s_active);
//-- end;
//else OK:=false;
OK:=true; //true, gdy mo¿na usun¹æ komendê
end
{naladunek/rozladunek}
else if Pos('Load=',command)=1 then
begin
OK:=false; //bêdzie powtarzane a¿ siê za³aduje
//-if (Vel=0) and (MaxLoad>0) and (Load<MaxLoad*(1+OverLoadFactor)) then //czy mo¿na
³adowac?
//- if Distance(Loc,CommandIn.Location,Dim,Dim)<10 then //ten peron/rampa
//- begin
//- testload:=LowerCase(DUE(command));
//-if Pos(testload,LoadAccepted)>0 then //nazwa jest obecna w CHK
//- OK:=LoadingDone(Min0R(CValue2,LoadSpeed),testload); //zmienia LoadStatus //
przeniesione do mover.cpp
//- end;
//if OK then LoadStatus:=0; //nie udalo sie w ogole albo juz skonczone
end
else if Pos('UnLoad=',command)=1 then
begin
OK:=false; //bêdzie powtarzane a¿ siê roz³aduje
//-if (Vel=0) and (Load>0) then //czy jest co rozladowac?
//- if Distance(Loc,CommandIn.Location,Dim,Dim)<10 then //ten peron
//- begin
//- testload:=DUE(command); //zgodnoœæ nazwy ³adunku z CHK
//-if LoadType=testload then {mozna to rozladowac}
//- OK:=LoadingDone(-Min0R(CValue2,LoadSpeed),testload); //
przeniesione do mover.cpp
//- end;
//if OK then LoadStatus:=0;
end;
RunCommand:=OK; //dla true komenda bêdzie usuniêta, dla false wykonana ponownie
*/
return OK;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
bool TMoverParameters::RunInternalCommand(void)
{
bool OK;
if (CommandIn.Command != "")
{
OK = RunCommand(CommandIn.Command, CommandIn.Value1, CommandIn.Value2);
if (OK)
{
CommandIn.Command = ""; // kasowanie bo rozkaz wykonany
CommandIn.Value1 = 0;
CommandIn.Value2 = 0;
CommandIn.Location.X = 0;
CommandIn.Location.Y = 0;
CommandIn.Location.Z = 0;
if (!PhysicActivation)
Physic_ReActivation();
}
}
else
OK = false;
return OK;
}
// *************************************************************************************************
// Q: 20160714
// *************************************************************************************************
int TMoverParameters::ShowCurrentP(int AmpN)
{
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
if ((DynamicBrakeType == dbrake_automatic) && (DynamicBrakeFlag))
Bn = 2;
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
for (b = 0; b < 1; b++)
// with Couplers[b] do
if (TestFlag(Couplers[b].CouplingFlag, ctrain_controll))
if (Couplers[b].Connected->Power > 0.01)
return Couplers[b].Connected->ShowCurrent(AmpN);
}