mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
build 191115. vehicle voltage circuits logic fixes, ai train manager logic tweak
This commit is contained in:
28
Driver.cpp
28
Driver.cpp
@@ -2156,12 +2156,26 @@ bool TController::CheckVehicles(TOrders user)
|
||||
int pantmask = 1;
|
||||
if (iDrivigFlags & movePrimary)
|
||||
{ // jeśli jest aktywnie prowadzącym pojazd, może zrobić własny porządek
|
||||
p = pVehicles[0];
|
||||
// establish ownership and vehicle order
|
||||
while (p)
|
||||
{
|
||||
if (p->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector)
|
||||
{ // jeśli pojazd posiada pantograf, to przydzielamy mu maskę, którą będzie informował o jeździe bezprądowej
|
||||
p->iOverheadMask = pantmask;
|
||||
pantmask = pantmask << 1; // przesunięcie bitów, max. 32 pojazdy z pantografami w składzie
|
||||
}
|
||||
|
||||
d = p->DirectionSet(d ? 1 : -1); // zwraca położenie następnego (1=zgodny,0=odwrócony - względem czoła składu)
|
||||
p->ctOwner = this; // dominator oznacza swoje terytorium
|
||||
p = p->Next(); // pojazd podłączony od tyłu (licząc od czoła)
|
||||
}
|
||||
// with the order established the virtual train manager can do their work
|
||||
p = pVehicles[0];
|
||||
while (p)
|
||||
{
|
||||
if( p != pVehicle ) {
|
||||
if( ( ( p->MoverParameters->Couplers[ end::front ].CouplingFlag & ( coupling::control ) ) == 0 )
|
||||
&& ( ( p->MoverParameters->Couplers[ end::rear ].CouplingFlag & ( coupling::control ) ) == 0 ) ) {
|
||||
if( false == p->is_connected( pVehicle, coupling::control ) ) {
|
||||
// NOTE: don't set battery in controllable vehicles, let the user/ai do it explicitly
|
||||
// HACK: wagony muszą mieć baterię załączoną do otwarcia drzwi...
|
||||
p->MoverParameters->BatterySwitch( true );
|
||||
@@ -2177,15 +2191,9 @@ bool TController::CheckVehicles(TOrders user)
|
||||
p->DestinationSet(TrainParams.Relation2, TrainParams.TrainName); // relacja docelowa, jeśli nie było
|
||||
if (AIControllFlag) // jeśli prowadzi komputer
|
||||
p->RaLightsSet(0, 0); // gasimy światła
|
||||
if (p->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector)
|
||||
{ // jeśli pojazd posiada pantograf, to przydzielamy mu maskę, którą będzie informował o jeździe bezprądowej
|
||||
p->iOverheadMask = pantmask;
|
||||
pantmask = pantmask << 1; // przesunięcie bitów, max. 32 pojazdy z pantografami w składzie
|
||||
}
|
||||
d = p->DirectionSet(d ? 1 : -1); // zwraca położenie następnego (1=zgodny,0=odwrócony - względem czoła składu)
|
||||
p->ctOwner = this; // dominator oznacza swoje terytorium
|
||||
p = p->Next(); // pojazd podłączony od tyłu (licząc od czoła)
|
||||
}
|
||||
|
||||
if (AIControllFlag)
|
||||
{ // jeśli prowadzi komputer
|
||||
if( true == TestFlag( OrderCurrentGet(), Obey_train ) ) {
|
||||
@@ -2562,7 +2570,7 @@ bool TController::PrepareEngine()
|
||||
}
|
||||
}
|
||||
if( ( mvControlling->EnginePowerSource.SourceType != TPowerSource::CurrentCollector )
|
||||
|| ( std::max( mvControlling->GetTrainsetVoltage(), mvControlling->PantographVoltage ) > mvControlling->EnginePowerSource.CollectorParameters.MinV ) ) {
|
||||
|| ( std::max( mvControlling->GetAnyTrainsetVoltage(), mvControlling->PantographVoltage ) > mvControlling->EnginePowerSource.CollectorParameters.MinV ) ) {
|
||||
mvControlling->MainSwitch( true );
|
||||
}
|
||||
}
|
||||
|
||||
42
DynObj.cpp
42
DynObj.cpp
@@ -2793,7 +2793,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|
||||
|| MoverParameters->PantRearUp ) {
|
||||
|
||||
if( ( MoverParameters->Mains )
|
||||
&& ( MoverParameters->GetTrainsetVoltage() < 0.1f ) ) {
|
||||
&& ( MoverParameters->GetAnyTrainsetVoltage() < 0.1f ) ) {
|
||||
// Ra 15-01: logować tylko, jeśli WS załączony
|
||||
// yB 16-03: i nie jest to asynchron zasilany z daleka
|
||||
// Ra 15-01: bezwzględne współrzędne pantografu nie są dostępne,
|
||||
@@ -6038,30 +6038,60 @@ int TDynamicObject::DirectionSet(int d)
|
||||
};
|
||||
|
||||
// wskaźnik na poprzedni, nawet wirtualny
|
||||
TDynamicObject * TDynamicObject::PrevAny() {
|
||||
TDynamicObject * TDynamicObject::PrevAny() const {
|
||||
return MoverParameters->Neighbours[ iDirection ^ 1 ].vehicle;
|
||||
}
|
||||
TDynamicObject * TDynamicObject::Prev() {
|
||||
TDynamicObject * TDynamicObject::Prev() const {
|
||||
return ( MoverParameters->Couplers[ iDirection ^ 1 ].CouplingFlag != coupling::faux ?
|
||||
MoverParameters->Neighbours[ iDirection ^ 1 ].vehicle :
|
||||
nullptr );// gdy sprzęg wirtualny, to jakby nic nie było
|
||||
}
|
||||
TDynamicObject * TDynamicObject::Next() {
|
||||
TDynamicObject * TDynamicObject::Next() const {
|
||||
return ( MoverParameters->Couplers[ iDirection ].CouplingFlag != coupling::faux ?
|
||||
MoverParameters->Neighbours[ iDirection ].vehicle :
|
||||
nullptr );// gdy sprzęg wirtualny, to jakby nic nie było
|
||||
}
|
||||
TDynamicObject * TDynamicObject::PrevC(int C) {
|
||||
TDynamicObject * TDynamicObject::PrevC(int C) const {
|
||||
return ( ( MoverParameters->Couplers[ iDirection ^ 1 ].CouplingFlag & C ) == C ?
|
||||
MoverParameters->Neighbours[ iDirection ^ 1 ].vehicle :
|
||||
nullptr ); // hide neighbour lacking specified connection type
|
||||
}
|
||||
TDynamicObject * TDynamicObject::NextC(int C) {
|
||||
TDynamicObject * TDynamicObject::NextC(int C) const {
|
||||
return ( ( MoverParameters->Couplers[ iDirection ].CouplingFlag & C ) == C ?
|
||||
MoverParameters->Neighbours[ iDirection ].vehicle :
|
||||
nullptr ); // hide neighbour lacking specified connection type
|
||||
}
|
||||
|
||||
// checks whether there's unbroken connection of specified type to specified vehicle
|
||||
bool
|
||||
TDynamicObject::is_connected( TDynamicObject const *Vehicle, coupling const Coupling ) const {
|
||||
|
||||
auto *vehicle { this };
|
||||
if( vehicle == Vehicle ) {
|
||||
// edge case, vehicle is always "connected" with itself
|
||||
return true;
|
||||
}
|
||||
// check ahead, it's more likely the "owner" using this method is located there
|
||||
while( ( vehicle = vehicle->PrevC( Coupling ) ) != nullptr ) {
|
||||
if( vehicle == Vehicle ) {
|
||||
return true;
|
||||
}
|
||||
if( vehicle == this ) {
|
||||
// edge case, looping consist
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// start anew in the other direction
|
||||
vehicle = this;
|
||||
while( ( vehicle = vehicle->NextC( Coupling ) ) != nullptr ) {
|
||||
if( vehicle == Vehicle ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// no lack in either direction, give up
|
||||
return false;
|
||||
}
|
||||
|
||||
// ustalenie następnego (1) albo poprzedniego (0) w składzie bez względu na prawidłowość iDirection
|
||||
TDynamicObject *
|
||||
TDynamicObject::Neighbour(int &dir) {
|
||||
|
||||
12
DynObj.h
12
DynObj.h
@@ -484,11 +484,13 @@ private:
|
||||
public:
|
||||
int *iLights; // wskaźnik na bity zapalonych świateł (własne albo innego członu)
|
||||
bool DimHeadlights{ false }; // status of the headlight dimming toggle. NOTE: single toggle for all lights is a simplification. TODO: separate per-light switches
|
||||
TDynamicObject * PrevAny();
|
||||
TDynamicObject * Prev();
|
||||
TDynamicObject * Next();
|
||||
TDynamicObject * PrevC(int C);
|
||||
TDynamicObject * NextC(int C);
|
||||
TDynamicObject * PrevAny() const;
|
||||
TDynamicObject * Prev() const;
|
||||
TDynamicObject * Next() const;
|
||||
TDynamicObject * PrevC(int C) const;
|
||||
TDynamicObject * NextC(int C) const;
|
||||
// checks whether there's unbroken connection of specified type to specified vehicle
|
||||
bool is_connected( TDynamicObject const *Vehicle, coupling const Coupling = coupling::coupler ) const;
|
||||
void SetdMoveLen(double dMoveLen) {
|
||||
MoverParameters->dMoveLen = dMoveLen; }
|
||||
void ResetdMoveLen() {
|
||||
|
||||
@@ -1526,7 +1526,8 @@ public:
|
||||
double ShowEngineRotation(int VehN);
|
||||
|
||||
// Q *******************************************************************************************
|
||||
double GetTrainsetVoltage(void);
|
||||
double GetTrainsetVoltage( int const Coupling = ( coupling::heating | coupling::highvoltage ) ) const;
|
||||
double GetAnyTrainsetVoltage() const;
|
||||
bool switch_physics(bool const State);
|
||||
double LocalBrakeRatio(void);
|
||||
double ManualBrakeRatio(void);
|
||||
|
||||
@@ -733,7 +733,7 @@ void TMoverParameters::UpdatePantVolume(double dt)
|
||||
// opuszczenie pantografów przy niskim ciśnieniu
|
||||
if( TrainType != dt_EZT ) {
|
||||
// pressure switch safety measure -- open the line breaker, unless there's alternate source of traction voltage
|
||||
if( GetTrainsetVoltage() < EnginePowerSource.CollectorParameters.MinV ) {
|
||||
if( GetAnyTrainsetVoltage() < EnginePowerSource.CollectorParameters.MinV ) {
|
||||
// TODO: check whether line breaker should be open EMU-wide
|
||||
MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) );
|
||||
}
|
||||
@@ -1472,11 +1472,8 @@ void TMoverParameters::MainsCheck( double const Deltatime ) {
|
||||
|
||||
// TODO: move other main circuit checks here
|
||||
|
||||
if( MainsInitTime == 0.0 ) { return; }
|
||||
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 ) {
|
||||
@@ -1491,8 +1488,18 @@ void TMoverParameters::MainsCheck( double const Deltatime ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( ( localvoltage == 0.0 )
|
||||
&& ( GetTrainsetVoltage() == 0 ) ) {
|
||||
auto const maincircuitpowersupply {
|
||||
( std::abs( localvoltage ) > 0.1 )
|
||||
|| ( GetAnyTrainsetVoltage() > 0.1 ) };
|
||||
|
||||
if( true == maincircuitpowersupply ) {
|
||||
// all is well
|
||||
if( MainsInitTimeCountdown > 0.0 ) {
|
||||
MainsInitTimeCountdown -= Deltatime;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no power supply
|
||||
MainsInitTimeCountdown = MainsInitTime;
|
||||
}
|
||||
}
|
||||
@@ -1507,6 +1514,10 @@ void TMoverParameters::PowerCouplersCheck( double const Deltatime ) {
|
||||
localvoltage = HeatingPowerSource.EngineGenerator.voltage - TotalCurrent * 0.02;
|
||||
break;
|
||||
}
|
||||
case TPowerSource::CurrentCollector: {
|
||||
localvoltage = PantographVoltage;
|
||||
break;
|
||||
}
|
||||
case TPowerSource::Main: {
|
||||
// HACK: main circuit can be fed through couplers, so we explicitly check pantograph supply here
|
||||
localvoltage = (
|
||||
@@ -1641,7 +1652,7 @@ void TMoverParameters::ConverterCheck( double const Timestep ) {
|
||||
&& ( ConverterAllowLocal )
|
||||
&& ( false == PantPressLockActive )
|
||||
&& ( ( Mains )
|
||||
|| ( GetTrainsetVoltage() > 0 ) ) ) {
|
||||
|| ( GetAnyTrainsetVoltage() > 0.0 ) ) ) {
|
||||
// delay timer can be optionally configured, and is set anew whenever converter goes off
|
||||
if( ConverterStartDelayTimer <= 0.0 ) {
|
||||
ConverterFlag = true;
|
||||
@@ -1697,17 +1708,22 @@ void TMoverParameters::HeatingCheck( double const Timestep ) {
|
||||
}
|
||||
// ...detailed check if we're still here
|
||||
auto const heatingpowerthreshold { 0.1 };
|
||||
// start with external power sources
|
||||
// start with blank slate
|
||||
auto voltage { 0.0 };
|
||||
// then try internal ones
|
||||
// then try specified power source
|
||||
switch( HeatingPowerSource.SourceType ) {
|
||||
case TPowerSource::Generator: {
|
||||
voltage = HeatingPowerSource.EngineGenerator.voltage;
|
||||
break;
|
||||
}
|
||||
case TPowerSource::CurrentCollector: {
|
||||
voltage = PantographVoltage;
|
||||
break;
|
||||
}
|
||||
case TPowerSource::PowerCable: {
|
||||
if( HeatingPowerSource.PowerType == TPowerType::ElectricPower ) {
|
||||
voltage = GetTrainsetVoltage();
|
||||
// TBD, TODO: limit input voltage to heating coupling type?
|
||||
voltage = GetAnyTrainsetVoltage();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4501,12 +4517,12 @@ void TMoverParameters::ComputeTotalForce(double dt) {
|
||||
|
||||
if( EngineType == TEngineType::ElectricSeriesMotor ) // potem ulepszyc! pantogtrafy!
|
||||
{ // Ra 2014-03: uwzględnienie kierunku jazdy w napięciu na silnikach, a powinien być zdefiniowany nawrotnik
|
||||
EngineVoltage =
|
||||
std::max(
|
||||
GetTrainsetVoltage(),
|
||||
( Mains ?
|
||||
PantographVoltage :
|
||||
0 ) );
|
||||
EngineVoltage = (
|
||||
Mains ?
|
||||
std::max(
|
||||
GetAnyTrainsetVoltage(),
|
||||
PantographVoltage ) :
|
||||
0.00 );
|
||||
if( CabNo == 0 ) {
|
||||
EngineVoltage *= ActiveDir;
|
||||
}
|
||||
@@ -4515,10 +4531,12 @@ void TMoverParameters::ComputeTotalForce(double dt) {
|
||||
}
|
||||
} // bo nie dzialalo
|
||||
else {
|
||||
EngineVoltage =
|
||||
std::max(
|
||||
GetTrainsetVoltage(),
|
||||
PantographVoltage );
|
||||
EngineVoltage = (
|
||||
Power > 1.0 ?
|
||||
std::max(
|
||||
GetAnyTrainsetVoltage(),
|
||||
PantographVoltage ) :
|
||||
0.0 );
|
||||
}
|
||||
|
||||
FTrain = (
|
||||
@@ -5091,7 +5109,7 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
|
||||
case TEngineType::ElectricSeriesMotor: {
|
||||
// update the state of voltage relays
|
||||
auto const voltage { std::max( GetTrainsetVoltage(), PantographVoltage ) };
|
||||
auto const voltage { std::max( GetAnyTrainsetVoltage(), PantographVoltage ) };
|
||||
NoVoltRelay =
|
||||
( EnginePowerSource.SourceType != TPowerSource::CurrentCollector )
|
||||
|| ( voltage >= EnginePowerSource.CollectorParameters.MinV );
|
||||
@@ -5110,8 +5128,8 @@ double TMoverParameters::TractionForce( double dt ) {
|
||||
// TODO: check if we can use instead the code for electricseriesmotor
|
||||
if( ( Mains ) ) {
|
||||
// nie wchodzić w funkcję bez potrzeby
|
||||
if( ( std::max( GetTrainsetVoltage(), PantographVoltage ) < EnginePowerSource.CollectorParameters.MinV )
|
||||
|| ( std::max( GetTrainsetVoltage(), PantographVoltage ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) {
|
||||
if( ( std::max( GetAnyTrainsetVoltage(), PantographVoltage ) < EnginePowerSource.CollectorParameters.MinV )
|
||||
|| ( std::max( GetAnyTrainsetVoltage(), PantographVoltage ) > EnginePowerSource.CollectorParameters.MaxV + 200 ) ) {
|
||||
MainSwitch( false, ( TrainType == dt_EZT ? range_t::unit : range_t::local ) ); // TODO: check whether we need to send this EMU-wide
|
||||
}
|
||||
}
|
||||
@@ -8096,19 +8114,30 @@ std::string TMoverParameters::EngineDescription(int what) const
|
||||
// Q: 20160709
|
||||
// Funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
|
||||
// *************************************************************************************************
|
||||
double TMoverParameters::GetTrainsetVoltage(void)
|
||||
double TMoverParameters::GetTrainsetVoltage( int const Coupling ) const
|
||||
{//ABu: funkcja zwracajaca napiecie dla calego skladu, przydatna dla EZT
|
||||
return std::max(
|
||||
( ( ( Couplers[end::front].Connected )
|
||||
&& ( Couplers[ end::front ].Connected->Couplers[ Couplers[ end::front ].ConnectedNr ].power_high.is_live ) ) ?
|
||||
&& ( Couplers[ end::front ].Connected->Couplers[ Couplers[ end::front ].ConnectedNr ].power_high.is_live )
|
||||
&& ( ( Couplers[ end::front ].CouplingFlag & Coupling ) != 0 ) ) ?
|
||||
Couplers[end::front].Connected->Couplers[ Couplers[end::front].ConnectedNr ].power_high.voltage :
|
||||
0.0 ),
|
||||
( ( ( Couplers[end::rear].Connected )
|
||||
&& ( Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.is_live ) ) ?
|
||||
&& ( Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.is_live )
|
||||
&& ( ( Couplers[ end::rear ].CouplingFlag & Coupling ) != 0 ) ) ?
|
||||
Couplers[ end::rear ].Connected->Couplers[ Couplers[ end::rear ].ConnectedNr ].power_high.voltage :
|
||||
0.0 ) );
|
||||
}
|
||||
|
||||
double TMoverParameters::GetAnyTrainsetVoltage() const {
|
||||
|
||||
return std::max(
|
||||
GetTrainsetVoltage( coupling::highvoltage ),
|
||||
( HeatingAllow ?
|
||||
GetTrainsetVoltage( coupling::heating ) :
|
||||
0.0 ) );
|
||||
}
|
||||
|
||||
// *************************************************************************************************
|
||||
// Kasowanie zmiennych pracy fizyki
|
||||
// *************************************************************************************************
|
||||
@@ -11278,20 +11307,21 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
}
|
||||
/*naladunek/rozladunek*/
|
||||
// TODO: have these commands leverage load exchange system instead
|
||||
// TODO: CValue1 defines amount to load/unload
|
||||
else if ( issection( "Load=", Command ) )
|
||||
{
|
||||
OK = false; // będzie powtarzane aż się załaduje
|
||||
if( ( Vel < 0.1 ) // tolerance margin for small vehicle movements in the consist
|
||||
&& ( MaxLoad > 0 )
|
||||
&& ( LoadAmount < MaxLoad * ( 1.0 + OverLoadFactor ) )
|
||||
&& ( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) ) { // ten peron/rampa
|
||||
&& ( Distance( Loc, CommandIn.Location, Dim, Dim ) < ( CValue2 > 1.0 ? CValue2 : 10.0 ) ) ) { // ten peron/rampa
|
||||
|
||||
auto const loadname { ToLower( extract_value( "Load", Command ) ) };
|
||||
if( LoadAmount == 0.f ) {
|
||||
AssignLoad( loadname );
|
||||
}
|
||||
OK = LoadingDone(
|
||||
std::min<float>( CValue2, LoadSpeed ),
|
||||
LoadSpeed,
|
||||
loadname ); // zmienia LoadStatus
|
||||
}
|
||||
else {
|
||||
@@ -11304,10 +11334,10 @@ bool TMoverParameters::RunCommand( std::string Command, double CValue1, double C
|
||||
OK = false; // będzie powtarzane aż się rozładuje
|
||||
if( ( Vel < 0.1 ) // tolerance margin for small vehicle movements in the consist
|
||||
&& ( LoadAmount > 0 ) // czy jest co rozladowac?
|
||||
&& ( Distance( Loc, CommandIn.Location, Dim, Dim ) < 10 ) ) { // ten peron
|
||||
&& ( Distance( Loc, CommandIn.Location, Dim, Dim ) < ( CValue2 > 1.0 ? CValue2 : 10.0 ) ) ) { // ten peron
|
||||
/*mozna to rozladowac*/
|
||||
OK = LoadingDone(
|
||||
-1.f * std::min<float>( CValue2, LoadSpeed ),
|
||||
-1.f * LoadSpeed,
|
||||
ToLower( extract_value( "UnLoad", Command ) ) );
|
||||
}
|
||||
else {
|
||||
|
||||
12
Train.cpp
12
Train.cpp
@@ -5701,12 +5701,16 @@ bool TTrain::Update( double const Deltatime )
|
||||
}
|
||||
|
||||
// Ra 2014-09: napięcia i prądy muszą być ustalone najpierw, bo wysyłane są ewentualnie na PoKeys
|
||||
if ((mvControlled->EngineType != TEngineType::DieselElectric)
|
||||
&& (mvControlled->EngineType != TEngineType::ElectricInductionMotor)) // Ra 2014-09: czy taki rozdzia? ma sens?
|
||||
fHVoltage = std::max( mvControlled->PantographVoltage, mvControlled->GetTrainsetVoltage() ); // Winger czy to nie jest zle?
|
||||
if( ( mvControlled->EngineType != TEngineType::DieselElectric )
|
||||
&& ( mvControlled->EngineType != TEngineType::ElectricInductionMotor ) ) { // Ra 2014-09: czy taki rozdzia? ma sens?
|
||||
fHVoltage = std::max(
|
||||
mvControlled->PantographVoltage,
|
||||
mvControlled->GetAnyTrainsetVoltage() ); // Winger czy to nie jest zle?
|
||||
}
|
||||
// *mvControlled->Mains);
|
||||
else
|
||||
else {
|
||||
fHVoltage = mvControlled->EngineVoltage;
|
||||
}
|
||||
if (ShowNextCurrent)
|
||||
{ // jeśli pokazywać drugi człon
|
||||
if (mvSecond)
|
||||
|
||||
Reference in New Issue
Block a user