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

build 190902. vehicle derailment, oil pressure change tweak, inverter sound tweak, car braking logic tweak, flashing alerter ui indicator, departure signal sources reduction, additional train state data exposed to uart interface, additional train state data for python scripts, wind simulation tweak, coupler animation fix

This commit is contained in:
tmj-fstate
2019-09-02 19:18:44 +02:00
parent 269e271f01
commit 68a45db21a
16 changed files with 285 additions and 147 deletions

View File

@@ -1138,6 +1138,17 @@ TCommandType TController::TableUpdate(double &fVelDes, double &fDist, double &fN
if( sSpeedTable[ i ].fDist > 0.0 ) {
// check signals ahead
if( sSpeedTable[ i ].IsProperSemaphor( OrderCurrentGet() ) ) {
if( ( mvOccupied->CategoryFlag & 2 )
&& ( sSpeedTable[ i ].fVelNext != -1.0 )
&& ( sSpeedTable[ i ].fVelNext < 1.0 )
&& ( sSpeedTable[ i ].fDist < -0.5 + std::min( fBrakeDist * 0.2, mvOccupied->Vel * 0.2 ) ) ) {
// special rule for cars: ignore stop signals at distance too short to come to a stop
// as trying to stop in such situation is likely to place the car on train tracks
sSpeedTable[ i ].iFlags &= ~spEnabled;
continue;
}
if( SemNextIndex == -1 ) {
// jeśli jest mienięty poprzedni semafor a wcześniej
// byl nowy to go dorzucamy do zmiennej, żeby cały czas widział najbliższy
@@ -5907,7 +5918,7 @@ TController::UpdateSituation(double dt) {
/* mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_FS ) ); GBH */
BrakeLevelSet( gbh_FS );
// don't charge the brakes too often, or we risk overcharging
BrakeChargingCooldown = -120.0;
BrakeChargingCooldown = -1 * clamp( iVehicleCount * 3, 30, 90 );
}
}
/*

View File

@@ -849,16 +849,19 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
//*************************************************************/// koniec
// wezykow
// uginanie zderzakow
for (int i = 0; i < 2; i++)
{
double dist = MoverParameters->Couplers[i].Dist / 2.0;
if (smBuforLewy[i])
if (dist < 0)
for (int i = 0; i < 2; ++i) {
auto const dist { clamp( MoverParameters->Couplers[ i ].Dist / 2.0, -MoverParameters->Couplers[ i ].DmaxB, 0.0 ) };
if( dist >= 0.0 ) { continue; }
if( smBuforLewy[ i ] ) {
smBuforLewy[ i ]->SetTranslate( Math3D::vector3( dist, 0, 0 ) );
if (smBuforPrawy[i])
if (dist < 0)
}
if( smBuforPrawy[ i ] ) {
smBuforPrawy[ i ]->SetTranslate( Math3D::vector3( dist, 0, 0 ) );
}
}
} // vehicle within 50m
// Winger 160204 - podnoszenie pantografow
@@ -2204,12 +2207,9 @@ void TDynamicObject::Move(double fDistance)
// Ra 2F1J: to nie jest stabilne (powoduje rzucanie taborem) i wymaga
// dopracowania
fAdjustment = vFront.Length() - fAxleDist; // na łuku będzie ujemny
// if (fabs(fAdjustment)>0.02) //jeśli jest zbyt dużo, to rozłożyć na kilka
// przeliczeń
// (wygasza drgania?)
// if (fabs(fAdjustment)>0.02) //jeśli jest zbyt dużo, to rozłożyć na kilka przeliczeń (wygasza drgania?)
//{//parę centymetrów trzeba by już skorygować; te błędy mogą się też
// generować na ostrych
//łukach
// generować na ostrych łukach
// fAdjustment*=0.5; //w jednym kroku korygowany jest ułamek błędu
//}
// else
@@ -2784,8 +2784,8 @@ bool TDynamicObject::Update(double dt, double dt1)
auto Frj { 0.0 };
auto osie { 0 };
// 0a. ustal aktualna nastawe zadania sily napedowej i hamowania
if (MoverParameters->Power < 1)
{
if( ( MoverParameters->Power < 1 )
&& ( ctOwner != nullptr ) ) {
MoverParameters->MainCtrlPos = ctOwner->Controlling()->MainCtrlPos*MoverParameters->MainCtrlPosNo / std::max(1, ctOwner->Controlling()->MainCtrlPosNo);
MoverParameters->ScndCtrlActualPos = ctOwner->Controlling()->ScndCtrlActualPos;
}
@@ -3126,7 +3126,10 @@ bool TDynamicObject::Update(double dt, double dt1)
-vPosition.x,
vPosition.z,
vPosition.y };
TRotation r { 0.0, 0.0, 0.0 };
TRotation const r {
0.0,
0.0,
modelRot.z };
// McZapkie-260202 - dMoveLen przyda sie przy stukocie kol
dDOMoveLen = GetdMoveLen() + MoverParameters->ComputeMovement(dt, dt1, ts, tp, tmpTraction, l, r);
if( Mechanik )
@@ -3620,7 +3623,10 @@ bool TDynamicObject::FastUpdate(double dt)
-vPosition.x,
vPosition.z,
vPosition.y };
TRotation r { 0.0, 0.0, 0.0 };
TRotation const r {
0.0,
0.0,
modelRot.z };
// McZapkie: parametry powinny byc pobierane z toru
// ts.R=MyTrack->fRadius;
// ts.Len= Max0R(MoverParameters->BDist,MoverParameters->ADist);
@@ -3904,7 +3910,7 @@ void TDynamicObject::RenderSounds() {
}
// NBMX sygnal odjazdu
if( MoverParameters->Doors.has_warning ) {
for( auto &door : m_doorsounds ) {
for( auto &departuresignalsound : m_departuresignalsounds ) {
// TBD, TODO: per-location door state triggers?
if( ( MoverParameters->DepartureSignal )
/*
@@ -3915,10 +3921,10 @@ void TDynamicObject::RenderSounds() {
) {
// for the autonomous doors play the warning automatically whenever a door is closing
// MC: pod warunkiem ze jest zdefiniowane w chk
door.sDepartureSignal.play( sound_flags::exclusive | sound_flags::looping );
departuresignalsound.play( sound_flags::exclusive | sound_flags::looping );
}
else {
door.sDepartureSignal.stop();
departuresignalsound.stop();
}
}
}
@@ -4227,12 +4233,7 @@ void TDynamicObject::RenderSounds() {
if( MoverParameters->EventFlag ) {
// McZapkie: w razie wykolejenia
if( true == TestFlag( MoverParameters->DamageFlag, dtrain_out ) ) {
if( GetVelocity() > 0 ) {
rsDerailment.play();
}
else {
rsDerailment.stop();
}
rsDerailment.play( sound_flags::exclusive );
}
MoverParameters->EventFlag = false;
@@ -5233,11 +5234,11 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
sound_source soundtemplate { sound_placement::general, 25.f };
soundtemplate.deserialize( parser, sound_type::multipart, sound_parameters::range );
soundtemplate.owner( this );
for( auto &door : m_doorsounds ) {
for( auto &departuresignalsound : m_departuresignalsounds ) {
// apply configuration to all defined doors, but preserve their individual offsets
auto const dooroffset { door.lock.offset() };
door.sDepartureSignal = soundtemplate;
door.sDepartureSignal.offset( dooroffset );
auto const soundoffset { departuresignalsound.offset() };
departuresignalsound = soundtemplate;
departuresignalsound.offset( soundoffset );
}
}
@@ -5391,7 +5392,6 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
// left...
auto const location { glm::vec3 { MoverParameters->Dim.W * 0.5f, MoverParameters->Dim.H * 0.5f, offset } };
door.placement = side::left;
door.sDepartureSignal.offset( location );
door.rsDoorClose.offset( location );
door.rsDoorOpen.offset( location );
door.lock.offset( location );
@@ -5403,9 +5403,8 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
if( ( sides == "both" )
|| ( sides == "right" ) ) {
// ...and right
auto const location { glm::vec3 { MoverParameters->Dim.W * -0.5f, MoverParameters->Dim.H * 0.5f, offset } };
auto const location { glm::vec3 { MoverParameters->Dim.W * -0.5f, 2.f, offset } };
door.placement = side::right;
door.sDepartureSignal.offset( location );
door.rsDoorClose.offset( location );
door.rsDoorOpen.offset( location );
door.lock.offset( location );
@@ -5414,6 +5413,10 @@ void TDynamicObject::LoadMMediaFile( std::string const &TypeName, std::string co
door.step_open.offset( location );
m_doorsounds.emplace_back( door );
}
// potential departure sound, one per door (pair) on vehicle centreline
sound_source departuresignalsound { sound_placement::general, 25.f };
departuresignalsound.offset( glm::vec3{ 0.f, 3.f, offset } );
m_departuresignalsounds.emplace_back( departuresignalsound );
}
}

View File

@@ -319,7 +319,6 @@ private:
};
struct door_sounds {
sound_source sDepartureSignal { sound_placement::general };
sound_source rsDoorOpen { sound_placement::general }; // Ra: przeniesione z kabiny
sound_source rsDoorClose { sound_placement::general };
sound_source lock { sound_placement::general };
@@ -446,6 +445,7 @@ private:
std::array<coupler_sounds, 2> m_couplersounds; // always front and rear
std::vector<pantograph_sounds> m_pantographsounds; // typically 2 but can be less (or more?)
std::vector<door_sounds> m_doorsounds; // can expect symmetrical arrangement, but don't count on it
std::vector<sound_source> m_departuresignalsounds; // single source per door (pair) on the centreline
bool m_doorlocks { false }; // sound helper, current state of door locks
sound_source sHorn1 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE };
sound_source sHorn2 { sound_placement::external, 5 * EU07_SOUND_RUNNINGNOISECUTOFFRANGE };

View File

@@ -649,7 +649,7 @@ global_settings::ConfigParse(cParser &Parser) {
>> uart_conf.updatetime;
}
else if( token == "uarttune" ) {
Parser.getTokens( 14 );
Parser.getTokens( 16 );
Parser
>> uart_conf.mainbrakemin
>> uart_conf.mainbrakemax
@@ -664,7 +664,9 @@ global_settings::ConfigParse(cParser &Parser) {
>> uart_conf.hvmax
>> uart_conf.hvuart
>> uart_conf.currentmax
>> uart_conf.currentuart;
>> uart_conf.currentuart
>> uart_conf.lvmax
>> uart_conf.lvuart;
}
else if( token == "uartfeature" ) {
Parser.getTokens( 4 );

View File

@@ -657,6 +657,7 @@ struct TCoupling {
double CForce = 0.0; /*sila z jaka dzialal*/
double Dist = 0.0; /*strzalka ugiecia zderzaków*/
bool CheckCollision = false; /*czy sprawdzac sile czy pedy*/
float stretch_duration { 0.f }; // seconds, elapsed time with excessive force applied to the coupler
power_coupling power_high;
// power_coupling power_low; // TODO: implement this
@@ -1142,6 +1143,7 @@ public:
/*--opis konkretnego egzemplarza taboru*/
TLocation Loc { 0.0, 0.0, 0.0 }; //pozycja pojazdów do wyznaczenia odległości pomiędzy sprzęgami
TRotation Rot { 0.0, 0.0, 0.0 };
glm::vec3 Front{};
std::string Name; /*nazwa wlasna*/
TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
std::array<neighbour_data, 2> Neighbours; // potential collision sources
@@ -1407,6 +1409,8 @@ public:
bool Attach(int ConnectNo, int ConnectToNr, TMoverParameters *ConnectTo, int CouplingType, bool Forced = false, bool Audible = true);
int DettachStatus(int ConnectNo);
bool Dettach(int ConnectNo);
void damage_coupler( int const End );
void derail( int const Reason );
bool DirectionForward();
bool DirectionBackward( void );/*! kierunek ruchu*/
void BrakeLevelSet(double b);
@@ -1416,8 +1420,8 @@ public:
bool ChangeCab(int direction);
bool CurrentSwitch(bool const State);
void UpdateBatteryVoltage(double dt);
double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, const TLocation &NewLoc, TRotation &NewRot); //oblicza przesuniecie pojazdu
double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, const TLocation &NewLoc, TRotation &NewRot); //oblicza przesuniecie pojazdu - wersja zoptymalizowana
double ComputeMovement(double dt, double dt1, const TTrackShape &Shape, TTrackParam &Track, TTractionParam &ElectricTraction, TLocation const &NewLoc, TRotation const &NewRot); //oblicza przesuniecie pojazdu
double FastComputeMovement(double dt, const TTrackShape &Shape, TTrackParam &Track, TLocation const &NewLoc, TRotation const &NewRot); //oblicza przesuniecie pojazdu - wersja zoptymalizowana
void compute_movement_( double const Deltatime );
double ShowEngineRotation(int VehN);
@@ -1506,7 +1510,7 @@ public:
double BrakeForceP(double press, double velocity);
double BrakeForce(const TTrackParam &Track);
double CouplerForce(int const End, double dt);
void CollisionDetect(int CouplerN, double dt);
void CollisionDetect(int const End, double const dt);
/*obrot kol uwzgledniajacy poslizg*/
double ComputeRotatingWheel(double WForce, double dt, double n) const;

View File

@@ -995,68 +995,140 @@ 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,
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,
othervehiclevelocity, velocity,
othervehicle->TotalMass, TotalMass,
( coupler.beta + othercoupler.beta ) / 2.0,
VirtualCoupling )
/ ( dt );
break; // czemu tu jest +0.01??
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
default: {
break;
}
}
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 );
}
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
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 ) {
if( SetFlag( DamageFlag, dtrain_coupling ) )
EventFlag = true;
if ((coupler.CouplingFlag & ctrain_pneumatic) == ctrain_pneumatic)
AlarmChainFlag = true; // hamowanie nagle - zerwanie przewodow hamulcowych
auto &coupler { Couplers[ End ] };
if( ( coupler.CouplingFlag & ctrain_pneumatic ) == ctrain_pneumatic ) {
// hamowanie nagle - zerwanie przewodow hamulcowych
AlarmChainFlag = true;
}
coupler.CouplingFlag = 0;
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;
if( coupler.Connected != nullptr ) {
switch( End ) {
// break connection with other vehicle, if there's any
case 0: {
coupler.Connected->Couplers[ end::rear ].CouplingFlag = 0;
break;
}
case 1: {
coupler.Connected->Couplers[ end::front ].CouplingFlag = 0;
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" );
}
}
@@ -1065,7 +1137,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;
@@ -1099,9 +1171,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}
{
@@ -1230,17 +1299,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
{
@@ -1716,7 +1782,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 );
}
@@ -4129,6 +4195,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ą
@@ -4418,15 +4489,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 ) };
@@ -4456,11 +4525,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;
@@ -4475,8 +4548,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 )
@@ -4487,12 +4560,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 );
}
if( coupler.Dist < 0 ) {
}
else {
coupler.stretch_duration = 0.f;
}
}
if( newdistance < 0 ) {
if( distDelta > 0 ) {
CF = ( -( coupler.SpringKB + othercoupler.SpringKB ) * coupler.Dist / 2.0 ) * DirF( End )
@@ -4503,7 +4589,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 )
@@ -5402,25 +5488,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];
@@ -5441,7 +5521,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 )

