e43ea7fc conflict mess up fix

This commit is contained in:
tmj-fstate
2019-10-12 19:53:42 +02:00
parent e43ea7fcfe
commit 0e20ec7f08
5 changed files with 680 additions and 404 deletions

View File

@@ -1001,68 +1001,145 @@ double TMoverParameters::PipeRatio(void)
// Q: 20160716
// Wykrywanie kolizji
// *************************************************************************************************
void TMoverParameters::CollisionDetect(int CouplerN, double dt)
void TMoverParameters::CollisionDetect(int const End, double const dt)
{
double CCF, Vprev, VprevC;
bool VirtualCoupling;
if( Neighbours[ End ].vehicle == nullptr ) { return; } // shouldn't normally happen but, eh
CCF = 0;
// with Couplers[CouplerN] do
auto &coupler = Couplers[ CouplerN ];
auto &coupler { Couplers[ End ] };
auto *othervehicle { Neighbours[ End ].vehicle->MoverParameters };
auto const otherend { Neighbours[ End ].vehicle_end };
auto &othercoupler { othervehicle->Couplers[ otherend ] };
if (coupler.Connected != nullptr)
{
VirtualCoupling = (coupler.CouplingFlag == ctrain_virtual);
Vprev = V;
VprevC = coupler.Connected->V;
switch (CouplerN)
{
case 0:
auto velocity { V };
auto othervehiclevelocity { othervehicle->V };
// calculate collision force and new velocities for involved vehicles
auto const VirtualCoupling { ( coupler.CouplingFlag == coupling::faux ) };
auto CCF { 0.0 };
switch( End ) {
case 0: {
CCF =
ComputeCollision(
V,
coupler.Connected->V,
TotalMass,
coupler.Connected->TotalMass,
(coupler.beta + coupler.Connected->Couplers[coupler.ConnectedNr].beta) / 2.0,
VirtualCoupling)
/ (dt);
velocity, othervehiclevelocity,
TotalMass, othervehicle->TotalMass,
( coupler.beta + othercoupler.beta ) / 2.0,
VirtualCoupling )
/ ( dt );
break; // yB: ej ej ej, a po
case 1:
}
case 1: {
CCF =
ComputeCollision(
coupler.Connected->V,
V,
coupler.Connected->TotalMass,
TotalMass,
(coupler.beta + coupler.Connected->Couplers[coupler.ConnectedNr].beta) / 2.0,
VirtualCoupling)
/ (dt);
break; // czemu tu jest +0.01??
othervehiclevelocity, velocity,
othervehicle->TotalMass, TotalMass,
( coupler.beta + othercoupler.beta ) / 2.0,
VirtualCoupling )
/ ( dt );
break;
}
AccS = AccS + (V - Vprev) / dt; // korekta przyspieszenia o siły wynikające ze zderzeń?
coupler.Connected->AccS += (coupler.Connected->V - VprevC) / dt;
if ((coupler.Dist > 0) && (!VirtualCoupling))
if (FuzzyLogic(abs(CCF), 5.0 * (coupler.FmaxC + 1.0), p_coupldmg))
{ //! zerwanie sprzegu
if (SetFlag(DamageFlag, dtrain_coupling))
EventFlag = true;
default: {
break;
}
}
if ((coupler.CouplingFlag & ctrain_pneumatic) == ctrain_pneumatic)
AlarmChainFlag = true; // hamowanie nagle - zerwanie przewodow hamulcowych
coupler.CouplingFlag = 0;
if( ( coupler.Dist < 0 )
&& ( FuzzyLogic( std::abs( CCF ), 5.0 * ( coupler.FmaxC + 1.0 ), p_coupldmg ) ) ) {
// small chance to smash the coupler if it's hit with excessive force
damage_coupler( End );
}
switch (CouplerN) // wyzerowanie flag podlaczenia ale ciagle sa wirtualnie polaczone
{
case 0:
coupler.Connected->Couplers[1].CouplingFlag = 0;
break;
case 1:
coupler.Connected->Couplers[0].CouplingFlag = 0;
break;
}
WriteLog( "Bad driving: " + Name + " broke a coupler" );
auto const safevelocitylimit { 15.0 };
auto const velocitydifference {
glm::length(
glm::angleAxis( Rot.Rz, glm::dvec3{ 0, 1, 0 } ) * V
- glm::angleAxis( othervehicle->Rot.Rz, glm::dvec3{ 0, 1, 0 } ) * othervehicle->V )
* 3.6 }; // m/s -> km/h
if( velocitydifference > safevelocitylimit ) {
// HACK: crude estimation for potential derail, will take place with velocity difference > 15 km/h adjusted for vehicle mass ratio
if( ( false == TestFlag( DamageFlag, dtrain_out ) )
|| ( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) ) {
WriteLog( "Bad driving: " + Name + " and " + othervehicle->Name + " collided with velocity " + to_string( velocitydifference, 0 ) + " km/h" );
}
if( velocitydifference > safevelocitylimit * ( TotalMass / othervehicle->TotalMass ) ) {
derail( 5 );
}
if( velocitydifference > safevelocitylimit * ( othervehicle->TotalMass / TotalMass ) ) {
othervehicle->derail( 5 );
}
}
// adjust velocity and acceleration of affected vehicles
if( false == TestFlag( DamageFlag, dtrain_out ) ) {
auto const accelerationchange{ ( velocity - V ) / dt };
// if( accelerationchange / AccS < 1.0 ) {
// HACK: prevent excessive vehicle pinball cases
AccS += accelerationchange;
// AccS = clamp( AccS, -2.0, 2.0 );
V = velocity;
// }
}
if( false == TestFlag( othervehicle->DamageFlag, dtrain_out ) ) {
auto const othervehicleaccelerationchange{ ( othervehiclevelocity - othervehicle->V ) / dt };
// if( othervehicleaccelerationchange / othervehicle->AccS < 1.0 ) {
// HACK: prevent excessive vehicle pinball cases
othervehicle->AccS += othervehicleaccelerationchange;
othervehicle->V = othervehiclevelocity;
// }
}
}
void
TMoverParameters::damage_coupler( int const End ) {
auto &coupler{ Couplers[ End ] };
if( coupler.CouplerType == TCouplerType::Articulated ) { return; } // HACK: don't break articulated couplings no matter what
if( SetFlag( DamageFlag, dtrain_coupling ) )
EventFlag = true;
if( ( coupler.CouplingFlag & coupling::brakehose ) == coupling::brakehose ) {
// hamowanie nagle - zerwanie przewodow hamulcowych
AlarmChainFlag = true;
}
coupler.CouplingFlag = 0;
if( coupler.Connected != nullptr ) {
switch( End ) {
// break connection with other vehicle, if there's any
case 0: {
coupler.Connected->Couplers[ end::rear ].CouplingFlag = coupling::faux;
break;
}
case 1: {
coupler.Connected->Couplers[ end::front ].CouplingFlag = coupling::faux;
break;
}
default: {
break;
}
}
}
WriteLog( "Bad driving: " + Name + " broke a coupler" );
}
void
TMoverParameters::derail( int const Reason ) {
if( SetFlag( DamageFlag, dtrain_out ) ) {
DerailReason = Reason; // TODO: enum derail causes
EventFlag = true;
MainSwitch( false, range_t::local );
AccS *= 0.65;
V *= 0.65;
WriteLog( "Bad driving: " + Name + " derailed" );
}
}
@@ -1071,7 +1148,7 @@ void TMoverParameters::CollisionDetect(int CouplerN, double dt)
// *************************************************************************************************
double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShape &Shape,
TTrackParam &Track, TTractionParam &ElectricTraction,
const TLocation &NewLoc, TRotation &NewRot)
TLocation const &NewLoc, TRotation const &NewRot)
{
const double Vepsilon = 1e-5;
const double Aepsilon = 1e-3; // ASBSpeed=0.8;
@@ -1105,9 +1182,6 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
// TODO: investigate, seems supplied NewRot is always 0 although the code here suggests some actual values are expected
Loc = NewLoc;
Rot = NewRot;
NewRot.Rx = 0;
NewRot.Ry = 0;
NewRot.Rz = 0;
if (dL == 0) // oblicz przesuniecie}
{
@@ -1236,17 +1310,14 @@ double TMoverParameters::ComputeMovement(double dt, double dt1, const TTrackShap
// *************************************************************************************************
double TMoverParameters::FastComputeMovement(double dt, const TTrackShape &Shape,
TTrackParam &Track, const TLocation &NewLoc,
TRotation &NewRot)
TTrackParam &Track, TLocation const &NewLoc,
TRotation const &NewRot)
{
int b;
// T_MoverParameters::FastComputeMovement(dt, Shape, Track, NewLoc, NewRot);
Loc = NewLoc;
Rot = NewRot;
NewRot.Rx = 0.0;
NewRot.Ry = 0.0;
NewRot.Rz = 0.0;
if (dL == 0) // oblicz przesuniecie
{
@@ -1315,10 +1386,11 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
RunInternalCommand();
// automatyczny rozruch
if (EngineType == TEngineType::ElectricSeriesMotor)
if (AutoRelayCheck())
SetFlag(SoundFlag, sound::relay);
if( EngineType == TEngineType::ElectricSeriesMotor ) {
if( AutoRelayCheck() ) {
SetFlag( SoundFlag, sound::relay );
}
}
if( ( EngineType == TEngineType::DieselEngine )
|| ( EngineType == TEngineType::DieselElectric ) ) {
@@ -1330,6 +1402,8 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
// TODO: gather and move current calculations to dedicated method
TotalCurrent = 0;
// main circuit
MainsCheck( Deltatime );
// traction motors
MotorBlowersCheck( Deltatime );
// uklady hamulcowe:
@@ -1371,6 +1445,37 @@ void TMoverParameters::compute_movement_( double const Deltatime ) {
PowerCouplersCheck( Deltatime );
}
void TMoverParameters::MainsCheck( double const Deltatime ) {
// TODO: move other main circuit checks here
if( MainsInitTime == 0.0 ) { return; }
if( MainsInitTimeCountdown > 0.0 ) {
MainsInitTimeCountdown -= Deltatime;
}
// TBD, TODO: move voltage calculation to separate method and use also in power coupler state calculation?
auto localvoltage { 0.0 };
switch( EnginePowerSource.SourceType ) {
case TPowerSource::CurrentCollector: {
localvoltage =
std::max(
localvoltage,
std::max(
PantFrontVolt,
PantRearVolt ) );
break;
}
default: {
break;
}
}
if( ( localvoltage == 0.0 )
&& ( GetTrainsetVoltage() == 0 ) ) {
MainsInitTimeCountdown = MainsInitTime;
}
}
void TMoverParameters::PowerCouplersCheck( double const Deltatime ) {
// TODO: add support for other power sources
auto localvoltage { 0.0 };
@@ -1382,7 +1487,13 @@ void TMoverParameters::PowerCouplersCheck( double const Deltatime ) {
break;
}
case TPowerSource::Main: {
localvoltage = ( true == Mains ? Voltage : 0.0 );
// HACK: main circuit can be fed through couplers, so we explicitly check pantograph supply here
localvoltage = (
true == Mains ?
std::max(
PantFrontVolt,
PantRearVolt ) :
0.0 );
break;
}
default: {
@@ -1544,6 +1655,8 @@ void TMoverParameters::HeatingCheck( double const Timestep ) {
auto const absrevolutions { std::abs( generator.revolutions ) };
generator.voltage = (
false == HeatingAllow ? 0.0 :
// TODO: add support for desired voltage selector
absrevolutions < generator.revolutions_min ? generator.voltage_min * absrevolutions / generator.revolutions_min :
// absrevolutions > generator.revolutions_max ? generator.voltage_max * absrevolutions / generator.revolutions_max :
interpolate(
@@ -1680,7 +1793,7 @@ void TMoverParameters::OilPumpCheck( double const Timestep ) {
OilPump.pressure =
std::max<float>(
OilPump.pressure_target,
OilPump.pressure - 0.01 * Timestep );
OilPump.pressure - ( enrot > 5.0 ? 0.05 : 0.035 ) * 0.5 * Timestep );
}
OilPump.pressure = clamp( OilPump.pressure, 0.f, 1.5f );
}
@@ -2115,14 +2228,14 @@ bool TMoverParameters::IncScndCtrl(int CtrlSpeed)
SendCtrlToNext("SpeedCntrl", SpeedCtrlValue, CabNo);
}
if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 1) && (EngineType == TEngineType::DieselEngine))
if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 1) && (EngineType == TEngineType::DieselEngine))
{
// NOTE: round() already adds 0.5, are the ones added here as well correct?
SpeedCtrlValue = Round(Vel);
SpeedCtrlUnit.IsActive = true;
}
return OK;
return OK;
}
// *************************************************************************************************
@@ -2177,14 +2290,13 @@ bool TMoverParameters::DecScndCtrl(int CtrlSpeed)
SpeedCtrlUnit.IsActive = false;
}
if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 0) && (EngineType == TEngineType::DieselEngine))
if ((OK) && (SpeedCtrl) && (ScndCtrlPos == 0) && (EngineType == TEngineType::DieselEngine))
{
// NOTE: round() already adds 0.5, are the ones added here as well correct?
SpeedCtrlValue = 0;
SpeedCtrlUnit.IsActive = false;
}
return OK;
return OK;
}
// *************************************************************************************************
@@ -2220,7 +2332,7 @@ bool TMoverParameters::CabDeactivisation(void)
CabNo = 0;
DirAbsolute = ActiveDir * CabNo;
DepartureSignal = false; // nie buczeć z nieaktywnej kabiny
SecuritySystem.Status = 0; // deactivate alerter TODO: make it part of control based cab selection
SecuritySystem.Status = s_off; // deactivate alerter TODO: make it part of control based cab selection
SendCtrlToNext("CabActivisation", 0, ActiveCab); // CabNo==0!
}
@@ -2439,8 +2551,9 @@ void TMoverParameters::SecuritySystemCheck(double dt)
if ((!Radio))
RadiostopSwitch(false);
if ((SecuritySystem.SystemType > 0) && (SecuritySystem.Status > 0) &&
(Battery)) // Ra: EZT ma teraz czuwak w rozrządczym
if ((SecuritySystem.SystemType > 0)
&& (SecuritySystem.Status != s_off)
&& (Battery)) // Ra: EZT ma teraz czuwak w rozrządczym
{
// CA
if( ( SecuritySystem.AwareMinSpeed > 0.0 ?
@@ -2468,30 +2581,29 @@ void TMoverParameters::SecuritySystemCheck(double dt)
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 += dt;
if (TestFlag(SecuritySystem.SystemType, 2) &&
TestFlag(SecuritySystem.Status, s_SHPalarm)) // jeśli buczy
}
// SHP
if( TestFlag( SecuritySystem.SystemType, 2 ) ) {
if( TestFlag( SecuritySystem.Status, s_SHPalarm ) ) {
// jeśli buczy
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;
}
if( TestFlag( SecuritySystem.Status, s_active ) ) {
// jeśli świeci albo miga
SecuritySystem.SystemSoundSHPTimer += dt;
if( ( SecuritySystem.VelocityAllowed >= 0 ) && ( Vel > SecuritySystem.VelocityAllowed ) ) {
SetFlag( SecuritySystem.Status, s_SHPebrake );
}
else if( ( ( SecuritySystem.SoundSignalDelay >= 0 ) && ( SecuritySystem.SystemSoundSHPTimer > SecuritySystem.SoundSignalDelay ) )
|| ( ( SecuritySystem.NextVelocityAllowed >= 0 ) && ( Vel > SecuritySystem.NextVelocityAllowed ) ) ) {
SetFlag( SecuritySystem.Status, s_SHPalarm );
if( ( SecuritySystem.EmergencyBrakeDelay >= 0 ) && ( SecuritySystem.SystemBrakeSHPTimer > SecuritySystem.EmergencyBrakeDelay ) ) {
SetFlag( SecuritySystem.Status, s_SHPebrake );
}
}
}
}
// TEST CA
if (TestFlag(SecuritySystem.Status, s_CAtest)) // jeśli świeci albo miga
SecuritySystem.SystemBrakeCATestTimer += dt;
@@ -2531,8 +2643,8 @@ bool TMoverParameters::BatterySwitch(bool State)
SendCtrlToNext("BatterySwitch", 0, CabNo);
BS = true;
if ((Battery) && (ActiveCab != 0)) /*|| (TrainType==dt_EZT)*/
SecuritySystem.Status = (SecuritySystem.Status | s_waiting); // aktywacja czuwaka
if ((Battery) && (ActiveCab != 0))
SecuritySystem.Status |= s_waiting; // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wyłączenie czuwaka
@@ -2999,6 +3111,7 @@ void TMoverParameters::MainSwitch_( bool const State ) {
if( ( false == State )
|| ( ( ( ScndCtrlPos == 0 ) || ( EngineType == TEngineType::ElectricInductionMotor ) )
&& ( ( ConvOvldFlag == false ) || ( TrainType == dt_EZT ) )
&& ( MainsInitTimeCountdown <= 0.0 )
&& ( true == NoVoltRelay )
&& ( true == OvervoltageRelay )
&& ( LastSwitchingTime > CtrlDelay )
@@ -4228,7 +4341,6 @@ void TMoverParameters::ComputeConstans(void)
double BearingF, RollF, HideModifier;
double Curvature; // Ra 2014-07: odwrotność promienia
TotalMass = ComputeMass();
TotalMassxg = TotalMass * g; // TotalMass*g
BearingF = 2.0 * (DamageFlag && dtrain_bearing);
@@ -4279,29 +4391,28 @@ void TMoverParameters::ComputeConstans(void)
// Q: 20160713
// Oblicza masę ładunku
// *************************************************************************************************
double TMoverParameters::ComputeMass(void)
void TMoverParameters::ComputeMass()
{
double M { 0.0 };
// TODO: unit weight table, pulled from external data file
if( LoadAmount > 0 ) {
if (ToLower(LoadQuantity) == "tonns")
M = LoadAmount * 1000;
else if (LoadType.name == "passengers")
M = LoadAmount * 80;
else if (LoadType.name == "luggage")
M = LoadAmount * 100;
else if (LoadType.name == "cars")
M = LoadAmount * 1200; // 800 kilo to miał maluch
else if (LoadType.name == "containers")
M = LoadAmount * 8000;
else if (LoadType.name == "transformers")
M = LoadAmount * 50000;
else
M = LoadAmount * 1000;
}
// Ra: na razie tak, ale nie wszędzie masy wirujące się wliczają
return Mass + M + Mred;
TotalMass = Mass + Mred;
if( LoadAmount == 0 ) { return; }
// include weight of carried load
auto loadtypeunitweight { 0.f };
if( ToLower( LoadQuantity ) == "tonns" ) {
loadtypeunitweight = 1000;
}
else {
auto const lookup { simulation::Weights.find( LoadType.name ) };
loadtypeunitweight = (
lookup != simulation::Weights.end() ?
lookup->second :
1000.f ); // legacy default unit weight value
}
TotalMass += LoadAmount * loadtypeunitweight;
}
// *************************************************************************************************
@@ -4343,6 +4454,11 @@ void TMoverParameters::ComputeTotalForce(double dt) {
// juz zoptymalizowane:
FStand = FrictionForce(RunningShape.R, RunningTrack.DamageFlag); // siła oporów ruchu
if( true == TestFlag( DamageFlag, dtrain_out ) ) {
// HACK: crude way to reduce speed after derailment
// TBD, TODO: more accurate approach?
FStand *= 1e20;
}
double old_nrot = abs(nrot);
nrot = v2n(); // przeliczenie prędkości liniowej na obrotową
@@ -4635,15 +4751,13 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
auto &othercoupler { othervehicle->Couplers[ otherend ] };
auto const othervehiclemove { ( othervehicle->dMoveLen * DirPatch( End, otherend ) ) };
auto const initialdistance { Neighbours[ End ].distance }; // odległość od sprzęgu sąsiada
auto const distancedelta { (
End == end::front ?
othervehiclemove - dMoveLen :
dMoveLen - othervehiclemove ) };
auto const initialdistance { Neighbours[ End ].distance }; // odległość od sprzęgu sąsiada
auto const newdistance =
initialdistance
+ 10.0 * distancedelta;
auto const newdistance { initialdistance + 10.0 * distancedelta };
auto const dV { V - ( othervehicle->V * DirPatch( End, otherend ) ) };
auto const absdV { std::abs( dV ) };
@@ -4673,11 +4787,15 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
}
coupler.CheckCollision = false;
coupler.Dist = 0.0;
double CF { 0.0 };
if( ( coupler.CouplingFlag != coupling::faux )
|| ( initialdistance < 0 ) ) {
coupler.Dist = clamp( newdistance, -coupler.DmaxB, coupler.DmaxC );
double BetaAvg = 0;
double Fmax = 0;
@@ -4692,8 +4810,8 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
Fmax = 0.5 * ( coupler.FmaxC + coupler.FmaxB + othercoupler.FmaxC + othercoupler.FmaxB ) * CouplerTune;
}
auto const distDelta { std::abs( newdistance ) - std::abs( coupler.Dist ) }; // McZapkie-191103: poprawka na histereze
coupler.Dist = newdistance;
if (coupler.Dist > 0) {
if (newdistance > 0) {
if( distDelta > 0 ) {
CF = ( -( coupler.SpringKC + othercoupler.SpringKC ) * coupler.Dist / 2.0 ) * DirF( End )
@@ -4704,12 +4822,25 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
- Fmax * dV * BetaAvg;
}
// liczenie sily ze sprezystosci sprzegu
if( coupler.Dist > ( coupler.DmaxC + othercoupler.DmaxC ) ) {
if( newdistance > ( coupler.DmaxC + othercoupler.DmaxC ) ) {
// zderzenie
coupler.CheckCollision = true;
}
if( std::abs( CF ) > coupler.FmaxC ) {
// coupler is stretched with excessive force, may break
coupler.stretch_duration += dt;
// give coupler 1 sec of leeway to account for simulation glitches, before checking whether it breaks
// (arbitrary) chance to break grows from 10-100% over 10 sec period
if( ( coupler.stretch_duration > 1.f )
&& ( Random() < ( coupler.stretch_duration * 0.1f * dt ) ) ) {
damage_coupler( End );
}
}
else {
coupler.stretch_duration = 0.f;
}
}
if( coupler.Dist < 0 ) {
if( newdistance < 0 ) {
if( distDelta > 0 ) {
CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End )
@@ -4720,7 +4851,7 @@ double TMoverParameters::CouplerForce( int const End, double dt ) {
- Fmax * dV * BetaAvg;
}
// liczenie sily ze sprezystosci zderzaka
if( -coupler.Dist > ( coupler.DmaxB + othercoupler.DmaxB ) ) {
if( -newdistance > ( coupler.DmaxB + othercoupler.DmaxB ) ) {
// zderzenie
coupler.CheckCollision = true;
if( ( coupler.CouplerType == TCouplerType::Automatic )
@@ -4774,9 +4905,12 @@ double TMoverParameters::TractionForce( double dt ) {
EngineHeatingRPM )
/ 60.0 );
}
// NOTE: fake dizel_fill calculation for the sake of smoke emitter which uses this parameter to determine smoke opacity
dizel_fill = clamp( 0.2 + 0.35 * ( tmp - enrot ), 0.0, 1.0 );
}
else {
tmp = 0.0;
dizel_fill = 0.0;
}
if( enrot != tmp ) {
@@ -5523,12 +5657,12 @@ double TMoverParameters::TractionForce( double dt ) {
eimv[eimv_Fzad] = PosRatio;
if ((Flat) && (eimc[eimc_p_F0] * eimv[eimv_Fful] > 0))
PosRatio = Min0R(PosRatio * eimc[eimc_p_F0] / eimv[eimv_Fful], 1);
/* if (SpeedCtrlValue > 0) //speed control
/* if (ScndCtrlActualPos > 0) //speed control
if (Vmax < 250)
PosRatio = Min0R(PosRatio, Max0R(-1, 0.5 * (SpeedCtrlValue - Vel)));
PosRatio = Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos - Vel)));
else
PosRatio =
Min0R(PosRatio, Max0R(-1, 0.5 * (SpeedCtrlValue * 2 - Vel))); */
Min0R(PosRatio, Max0R(-1, 0.5 * (ScndCtrlActualPos * 2 - Vel))); */
// PosRatio = 1.0 * (PosRatio * 0 + 1) * PosRatio; // 1 * 1 * PosRatio = PosRatio
Hamulec->SetED(0);
// (Hamulec as TLSt).SetLBP(LocBrakePress);
@@ -5616,25 +5750,19 @@ double TMoverParameters::TractionForce( double dt ) {
eimv[eimv_ks] = eimv[eimv_Fr] / 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]; // do przemyslenia dzialanie pp z tmpV
eimv[eimv_fp] = DirAbsolute * enrot * eimc[eimc_s_p] + eimv[eimv_df]; // do przemyslenia dzialanie pp z tmpV
// 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]))
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_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_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_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];
@@ -5655,7 +5783,7 @@ double TMoverParameters::TractionForce( double dt ) {
if( ( RlistSize > 0 )
&& ( ( std::abs( eimv[ eimv_If ] ) > 1.0 )
|| ( tmpV > 0.1 ) ) ) {
&& ( tmpV > 0.1 ) ) ) {
int i = 0;
while( ( i < RlistSize - 1 )
@@ -7386,6 +7514,7 @@ TMoverParameters::AssignLoad( std::string const &Name, float const Amount ) {
if( Name == loadattributes.name ) {
LoadType = loadattributes;
LoadAmount = clamp( Amount, 0.f, MaxLoad ) ;
ComputeMass();
return true;
}
}
@@ -7405,7 +7534,7 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
return true;
}
if( Loadname.empty() ) { return ( LoadStatus >= 4 ); }
if( Loadname.empty() ) { return ( LoadStatus >= 4 ); }
if( Loadname != LoadType.name ) { return ( LoadStatus >= 4 ); }
// test zakończenia załadunku/rozładunku
@@ -7428,6 +7557,7 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
if( LoadAmount == 0.f ) {
AssignLoad(""); // jak nic nie ma, to nie ma też nazwy
}
ComputeMass();
}
}
else if( LSpeed > 0 ) {
@@ -7442,6 +7572,7 @@ bool TMoverParameters::LoadingDone(double const LSpeed, std::string const &Loadn
LoadStatus = 4; // skończony załadunek
LoadAmount = std::min<float>( MaxLoad * ( 1.0 + OverLoadFactor ), LoadAmount );
}
ComputeMass();
}
}
@@ -8614,7 +8745,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue;
}
if (issection("SpeedControl:", inputline))
if (issection("SpeedControl:", inputline))
{
startBPT = false;
fizlines.emplace("SpeedControl", inputline);
@@ -8622,7 +8753,7 @@ bool TMoverParameters::LoadFIZ(std::string chkpath)
continue;
}
if( issection( "Engine:", inputline ) )
if( issection( "Engine:", inputline ) )
{
startBPT = false;
fizlines.emplace( "Engine", inputline );
@@ -9373,6 +9504,8 @@ void TMoverParameters::LoadFIZ_Cntrl( std::string const &line ) {
extract_value( StopBrakeDecc, "SBD", line, "" );
// main circuit
extract_value( MainsInitTime, "MainInitTime", line, "" );
// converter
{
std::map<std::string, start_t> starts {
@@ -10767,10 +10900,13 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
Battery = true;
else if ((CValue1 == 0))
Battery = false;
if ((Battery) && (ActiveCab != 0) /*or (TrainType=dt_EZT)*/)
SecuritySystem.Status = SecuritySystem.Status || s_waiting; // aktywacja czuwaka
/*
// TBD: makes no sense to activate alerters in entire consist
if ((Battery) && (ActiveCab != 0) )
SecuritySystem.Status = SecuritySystem.Status | s_waiting; // aktywacja czuwaka
else
SecuritySystem.Status = 0; // wyłączenie czuwaka
*/
OK = SendCtrlToNext( Command, CValue1, CValue2, Couplertype );
}
// else if command='EpFuseSwitch' then {NBMX}
@@ -11138,3 +11274,9 @@ double TMoverParameters::ShowCurrentP(int AmpN) const
return current;
}
}
namespace simulation {
weights_table Weights;
} // simulation

604
Train.cpp

File diff suppressed because it is too large Load Diff

34
Train.h
View File

@@ -69,8 +69,10 @@ public:
find( TSubModel const *Control ) const;
};
class TTrain
{
class TTrain {
friend class drivingaid_panel;
public:
// types
struct state_t {
@@ -88,6 +90,7 @@ class TTrain
std::uint8_t ventilator_overload;
std::uint8_t motor_overload_threshold;
std::uint8_t train_heating;
std::uint8_t cab;
std::uint8_t recorder_braking;
std::uint8_t recorder_power;
std::uint8_t alerter_sound;
@@ -98,13 +101,15 @@ class TTrain
float brake_pressure;
float hv_voltage;
std::array<float, 3> hv_current;
float lv_voltage;
};
// constructors
TTrain();
// methods
bool CabChange(int iDirection);
bool ShowNextCurrent; // pokaz przd w podlaczonej lokomotywie (ET41)
bool InitializeCab(int NewCabNo, std::string const &asFileName);
TTrain();
// McZapkie-010302
bool Init(TDynamicObject *NewDynamicObject, bool e3d = false);
@@ -113,6 +118,7 @@ class TTrain
inline std::string GetLabel( TSubModel const *Control ) const { return m_controlmapper.find( Control ); }
void UpdateCab();
bool Update( double const Deltatime );
void add_distance( double const Distance );
void SetLights();
// McZapkie-310302: ladowanie parametrow z pliku
bool LoadMMediaFile(std::string const &asFileName);
@@ -151,6 +157,12 @@ class TTrain
void update_sounds( double const Deltatime );
void update_sounds_runningnoise( sound_source &Sound );
void update_sounds_radio();
inline
end cab_to_end() const {
return (
iCabn == 2 ?
end::rear :
end::front ); }
// command handlers
// NOTE: we're currently using universal handlers and static handler map but it may be beneficial to have these implemented on individual class instance basis
@@ -350,6 +362,7 @@ class TTrain
static void OnCommand_radiochanneldecrease( TTrain *Train, command_data const &Command );
static void OnCommand_radiostopsend( TTrain *Train, command_data const &Command );
static void OnCommand_radiostoptest( TTrain *Train, command_data const &Command );
static void OnCommand_radiocall3send( TTrain *Train, command_data const &Command );
static void OnCommand_cabchangeforward( TTrain *Train, command_data const &Command );
static void OnCommand_cabchangebackward( TTrain *Train, command_data const &Command );
static void OnCommand_generictoggle( TTrain *Train, command_data const &Command );
@@ -360,6 +373,7 @@ class TTrain
static void OnCommand_springbrakeshutoffenable(TTrain *Train, command_data const &Command);
static void OnCommand_springbrakeshutoffdisable(TTrain *Train, command_data const &Command);
static void OnCommand_springbrakerelease(TTrain *Train, command_data const &Command);
static void OnCommand_distancecounteractivate( TTrain *Train, command_data const &Command );
static void OnCommand_speedcontrolincrease(TTrain *Train, command_data const &Command);
static void OnCommand_speedcontroldecrease(TTrain *Train, command_data const &Command);
static void OnCommand_speedcontrolpowerincrease(TTrain *Train, command_data const &Command);
@@ -429,7 +443,7 @@ public: // reszta może by?publiczna
TGauge ggUniveralBrakeButton2;
TGauge ggUniveralBrakeButton3;
TGauge ggSandButton; // guzik piasecznicy
TGauge ggAutoSandAllow; // przełącznik piasecznicy
TGauge ggAutoSandButton; // przełącznik piasecznicy
TGauge ggAntiSlipButton;
TGauge ggFuseButton;
TGauge ggConverterFuseButton; // hunter-261211: przycisk odblokowania nadmiarowego przetwornic i ogrzewania
@@ -440,6 +454,7 @@ public: // reszta może by?publiczna
TGauge ggRadioChannelNext;
TGauge ggRadioTest;
TGauge ggRadioStop;
TGauge ggRadioCall3;
TGauge ggUpperLightButton;
TGauge ggLeftLightButton;
TGauge ggRightLightButton;
@@ -472,14 +487,14 @@ public: // reszta może by?publiczna
TGauge ggHelperButton;
TGauge ggNextCurrentButton;
// yB 191005 - tempomat
// yB 191005 - tempomat
TGauge ggSpeedControlIncreaseButton;
TGauge ggSpeedControlDecreaseButton;
TGauge ggSpeedControlPowerIncreaseButton;
TGauge ggSpeedControlPowerDecreaseButton;
std::array<TGauge, 10> ggSpeedCtrlButtons; // NOTE: temporary arrangement until we have dynamically built control table
std::array<TGauge, 10> ggUniversals; // NOTE: temporary arrangement until we have dynamically built control table
std::array<TGauge, 10> ggUniversals; // NOTE: temporary arrangement until we have dynamically built control table
TGauge ggInstrumentLightButton;
TGauge ggDashboardLightButton;
@@ -529,6 +544,8 @@ public: // reszta może by?publiczna
TGauge ggMotorBlowersRearButton; // rear traction motor fan switch
TGauge ggMotorBlowersAllOffButton; // motor fans shutdown switch
TGauge ggDistanceCounterButton; // distance meter activation button
TButton btLampkaPoslizg;
TButton btLampkaStyczn;
TButton btLampkaNadmPrzetw;
@@ -624,6 +641,7 @@ public: // reszta może by?publiczna
TButton btLampkaMotorBlowers;
TButton btLampkaCoolingFans;
TButton btLampkaTempomat;
TButton btLampkaDistanceCounter;
TButton btCabLight; // hunter-171012: lampa oswietlajaca kabine
// Ra 2013-12: wirtualne "lampki" do odbijania na haslerze w PoKeys
@@ -656,6 +674,7 @@ public: // reszta może by?publiczna
sound_source m_radiosound { sound_placement::internal, 2 * EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // cached template for radio messages
std::vector<std::pair<int, std::shared_ptr<sound_source>>> m_radiomessages; // list of currently played radio messages
sound_source m_radiostop { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE };
sound_source m_distancecounterclear { sound_placement::internal, EU07_SOUND_CABCONTROLSCUTOFFRANGE }; // distance meter 'good to go' alert
/*
int iCabLightFlag; // McZapkie:120503: oswietlenie kabiny (0: wyl, 1: przyciemnione, 2: pelne)
bool bCabLight; // hunter-091012: czy swiatlo jest zapalone?
@@ -663,7 +682,7 @@ public: // reszta może by?publiczna
*/
// McZapkie: opis kabiny - obszar poruszania sie mechanika oraz zajetosc
std::array<TCab, maxcab + 1> Cabine; // przedzial maszynowy, kabina 1 (A), kabina 2 (B)
int iCabn { 0 };
int iCabn { 0 }; // 0: mid, 1: front, 2: rear
// McZapkie: do poruszania sie po kabinie
Math3D::vector3 pMechSittingPosition; // ABu 180404
Math3D::vector3 MirrorPosition( bool lewe );
@@ -709,6 +728,7 @@ private:
float m_mastercontrollerreturndelay { 0.f };
int iRadioChannel { 1 }; // numer aktualnego kana?u radiowego
std::vector<std::pair<std::string, texture_handle>> m_screens;
float m_distancecounter { -1.f }; // distance traveled since meter was activated or -1 if inactive
public:
float fPress[20][3]; // cisnienia dla wszystkich czlonow

View File

@@ -132,7 +132,8 @@ commanddescription_sequence Commands_descriptions = {
{ "radiochanneldecrease", command_target::vehicle },
{ "radiostopsend", command_target::vehicle },
{ "radiostoptest", command_target::vehicle },
// TBD, TODO: make cab change controls entity-centric
{ "radiocall3send", command_target::vehicle },
// TBD, TODO: make cab change controls entity-centric
{ "cabchangeforward", command_target::vehicle },
{ "cabchangebackward", command_target::vehicle },
@@ -244,7 +245,8 @@ commanddescription_sequence Commands_descriptions = {
{ "springbrakeshutoffenable", command_target::vehicle },
{ "springbrakeshutoffdisable", command_target::vehicle },
{ "springbrakerelease", command_target::vehicle },
{ "speedcontrolincrease", command_target::vehicle },
{ "distancecounteractivate", command_target::vehicle },
{ "speedcontrolincrease", command_target::vehicle },
{ "speedcontroldecrease", command_target::vehicle },
{ "speedcontrolpowerincrease", command_target::vehicle },
{ "speedcontrolpowerdecrease", command_target::vehicle },

View File

@@ -126,6 +126,7 @@ enum class user_command {
radiochanneldecrease,
radiostopsend,
radiostoptest,
radiocall3send,
cabchangeforward,
cabchangebackward,
@@ -237,6 +238,7 @@ enum class user_command {
springbrakeshutoffenable,
springbrakeshutoffdisable,
springbrakerelease,
distancecounteractivate,
speedcontrolincrease,
speedcontroldecrease,
speedcontrolpowerincrease,