View File

@@ -500,7 +500,7 @@ dictionary_source *TTrain::GetTrainState() {
// induction motor state data
char const *TXTT[ 10 ] = { "fd", "fdt", "fdb", "pd", "pdt", "pdb", "itothv", "1", "2", "3" };
char const *TXTC[ 10 ] = { "fr", "frt", "frb", "pr", "prt", "prb", "im", "vm", "ihv", "uhv" };
char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "res1", "res2" };
char const *TXTD[ 10 ] = { "enrot", "nrot", "fill_des", "fill_real", "clutch_des", "clutch_real", "water_temp", "oil_press", "engine_temp", "res1" };
char const *TXTP[ 3 ] = { "bc", "bp", "sp" };
for( int j = 0; j < 10; ++j )
dict->insert( ( "eimp_t_" + std::string( TXTT[ j ] ) ), fEIMParams[ 0 ][ j ] );
@@ -588,6 +588,7 @@ TTrain::get_state() const {
btLampkaNadmWent.GetValue(),
btLampkaWysRozr.GetValue(),
btLampkaOgrzewanieSkladu.GetValue(),
static_cast<std::uint8_t>( iCabn ),
btHaslerBrakes.GetValue(),
btHaslerCurrent.GetValue(),
( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm ) || TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ),
@@ -597,7 +598,8 @@ TTrain::get_state() const {
static_cast<float>( mvOccupied->PipePress ),
static_cast<float>( mvOccupied->BrakePress ),
fHVoltage,
{ fHCurrent[ ( mvControlled->TrainType & dt_EZT ) ? 0 : 1 ], fHCurrent[ 2 ], fHCurrent[ 3 ] }
{ fHCurrent[ ( mvControlled->TrainType & dt_EZT ) ? 0 : 1 ], fHCurrent[ 2 ], fHCurrent[ 3 ] },
ggLVoltage.GetValue()
};
}
@@ -5375,7 +5377,9 @@ bool TTrain::Update( double const Deltatime )
in++;
iPowerNo = in;
}
if ((in < 8) && (p->MoverParameters->EngineType==TEngineType::DieselEngine))
if ((in < 8)
&& ((p->MoverParameters->EngineType==TEngineType::DieselEngine)
||(p->MoverParameters->EngineType==TEngineType::DieselElectric)))
{
fDieselParams[1 + in][0] = p->MoverParameters->enrot*60;
fDieselParams[1 + in][1] = p->MoverParameters->nrot;
@@ -5385,7 +5389,7 @@ bool TTrain::Update( double const Deltatime )
fDieselParams[1 + in][5] = p->MoverParameters->dizel_engage;
fDieselParams[1 + in][6] = p->MoverParameters->dizel_heat.Twy;
fDieselParams[1 + in][7] = p->MoverParameters->OilPump.pressure;
//fDieselParams[1 + in][8] = p->MoverParameters->
fDieselParams[1 + in][8] = p->MoverParameters->dizel_heat.Ts;
//fDieselParams[1 + in][9] = p->MoverParameters->
bMains[in] = p->MoverParameters->Mains;
fCntVol[in] = p->MoverParameters->BatteryVoltage;

10
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,6 +101,7 @@ class TTrain
float brake_pressure;
float hv_voltage;
std::array<float, 3> hv_current;
float lv_voltage;
};
// methods
@@ -626,7 +630,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 );

View File

@@ -20,6 +20,7 @@ http://mozilla.org/MPL/2.0/.
#include "Camera.h"
#include "mtable.h"
#include "Train.h"
#include "Button.h"
#include "Driver.h"
#include "AnimModel.h"
#include "DynObj.h"
@@ -135,12 +136,14 @@ drivingaid_panel::update() {
}
}
}
std::string textline =
( true == TestFlag( mover->SecuritySystem.Status, s_aware ) ?
std::string textline = (
( ( true == TestFlag( mover->SecuritySystem.Status, s_aware ) )
&& ( train != nullptr )
&& ( train->fBlinkTimer > 0 ) ) ?
locale::strings[ locale::string::driver_aid_alerter ] :
" " );
textline +=
( true == TestFlag( mover->SecuritySystem.Status, s_active ) ?
textline += (
( true == TestFlag( mover->SecuritySystem.Status, s_active ) ) ?
locale::strings[ locale::string::driver_aid_shp ] :
" " );
@@ -961,6 +964,13 @@ debug_panel::update_section_scenario( std::vector<text_line> &Output ) {
textline = "Cloud cover: " + to_string( Global.Overcast, 3 );
textline += "\nLight level: " + to_string( Global.fLuminance, 3 );
if( Global.FakeLight ) { textline += "(*)"; }
textline +=
"\nWind: azimuth "
+ to_string( simulation::Environment.wind_azimuth(), 0 ) // ma być azymut, czyli 0 na północy i rośnie na wschód
+ " "
+ std::string( "N NEE SES SWW NW" )
.substr( 0 + 2 * std::floor( std::fmod( 8 + ( glm::radians( simulation::Environment.wind_azimuth() ) + 0.5 * M_PI_4 ) / M_PI_4, 8 ) ), 2 )
+ ", " + to_string( glm::length( simulation::Environment.wind() ), 1 ) + " m/s";
textline += "\nAir temperature: " + to_string( Global.AirTemperature, 1 ) + " deg C";
Output.emplace_back( textline, Global.UITextColor );

View File

@@ -61,9 +61,9 @@ smoke_source::particle_emitter::initialize( smoke_particle &Particle ) {
auto const azimuthalangle { glm::radians( Random( -180, 180 ) ) }; // phi
// convert spherical coordinates to opengl coordinates
auto const launchvector { glm::vec3(
std::sin( polarangle ) * std::sin( azimuthalangle ),
std::sin( polarangle ) * std::sin( azimuthalangle ) * -1,
std::cos( polarangle ),
std::sin( polarangle ) * std::cos( azimuthalangle ) * -1 ) };
std::sin( polarangle ) * std::cos( azimuthalangle ) ) };
auto const launchvelocity { static_cast<float>( Random( velocity[ value_limit::min ], velocity[ value_limit::max ] ) ) };
Particle.velocity = launchvector * launchvelocity;

View File

@@ -194,13 +194,17 @@ world_environment::update_wind() {
m_wind.change_time -= timedelta;
if( m_wind.change_time < 0 ) {
m_wind.change_time = Random( 5, 30 );
m_wind.velocity_change = Random( -1, 1 );
if( Random() < 0.2 ) {
m_wind.change_time = Random( 5, 15 );
m_wind.velocity_change = Random( -0.2, 0.2 );
if( Random() < 0.05 ) {
// changes in wind direction should be less frequent than changes in wind speed
// TBD, TODO: configuration-driven direction change frequency
m_wind.azimuth_change = Random( -5, 5 );
}
else {
// keep direction change periods short, to avoid too drastic changes in direction
m_wind.azimuth_change = 0.0;
}
}
// TBD, TODO: wind configuration
m_wind.azimuth = clamp_circular( m_wind.azimuth + m_wind.azimuth_change * timedelta );
@@ -213,9 +217,9 @@ world_environment::update_wind() {
m_wind.vector =
std::max( 0.f, m_wind.velocity )
* glm::vec3(
std::sin( polarangle ) * std::sin( azimuthalangle ),
std::sin( polarangle ) * std::sin( azimuthalangle ) * -1,
std::cos( polarangle ),
std::sin( polarangle ) * std::cos( azimuthalangle ) * -1 );
std::sin( polarangle ) * std::cos( azimuthalangle ) );
}
void

View File

@@ -40,6 +40,9 @@ public:
glm::vec3 const &
wind() const {
return m_wind.vector; }
float const &
wind_azimuth() const {
return m_wind.azimuth; }
private:
// types

View File

@@ -56,14 +56,15 @@ basic_station::update_load( TDynamicObject *First, Mtable::TTrainParameters &Sch
// NOTE: for the time being we're doing simple, random load change calculation
// TODO: exchange driven by station parameters and time of the day
auto unloadcount = static_cast<int>(
TestFlag( parameters.DamageFlag, dtrain_out ) ? parameters.LoadAmount :
laststop ? parameters.LoadAmount :
firststop ? 0 :
std::min<float>(
parameters.LoadAmount,
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) ) );
auto loadcount = static_cast<int>(
laststop ?
0 :
TestFlag( parameters.DamageFlag, dtrain_out ) ? 0 :
laststop ? 0 :
Random( parameters.MaxLoad * 0.15f * stationsizemodifier ) );
if( true == firststop ) {
// larger group at the initial station

View File

@@ -242,6 +242,12 @@ void uart_input::poll()
uint16_t current1 = (uint16_t)std::min(conf.currentuart, trainstate.hv_current[0] / conf.currentmax * conf.currentuart);
uint16_t current2 = (uint16_t)std::min(conf.currentuart, trainstate.hv_current[1] / conf.currentmax * conf.currentuart);
uint16_t current3 = (uint16_t)std::min(conf.currentuart, trainstate.hv_current[2] / conf.currentmax * conf.currentuart);
uint16_t lv_voltage = (uint16_t)std::min( conf.lvuart, trainstate.lv_voltage / conf.lvmax * conf.lvuart );
if( trainstate.cab > 0 ) {
// NOTE: moving from a cab to engine room doesn't change cab indicator
m_trainstatecab = trainstate.cab - 1;
}
std::array<uint8_t, 31> buffer {
//byte 0
@@ -271,7 +277,8 @@ void uart_input::poll()
| trainstate.compressor_overload << 6),
//byte 6
(uint8_t)(
trainstate.recorder_braking << 3
m_trainstatecab << 2
| trainstate.recorder_braking << 3
| trainstate.recorder_power << 4
| trainstate.radio_stop <<5
| trainstate.alerter_sound << 7),
@@ -289,8 +296,10 @@ void uart_input::poll()
SPLIT_INT16(current2),
//byte 19-20
SPLIT_INT16(current3),
//byte 21-30
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
//byte 21-22
SPLIT_INT16(lv_voltage),
//byte 23-30
0, 0, 0, 0, 0, 0, 0, 0
};
if (conf.debug)

3
uart.h
View File

@@ -27,6 +27,8 @@ public:
float hvuart = 65535.0f;
float currentmax = 10000.0f;
float currentuart = 65535.0f;
float lvmax = 150.0f;
float lvuart = 65535.0f;
bool mainenable = true;
bool scndenable = true;
@@ -66,4 +68,5 @@ private:
std::chrono::time_point<std::chrono::high_resolution_clock> last_update;
conf_t conf;
bool data_pending = false;
std::uint8_t m_trainstatecab { 0 }; // helper, keeps track of last active cab. 0: front cab, 1: rear cab
};

View File

@@ -1,5 +1,5 @@
#pragma once
#define VERSION_MAJOR 19
#define VERSION_MINOR 809
#define VERSION_MINOR 902
#define VERSION_REVISION 0