16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-21 10:19:17 +02:00

basic power circuits simulation, vehicle device presence definition, automatic coupling tweaks, minor vehicle simulation logic enhancements, minor brake simulation logic fixes, pantograph control enhancements, ai logic enhancements

This commit is contained in:
tmj-fstate
2020-04-30 03:08:37 +02:00
parent 17b545e88a
commit c457ffe05d
14 changed files with 946 additions and 662 deletions

View File

@@ -2562,31 +2562,32 @@ bool TController::PrepareEngine()
mvControlling->FuelPumpSwitch( true );
}
}
if (mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector)
{ // jeśli silnikowy jest pantografującym
if (mvControlling->PantPress < 4.2) {
if( ( mvPantographUnit->EnginePowerSource.SourceType == TPowerSource::CurrentCollector )
&&( mvPantographUnit->EnginePowerSource.CollectorParameters.CollectorsNo > 0 ) ) {
// if our pantograph unit isn't a pantograph-devoid fallback
if (mvPantographUnit->PantPress < 4.2) {
// załączenie małej sprężarki
if( false == mvControlling->PantAutoValve ) {
if( false == mvPantographUnit->PantAutoValve ) {
// odłączenie zbiornika głównego, bo z nim nie da rady napompować
mvControlling->bPantKurek3 = false;
mvPantographUnit->bPantKurek3 = false;
}
mvControlling->PantCompFlag = true; // załączenie sprężarki pantografów
mvPantographUnit->PantCompFlag = true; // załączenie sprężarki pantografów
}
else {
// jeżeli jest wystarczające ciśnienie w pantografach
if ((!mvControlling->bPantKurek3)
|| (mvControlling->PantPress <= mvControlling->ScndPipePress)) // kurek przełączony albo główna już pompuje
mvControlling->PantCompFlag = false; // sprężarkę pantografów można już wyłączyć
if ((!mvPantographUnit->bPantKurek3)
|| (mvPantographUnit->PantPress <= mvPantographUnit->ScndPipePress)) // kurek przełączony albo główna już pompuje
mvPantographUnit->PantCompFlag = false; // sprężarkę pantografów można już wyłączyć
}
if( ( fOverhead2 == -1.0 ) && ( iOverheadDown == 0 ) ) {
mvControlling->OperatePantographsValve( operation_t::enable );
mvControlling->OperatePantographValve( end::front, operation_t::enable );
mvControlling->OperatePantographValve( end::rear, operation_t::enable );
mvOccupied->OperatePantographsValve( operation_t::enable );
mvOccupied->OperatePantographValve( end::front, operation_t::enable );
mvOccupied->OperatePantographValve( end::rear, operation_t::enable );
}
}
}
if ((mvControlling->PantographVoltage != 0.0) || voltfront || voltrear)
if ((mvPantographUnit->PantographVoltage != 0.0) || voltfront || voltrear)
{ // najpierw ustalamy kierunek, jeśli nie został ustalony
if( !iDirection ) {
// jeśli nie ma ustalonego kierunku
@@ -2594,7 +2595,7 @@ bool TController::PrepareEngine()
iDirection = mvOccupied->CabActive; // wg wybranej kabiny
if( !iDirection ) {
// jeśli nie ma ustalonego kierunku
if( ( mvControlling->PantographVoltage != 0.0 ) || voltfront || voltrear ) {
if( ( mvPantographUnit->PantographVoltage != 0.0 ) || voltfront || voltrear ) {
if( mvOccupied->Couplers[ end::rear ].Connected == nullptr ) {
// jeśli z tyłu nie ma nic
iDirection = -1; // jazda w kierunku sprzęgu 1
@@ -2622,12 +2623,12 @@ bool TController::PrepareEngine()
}
if (AIControllFlag) // jeśli prowadzi komputer
{ // część wykonawcza dla sterowania przez komputer
if (mvControlling->ConvOvldFlag)
{ // wywalił bezpiecznik nadmiarowy przetwornicy
ZeroSpeed();
mvControlling->ConvOvldFlag = false; // reset nadmiarowego
if( IsAnyConverterOverloadRelayOpen ) {
// wywalił bezpiecznik nadmiarowy przetwornicy
mvOccupied->ConverterSwitch( false );
mvOccupied->RelayReset( relay_t::primaryconverteroverload ); // reset nadmiarowego
}
else if (false == IsLineBreakerClosed) {
if (IsAnyLineBreakerOpen) {
ZeroSpeed();
if( mvOccupied->DirActive == 0 ) {
OrderDirectionChange( iDirection, mvOccupied );
@@ -2641,19 +2642,21 @@ bool TController::PrepareEngine()
}
}
if( ( mvControlling->EnginePowerSource.SourceType != TPowerSource::CurrentCollector )
|| ( std::max( mvControlling->GetAnyTrainsetVoltage(), mvControlling->PantographVoltage ) > mvControlling->EnginePowerSource.CollectorParameters.MinV ) ) {
mvControlling->MainSwitch( true );
|| ( std::max( mvControlling->GetTrainsetHighVoltage(), mvControlling->PantographVoltage ) > mvControlling->EnginePowerSource.CollectorParameters.MinV ) ) {
mvOccupied->MainSwitch( true );
}
}
else {
mvControlling->ConverterSwitch( true );
// w EN57 sprężarka w ra jest zasilana z silnikowego
mvControlling->CompressorSwitch( true );
// enable motor blowers
mvControlling->MotorBlowersSwitchOff( false, end::front );
mvControlling->MotorBlowersSwitch( true, end::front );
mvControlling->MotorBlowersSwitchOff( false, end::rear );
mvControlling->MotorBlowersSwitch( true, end::rear );
else {
if( false == IsAnyConverterOverloadRelayOpen ) {
mvOccupied->ConverterSwitch( true );
// w EN57 sprężarka w ra jest zasilana z silnikowego
mvOccupied->CompressorSwitch( true );
// enable motor blowers
mvOccupied->MotorBlowersSwitchOff( false, end::front );
mvOccupied->MotorBlowersSwitch( true, end::front );
mvOccupied->MotorBlowersSwitchOff( false, end::rear );
mvOccupied->MotorBlowersSwitch( true, end::rear );
}
// enable train brake if it's off
if( mvOccupied->fBrakeCtrlPos == mvOccupied->Handle->GetPos( bh_NP ) ) {
mvOccupied->BrakeLevelSet( mvOccupied->Handle->GetPos( bh_RP ) );
@@ -2667,7 +2670,8 @@ bool TController::PrepareEngine()
if( lookup != brakepositions.end() ) {
BrakeLevelSet( lookup->second ); // GBH
}
OK = ( VelforDriver == -1 );
OK = ( false == IsAnyConverterOverloadRelayOpen )
&& ( VelforDriver == -1 );
}
}
else
@@ -2755,13 +2759,12 @@ bool TController::ReleaseEngine() {
// heating
mvControlling->HeatingAllow = false;
// devices
mvControlling->ConverterSwitch( false );
mvOccupied->ConverterSwitch( false );
// line breaker/engine
OK = mvControlling->MainSwitch( false );
if( mvControlling->EnginePowerSource.SourceType == TPowerSource::CurrentCollector ) {
mvControlling->OperatePantographValve( end::front, operation_t::disable );
mvControlling->OperatePantographValve( end::rear, operation_t::disable );
}
OK = mvOccupied->MainSwitch( false );
mvOccupied->OperatePantographValve( end::front, operation_t::disable );
mvOccupied->OperatePantographValve( end::rear, operation_t::disable );
}
else {
OK = true;
@@ -3200,7 +3203,7 @@ bool TController::IncSpeed()
if (iOverheadZero) // jazda bezprądowa z poziomu toru ustawia bity
return false; // to nici z ruszania
}
if ((!mvControlling->FuseFlag)
if ((!IsAnyMotorOverloadRelayOpen)
&&(!mvControlling->ControlPressureSwitch)) {
if ((mvControlling->IsMainCtrlNoPowerPos())
|| (mvControlling->StLinFlag)) { // youBy polecił dodać 2012-09-08 v367
@@ -3303,7 +3306,7 @@ bool TController::IncSpeed()
mvControlling->AutoRelayCheck(); // sprawdzenie logiki sterowania
break;
case TEngineType::Dumb:
if (!mvControlling->FuseFlag)
if (!IsAnyMotorOverloadRelayOpen)
if (Ready || (iDrivigFlags & movePress)) //{(BrakePress<=0.01*MaxBrakePress)}
{
OK = IncSpeedEIM();
@@ -3314,7 +3317,7 @@ bool TController::IncSpeed()
}
break;
case TEngineType::DieselElectric:
if ((!mvControlling->FuseFlag)
if ((!IsAnyMotorOverloadRelayOpen)
&&(!mvControlling->ControlPressureSwitch)) {
if ((mvControlling->IsMainCtrlNoPowerPos()) ||
(mvControlling->StLinFlag)) { // youBy polecił dodać 2012-09-08 v367
@@ -3331,7 +3334,7 @@ bool TController::IncSpeed()
}
break;
case TEngineType::ElectricInductionMotor:
if (!mvControlling->FuseFlag)
if (!IsAnyMotorOverloadRelayOpen)
if (Ready || (iDrivigFlags & movePress) || (mvOccupied->ShuntMode)) //{(BrakePress<=0.01*MaxBrakePress)}
{
OK = IncSpeedEIM();
@@ -3390,9 +3393,9 @@ bool TController::IncSpeed()
}
if( false == mvControlling->Mains ) {
SpeedCntrl(0.0);
mvControlling->MainSwitch( true );
mvControlling->ConverterSwitch( true );
mvControlling->CompressorSwitch( true );
mvOccupied->MainSwitch( true );
mvOccupied->ConverterSwitch( true );
mvOccupied->CompressorSwitch( true );
}
break;
}
@@ -4612,7 +4615,7 @@ TController::UpdateSituation(double dt) {
if( ( OrderCurrentGet() == Wait_for_orders )
&& ( false == AIControllFlag )
&& ( false == iEngineActive )
&& ( true == mvControlling->Battery ) ) {
&& ( true == mvOccupied->Power24vIsAvailable ) ) {
OrderNext( Prepare_engine );
}
@@ -4686,10 +4689,6 @@ TController::UpdateSituation(double dt) {
// ciężar razy składowa styczna grawitacji
fAccGravity -= vehicle->TotalMassxg * dy * ( p->DirectionGet() == iDirection ? 1 : -1 );
}
if( ( vehicle->Power > 0.01 ) // jeśli ma silnik
&& ( vehicle->FuseFlag ) ) { // wywalony nadmiarowy
Need_TryAgain = true; // reset jak przy wywaleniu nadmiarowego
}
// check door state
auto const switchsides { p->DirectionGet() != iDirection };
IsAnyDoorOpen[ side::right ] =
@@ -4707,21 +4706,31 @@ TController::UpdateSituation(double dt) {
ConsistShade /= iVehicles;
// test state of main switch in all powered vehicles under control
IsLineBreakerClosed = ( mvOccupied->Power > 0.01 ? mvOccupied->Mains : true );
IsAnyConverterOverloadRelayOpen = mvOccupied->ConvOvldFlag;
IsAnyMotorOverloadRelayOpen = mvOccupied->FuseFlag;
IsAnyGroundRelayOpen = !mvOccupied->GroundRelay;
IsAnyLineBreakerOpen = ( mvOccupied->Power > 0.01 ? !mvOccupied->Mains : false );
IsAnyCompressorEnabled = mvOccupied->CompressorAllow;
p = pVehicle;
while( ( true == IsLineBreakerClosed )
&& ( ( p = p->PrevC( coupling::control) ) != nullptr ) ) {
while( ( p = p->PrevC( coupling::control) ) != nullptr ) {
auto const *vehicle { p->MoverParameters };
IsAnyConverterOverloadRelayOpen |= vehicle->ConvOvldFlag;
IsAnyMotorOverloadRelayOpen |= vehicle->FuseFlag;
IsAnyGroundRelayOpen |= !vehicle->GroundRelay;
IsAnyCompressorEnabled |= vehicle->CompressorAllow;
if( vehicle->Power > 0.01 ) {
IsLineBreakerClosed = ( IsLineBreakerClosed && vehicle->Mains );
IsAnyLineBreakerOpen |= !vehicle->Mains;
}
}
p = pVehicle;
while( ( true == IsLineBreakerClosed )
&& ( ( p = p->NextC( coupling::control ) ) != nullptr ) ) {
while( ( p = p->NextC( coupling::control ) ) != nullptr ) {
auto const *vehicle { p->MoverParameters };
IsAnyConverterOverloadRelayOpen |= vehicle->ConvOvldFlag;
IsAnyMotorOverloadRelayOpen |= vehicle->FuseFlag;
IsAnyGroundRelayOpen |= !vehicle->GroundRelay;
IsAnyCompressorEnabled |= vehicle->CompressorAllow;
if( vehicle->Power > 0.01 ) {
IsLineBreakerClosed = ( IsLineBreakerClosed && vehicle->Mains );
IsAnyLineBreakerOpen |= !vehicle->Mains;
}
}
@@ -4795,7 +4804,7 @@ TController::UpdateSituation(double dt) {
}
// uśrednione napięcie sieci: przy spadku poniżej wartości minimalnej opóźnić rozruch o losowy czas
fVoltage = 0.5 * (fVoltage + std::max( mvControlling->GetAnyTrainsetVoltage(), mvControlling->PantographVoltage ) );
fVoltage = 0.5 * (fVoltage + std::max( mvControlling->GetTrainsetHighVoltage(), mvControlling->PantographVoltage ) );
if( fVoltage < mvControlling->EnginePowerSource.CollectorParameters.MinV ) {
// gdy rozłączenie WS z powodu niskiego napięcia
if( fActionTime >= PrepareTime ) {
@@ -4840,11 +4849,11 @@ TController::UpdateSituation(double dt) {
if( ( fOverhead2 > 0.0 ) || iOverheadDown ) {
// jazda z opuszczonymi pantografami
if( mvControlling->Pantographs[ end::front ].is_active ) {
mvControlling->OperatePantographValve( end::front, operation_t::disable );
if( mvPantographUnit->Pantographs[ end::front ].is_active ) {
mvOccupied->OperatePantographValve( end::front, operation_t::disable );
}
if( mvControlling->Pantographs[ end::rear ].is_active ) {
mvControlling->OperatePantographValve( end::rear, operation_t::disable );
if( mvPantographUnit->Pantographs[ end::rear ].is_active ) {
mvOccupied->OperatePantographValve( end::rear, operation_t::disable );
}
}
else {
@@ -4854,37 +4863,37 @@ TController::UpdateSituation(double dt) {
// jazda na tylnym
if( ( iDirection >= 0 ) && ( useregularpantographlayout ) ) {
// jak jedzie w kierunku sprzęgu 0
if( ( mvControlling->PantRearVolt == 0.0 )
if( ( mvPantographUnit->PantRearVolt == 0.0 )
// filter out cases with single _other_ working pantograph so we don't try to raise something we can't
&& ( ( mvControlling->PantographVoltage == 0.0 )
|| ( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) {
mvControlling->OperatePantographValve( end::rear, operation_t::enable );
&& ( ( mvPantographUnit->PantographVoltage == 0.0 )
|| ( mvPantographUnit->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) {
mvOccupied->OperatePantographValve( end::rear, operation_t::enable );
}
}
else {
// jak jedzie w kierunku sprzęgu 0
if( ( mvControlling->PantFrontVolt == 0.0 )
if( ( mvPantographUnit->PantFrontVolt == 0.0 )
// filter out cases with single _other_ working pantograph so we don't try to raise something we can't
&& ( ( mvControlling->PantographVoltage == 0.0 )
|| ( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) {
mvControlling->OperatePantographValve( end::front, operation_t::enable );
&& ( ( mvPantographUnit->PantographVoltage == 0.0 )
|| ( mvPantographUnit->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) ) ) {
mvOccupied->OperatePantographValve( end::front, operation_t::enable );
}
}
if( mvOccupied->Vel > 5 ) {
// opuszczenie przedniego po rozpędzeniu się o ile jest więcej niż jeden
if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) {
if( mvPantographUnit->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) {
if( ( iDirection >= 0 ) && ( useregularpantographlayout ) ) // jak jedzie w kierunku sprzęgu 0
{ // poczekać na podniesienie tylnego
if( ( mvControlling->PantFrontVolt != 0.0 )
&& ( mvControlling->PantRearVolt != 0.0 ) ) { // czy jest napięcie zasilające na tylnym?
mvControlling->OperatePantographValve( end::front, operation_t::disable ); // opuszcza od sprzęgu 0
if( ( mvPantographUnit->PantFrontVolt != 0.0 )
&& ( mvPantographUnit->PantRearVolt != 0.0 ) ) { // czy jest napięcie zasilające na tylnym?
mvOccupied->OperatePantographValve( end::front, operation_t::disable ); // opuszcza od sprzęgu 0
}
}
else { // poczekać na podniesienie przedniego
if( ( mvControlling->PantRearVolt != 0.0 )
&& ( mvControlling->PantFrontVolt != 0.0 ) ) { // czy jest napięcie zasilające na przednim?
mvControlling->OperatePantographValve( end::rear, operation_t::disable ); // opuszcza od sprzęgu 1
if( ( mvPantographUnit->PantRearVolt != 0.0 )
&& ( mvPantographUnit->PantFrontVolt != 0.0 ) ) { // czy jest napięcie zasilające na przednim?
mvOccupied->OperatePantographValve( end::rear, operation_t::disable ); // opuszcza od sprzęgu 1
}
}
}
@@ -4895,12 +4904,12 @@ TController::UpdateSituation(double dt) {
// use suggested pantograph setup
if( mvOccupied->Vel > 5 ) {
auto const pantographsetup{ mvOccupied->AIHintPantstate };
mvControlling->OperatePantographValve(
mvOccupied->OperatePantographValve(
end::front,
( pantographsetup & ( 1 << 0 ) ?
operation_t::enable :
operation_t::disable ) );
mvControlling->OperatePantographValve(
mvOccupied->OperatePantographValve(
end::rear,
( pantographsetup & ( 1 << 1 ) ?
operation_t::enable :
@@ -4946,16 +4955,16 @@ TController::UpdateSituation(double dt) {
// NOTE: abs(stoptime) covers either at least 15 sec remaining for a scheduled stop, or 15+ secs spent at a basic stop
&& ( std::abs( fStopTime ) > 15.0 ) ) {
// spending a longer at a stop, raise also front pantograph
if( mvControlling->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) {
if( mvPantographUnit->EnginePowerSource.CollectorParameters.CollectorsNo > 1 ) {
if( ( iDirection >= 0 ) && ( useregularpantographlayout ) ) {
// jak jedzie w kierunku sprzęgu 0
if( mvControlling->PantFrontVolt == 0.0 ) {
mvControlling->OperatePantographValve( end::front, operation_t::enable );
if( mvPantographUnit->PantFrontVolt == 0.0 ) {
mvOccupied->OperatePantographValve( end::front, operation_t::enable );
}
}
else {
if( mvControlling->PantRearVolt == 0.0 ) {
mvControlling->OperatePantographValve( end::rear, operation_t::enable );
if( mvPantographUnit->PantRearVolt == 0.0 ) {
mvOccupied->OperatePantographValve( end::rear, operation_t::enable );
}
}
}
@@ -6237,29 +6246,31 @@ TController::UpdateSituation(double dt) {
return; // ...and don't touch any other controls
}
if( ( true == mvControlling->ConvOvldFlag ) // wywalił bezpiecznik nadmiarowy przetwornicy
|| ( false == IsLineBreakerClosed ) ) { // WS może wywalić z powodu błędu w drutach
if( ( IsAnyConverterOverloadRelayOpen ) // wywalił bezpiecznik nadmiarowy przetwornicy
|| ( IsAnyLineBreakerOpen ) ) { // WS może wywalić z powodu błędu w drutach
// próba ponownego załączenia
PrepareEngine();
}
// włączanie bezpiecznika
if ((mvControlling->EngineType == TEngineType::ElectricSeriesMotor) ||
(mvControlling->TrainType & dt_EZT) ||
(mvControlling->EngineType == TEngineType::DieselElectric))
if (mvControlling->FuseFlag || Need_TryAgain || (false == mvControlling->GroundRelay))
{
Need_TryAgain = false; // true, jeśli druga pozycja w elektryku nie załapała
mvControlling->DecScndCtrl(2); // nastawnik bocznikowania na 0
mvControlling->DecMainCtrl(2); // nastawnik jazdy na 0
if (mvControlling->FuseOn()) {
++iDriverFailCount;
if (iDriverFailCount > maxdriverfails)
Psyche = Easyman;
if (iDriverFailCount > maxdriverfails * 2)
SetDriverPsyche();
}
mvControlling->MainSwitch(true); // Ra: dodałem, bo EN57 stawały po wywaleniu
if( ( mvControlling->EngineType == TEngineType::ElectricSeriesMotor )
|| ( mvControlling->EngineType == TEngineType::DieselElectric )
|| ( mvControlling->TrainType == dt_EZT ) ) {
if( Need_TryAgain ) {
// true, jeśli druga pozycja w elektryku nie załapała
ZeroSpeed();
Need_TryAgain = false;
}
if( IsAnyMotorOverloadRelayOpen || IsAnyGroundRelayOpen ) {
ZeroSpeed();
mvOccupied->FuseOn();
mvControlling->MainSwitch( true ); // Ra: dodałem, bo EN57 stawały po wywaleniu
++iDriverFailCount;
if( iDriverFailCount > maxdriverfails )
Psyche = Easyman;
if( iDriverFailCount > maxdriverfails * 2 )
SetDriverPsyche();
}
}
// NOTE: as a stop-gap measure the routine is limited to trains only while car calculations seem off
if( mvControlling->CategoryFlag == 1 ) {
if( vel < VelDesired ) {
@@ -6542,7 +6553,7 @@ TController::UpdateSituation(double dt) {
else
{ // tutaj, gdy pojazd jest wyłączony
if (!AIControllFlag) // jeśli sterowanie jest w gestii użytkownika
if (mvOccupied->Battery) // czy użytkownik załączył baterię?
if (mvOccupied->Power24vIsAvailable) // czy użytkownik załączył baterię?
if (mvOccupied->DirActive) // czy ustawił kierunek
{ // jeśli tak, to uruchomienie skanowania
CheckVehicles(); // sprawdzić skład
@@ -7385,7 +7396,14 @@ void TController::ControllingSet()
// dzięki temu będzie wirtualna kabina w silnikowym, działająca w rozrządczym
// w plikach FIZ zostały zgubione ujemne maski sprzęgów, stąd problemy z EZT
mvOccupied = pVehicle->MoverParameters; // domyślny skrót do obiektu parametrów
mvControlling = pVehicle->ControlledFind()->MoverParameters; // poszukiwanie członu sterowanego
mvControlling = pVehicle->FindPowered()->MoverParameters; // poszukiwanie członu sterowanego
{
auto *lookup { pVehicle->FindPantographCarrier() };
mvPantographUnit = (
lookup != nullptr ?
lookup->MoverParameters :
mvControlling );
}
};
std::string TController::TableText( std::size_t const Index ) const

129
Driver.h
View File

@@ -193,19 +193,22 @@ public:
// ai operations logic
// methods
public:
void UpdateSituation(double dt); // uruchamiac przynajmniej raz na sekundę
void MoveTo(TDynamicObject *to);
void TakeControl(bool const Aidriver, bool const Forcevehiclecheck = false);
void UpdateSituation( double dt ); // uruchamiac przynajmniej raz na sekundę
void MoveTo( TDynamicObject *to );
void TakeControl( bool const Aidriver, bool const Forcevehiclecheck = false );
inline
bool primary( bool const Primary ) {
bool primary( bool const Primary ) {
SetFlag( iDrivigFlags, ( Primary ? movePrimary : -movePrimary ) );
return primary(); }
return primary();
}
inline
bool primary() const {
return ( ( iDrivigFlags & movePrimary ) != 0 ); };
bool primary() const {
return ( ( iDrivigFlags & movePrimary ) != 0 );
};
inline
TMoverParameters const *Controlling() const {
return mvControlling; }
TMoverParameters const *Controlling() const {
return mvControlling;
}
inline
TMoverParameters const *Occupied() const {
return mvOccupied;
@@ -213,14 +216,17 @@ public:
void DirectionInitial();
void DirectionChange();
inline
int Direction() const {
return iDirection; }
int Direction() const {
return iDirection;
}
inline
TAction & action() {
return eAction; }
inline
TAction const & action() const {
return eAction; }
TAction & action() {
return eAction;
}
inline
TAction const & action() const {
return eAction;
}
private:
void Activation(); // umieszczenie obsady w odpowiednim członie
void ControllingSet(); // znajduje człon do sterowania
@@ -229,54 +235,56 @@ private:
bool DecBrake();
bool ZeroLocalBrake();
bool IncSpeed();
bool DecSpeed(bool force = false);
bool DecSpeed( bool force = false );
void ZeroSpeed( bool const Enforce = false );
bool IncBrakeEIM();
bool DecBrakeEIM();
bool IncSpeedEIM();
bool DecSpeedEIM();
void BrakeLevelSet(double b);
bool BrakeLevelAdd(double b);
bool IncBrakeEIM();
bool DecBrakeEIM();
bool IncSpeedEIM();
bool DecSpeedEIM();
void BrakeLevelSet( double b );
bool BrakeLevelAdd( double b );
void SpeedSet();
void SpeedCntrl(double DesiredSpeed);
void SetTimeControllers(); /*setting state of time controllers depending of desired action*/
void CheckTimeControllers(); /*checking state of time controllers to reset them to stable position*/
double ESMVelocity(bool Main);
void SpeedCntrl( double DesiredSpeed );
void SetTimeControllers(); /*setting state of time controllers depending of desired action*/
void CheckTimeControllers(); /*checking state of time controllers to reset them to stable position*/
double ESMVelocity( bool Main );
bool UpdateHeating();
// uaktualnia informacje o prędkości
void SetVelocity(double NewVel, double NewVelNext, TStopReason r = stopNone);
void SetVelocity( double NewVel, double NewVelNext, TStopReason r = stopNone );
int CheckDirection();
void WaitingSet(double Seconds);
void DirectionForward(bool forward);
void WaitingSet( double Seconds );
void DirectionForward( bool forward );
void ZeroDirection();
int OrderDirectionChange(int newdir, TMoverParameters *Vehicle);
int OrderDirectionChange( int newdir, TMoverParameters *Vehicle );
void sync_consist_reversers();
void Lights(int head, int rear);
void Lights( int head, int rear );
std::string StopReasonText() const;
double BrakeAccFactor() const;
// modifies brake distance for low target speeds, to ease braking rate in such situations
float
braking_distance_multiplier( float const Targetvelocity ) const;
inline
int DrivigFlags() const {
return iDrivigFlags; };
int DrivigFlags() const {
return iDrivigFlags;
};
// members
public:
bool AIControllFlag = false; // rzeczywisty/wirtualny maszynista
int iOverheadZero = 0; // suma bitowa jezdy bezprądowej, bity ustawiane przez pojazdy z podniesionymi pantografami
int iOverheadDown = 0; // suma bitowa opuszczenia pantografów, bity ustawiane przez pojazdy z podniesionymi pantografami
double BrakeCtrlPosition = 0.0; // intermediate position of main brake controller
int UniversalBrakeButtons = 0.0; // flag of which universal buttons need to be pressed
int DizelPercentage = 0; // oczekiwane procenty jazdy/hamowania szynobusem
int DizelPercentage_Speed = 0; // oczekiwane procenty jazdy/hamowania szynobusem w związku z osiąganiem VelDesired
int UniversalBrakeButtons = 0.0; // flag of which universal buttons need to be pressed
int DizelPercentage = 0; // oczekiwane procenty jazdy/hamowania szynobusem
int DizelPercentage_Speed = 0; // oczekiwane procenty jazdy/hamowania szynobusem w związku z osiąganiem VelDesired
private:
bool Psyche = false;
int HelperState = 0; //stan pomocnika maszynisty
TDynamicObject *pVehicle = nullptr; // pojazd w którym siedzi sterujący
TMoverParameters *mvControlling = nullptr; // jakim pojazdem steruje (może silnikowym w EZT)
TMoverParameters *mvOccupied = nullptr; // jakim pojazdem hamuje
TMoverParameters *mvPantographUnit = nullptr; //pantograph equipped vehicle in the occupied/controlled set
std::string VehicleName;
std::array<int, 2> m_lighthints { -1 }; // suggested light patterns
std::array<int, 2> m_lighthints = { -1, -1 }; // suggested light patterns
double AccPreferred = 0.0; // preferowane przyspieszenie (wg psychiki kierującego, zmniejszana przy wykryciu kolizji)
double AccDesired = AccPreferred; // przyspieszenie, jakie ma utrzymywać (<0:nie przyspieszaj,<-0.1:hamuj)
double VelDesired = 0.0; // predkość, z jaką ma jechać, wynikająca z analizy tableki; <=VelSignal
@@ -311,7 +319,7 @@ private:
double fWarningDuration = 0.0; // ile czasu jeszcze trąbić
double WaitingTime = 0.0; // zliczany czas oczekiwania do samoistnego ruszenia
double WaitingExpireTime = 31.0; // tyle ma czekać, zanim się ruszy // maksymlany czas oczekiwania do samoistnego ruszenia
double IdleTime {}; // keeps track of time spent at a stop
double IdleTime{}; // keeps track of time spent at a stop
double fStopTime = 0.0; // czas postoju przed dalszą jazdą (np. na przystanku)
float ExchangeTime{ 0.0 }; // time needed to finish current load exchange
double fShuntVelocity = 40.0; // maksymalna prędkość manewrowania, zależy m.in. od składu // domyślna prędkość manewrowa
@@ -323,29 +331,29 @@ private:
double fDriverDist = 0.0; // dopuszczalna odległość podjechania do przeszkody
double fVelMax = -1.0; // maksymalna prędkość składu (sprawdzany każdy pojazd)
double fBrakeDist = 0.0; // przybliżona droga hamowania
double fBrakeReaction = 1.0; //opóźnienie zadziałania hamulca - czas w s / (km/h)
double fNominalAccThreshold = 0.0; // nominalny próg opóźnienia dla zadziałania hamulca
double fBrakeReaction = 1.0; //opóźnienie zadziałania hamulca - czas w s / (km/h)
double fNominalAccThreshold = 0.0; // nominalny próg opóźnienia dla zadziałania hamulca
double fAccThreshold = 0.0; // aktualny próg opóźnienia dla zadziałania hamulca
double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca
double AbsAccS_pub = 0.0; // próg opóźnienia dla zadziałania hamulca
// dla fBrake_aX:
// indeks [0] - wartości odpowiednie dla aktualnej prędkości
// a potem jest 20 wartości dla różnych prędkości zmieniających się co 5 % Vmax pojazdu obsadzonego
double fBrake_a0[BrakeAccTableSize+1] = { 0.0 }; // opóźnienia hamowania przy ustawieniu zaworu maszynisty w pozycji 1.0
double fBrake_a1[BrakeAccTableSize+1] = { 0.0 }; // przyrost opóźnienia hamowania po przestawieniu zaworu maszynisty o 0,25 pozycji
double fBrake_a0[ BrakeAccTableSize + 1 ] = { 0.0 }; // opóźnienia hamowania przy ustawieniu zaworu maszynisty w pozycji 1.0
double fBrake_a1[ BrakeAccTableSize + 1 ] = { 0.0 }; // przyrost opóźnienia hamowania po przestawieniu zaworu maszynisty o 0,25 pozycji
double BrakingInitialLevel{ 1.0 };
double BrakingLevelIncrease{ 0.25 };
double ReactionTime = 0.0; // czas reakcji Ra: czego i na co? świadomości AI
double fBrakeTime = 0.0; // wpisana wartość jest zmniejszana do 0, gdy ujemna należy zmienić nastawę hamulca
double BrakeChargingCooldown {}; // prevents the ai from trying to charge the train brake too frequently
double BrakeChargingCooldown{}; // prevents the ai from trying to charge the train brake too frequently
double LastReactionTime = 0.0;
double fActionTime = 0.0; // czas używany przy regulacji prędkości i zamykaniu drzwi
double m_radiocontroltime{ 0.0 }; // timer used to control speed of radio operations
TAction eAction { TAction::actUnknown }; // aktualny stan
TAction eAction{ TAction::actUnknown }; // aktualny stan
// orders
// methods
public:
void PutCommand(std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation, TStopReason reason = stopComm);
void PutCommand( std::string NewCommand, double NewValue1, double NewValue2, const TLocation &NewLocation, TStopReason reason = stopComm );
bool PutCommand( std::string NewCommand, double NewValue1, double NewValue2, glm::dvec3 const *NewLocation, TStopReason reason = stopComm );
// defines assignment data
inline auto assignment() -> std::string & { return m_assignment; }
@@ -355,15 +363,15 @@ private:
void RecognizeCommand(); // odczytuje komende przekazana lokomotywie
void JumpToNextOrder();
void JumpToFirstOrder();
void OrderPush(TOrders NewOrder);
void OrderNext(TOrders NewOrder);
void OrderPush( TOrders NewOrder );
void OrderNext( TOrders NewOrder );
inline TOrders OrderCurrentGet() const;
inline TOrders OrderNextGet() const;
void OrderCheck();
void OrdersInit(double fVel);
void OrdersInit( double fVel );
void OrdersClear();
void OrdersDump();
std::string Order2Str(TOrders Order) const;
std::string Order2Str( TOrders Order ) const;
// members
std::string m_assignment;
Math3D::vector3 vCommandLocation; // polozenie wskaznika, sygnalizatora lub innego obiektu do ktorego odnosi sie komenda // NOTE: not used
@@ -374,9 +382,10 @@ private:
// scantable
// methods
public:
int CrossRoute(TTrack *tr);
int CrossRoute( TTrack *tr );
inline void MoveDistanceAdd( double distance ) {
dMoveLen += distance * iDirection; } //jak jedzie do tyłu to trzeba uwzględniać, że distance jest ujemna
dMoveLen += distance * iDirection;
} //jak jedzie do tyłu to trzeba uwzględniać, że distance jest ujemna
private:
// Ra: metody obsługujące skanowanie toru
std::vector<basic_event *> CheckTrackEvent( TTrack *Track, double const fDirection ) const;
@@ -404,7 +413,7 @@ private:
TTrack *BackwardTraceRoute( double &fDistance, double &fDirection, TTrack *Track, basic_event *&Event );
void SetProximityVelocity( double dist, double vel, glm::dvec3 const *pos );
TCommandType BackwardScan();
std::string TableText(std::size_t const Index) const;
std::string TableText( std::size_t const Index ) const;
/*
void RouteSwitch(int d);
*/
@@ -415,7 +424,7 @@ private:
double fLastVel = 0.0; // prędkość na poprzednio sprawdzonym torze
TTrack *tLast = nullptr; // ostatni analizowany tor
basic_event *eSignSkip = nullptr; // można pominąć ten SBL po zatrzymaniu
std::size_t SemNextIndex{ std::size_t(-1) };
std::size_t SemNextIndex{ std::size_t( -1 ) };
std::size_t SemNextStopIndex{ std::size_t( -1 ) };
double dMoveLen = 0.0; // odległość przejechana od ostatniego sprawdzenia tabelki
basic_event *eSignNext = nullptr; // sygnał zmieniający prędkość, do pokazania na [F2]
@@ -442,7 +451,7 @@ private:
double fLastStopExpDist = -1.0; // odległość wygasania ostateniego przystanku
int iRadioChannel = 1; // numer aktualnego kanału radiowego
int iGuardRadio = 0; // numer kanału radiowego kierownika (0, gdy nie używa radia)
sound_source tsGuardSignal { sound_placement::internal };
sound_source tsGuardSignal{ sound_placement::internal };
// consist
// methods
@@ -451,7 +460,7 @@ public:
private:
bool PrepareEngine();
bool ReleaseEngine();
void Doors(bool const Open, int const Side = 0);
void Doors( bool const Open, int const Side = 0 );
// returns true if any vehicle in the consist has an open door
bool doors_open() const;
void AutoRewident(); // ustawia hamulce w składzie
@@ -465,12 +474,16 @@ private:
bool iEngineActive{ false }; // ABu: Czy silnik byl juz zalaczony
bool IsCargoTrain{ false };
bool IsHeavyCargoTrain{ false };
bool IsLineBreakerClosed{ false }; // state of line breaker in all powered vehicles under control
double fReady = 0.0; // poziom odhamowania wagonów
bool Ready = false; // ABu: stan gotowosci do odjazdu - sprawdzenie odhamowania wagonow
double ConsistShade{ 1.0 }; // averaged amount of sunlight received by the consist
TDynamicObject *pVehicles[ 2 ]; // skrajne pojazdy w składzie (niekoniecznie bezpośrednio sterowane)
bool IsAnyDoorOpen[ 2 ]; // state of door in the consist
bool IsAnyLineBreakerOpen{ false }; // state of line breaker in all powered vehicles under control
bool IsAnyConverterOverloadRelayOpen{ false }; // state of converter overload relays in all vehicles under control
bool IsAnyMotorOverloadRelayOpen{ false }; // state of motor overload relays in all vehicles under control
bool IsAnyGroundRelayOpen{ false };
bool IsAnyCompressorEnabled{ false };
// logs
// methods

View File

@@ -956,7 +956,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
btnOn = true;
}
// else btCPass2.TurnOff();
if (MoverParameters->Battery || MoverParameters->ConverterFlag)
if (MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable)
{ // sygnaly konca pociagu
if (btEndSignals1.Active())
{
@@ -1056,7 +1056,7 @@ void TDynamicObject::ABuLittleUpdate(double ObjSqrDist)
} // vehicle within 400m
if( MoverParameters->Battery || MoverParameters->ConverterFlag )
if( MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable )
{ // sygnały czoła pociagu //Ra: wyświetlamy bez
// ograniczeń odległości, by były widoczne z
// daleka
@@ -2782,8 +2782,10 @@ void TDynamicObject::update_destinations() {
if( DestinationSign.sign == nullptr ) { return; }
auto const lowvoltagepower { ( MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable ) };
DestinationSign.sign->fLight = (
( ( DestinationSign.has_light ) && ( MoverParameters->Battery ) ) ?
( ( DestinationSign.has_light ) && ( lowvoltagepower ) ) ?
2.0 :
-1.0 );
@@ -2793,7 +2795,7 @@ void TDynamicObject::update_destinations() {
m_materialdata.replacable_skins[ 4 ] = (
( ( DestinationSign.destination != null_handle )
&& ( ( false == DestinationSign.has_light ) // physical destination signs remain up until manually changed
|| ( ( true == MoverParameters->Battery ) // lcd signs are off without power
|| ( ( lowvoltagepower ) // lcd signs are off without power
&& ( ctOwner != nullptr ) ) ) ) ? // lcd signs are off for carriages without engine, potentially left on a siding
DestinationSign.destination :
DestinationSign.destination_off );
@@ -2905,7 +2907,7 @@ bool TDynamicObject::Update(double dt, double dt1)
|| MoverParameters->Pantographs[end::rear].is_active ) {
if( ( MoverParameters->Mains )
&& ( MoverParameters->GetAnyTrainsetVoltage() < 0.1f ) ) {
&& ( MoverParameters->GetTrainsetHighVoltage() < 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,
@@ -3275,8 +3277,7 @@ bool TDynamicObject::Update(double dt, double dt1)
// fragment "z EXE Kursa"
if( MoverParameters->Mains ) { // nie wchodzić w funkcję bez potrzeby
if( ( false == MoverParameters->Battery )
&& ( false == MoverParameters->ConverterFlag ) // added alternative power source. TODO: more generic power check
if( ( false == ( MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable ) )
/*
// NOTE: disabled on account of multi-unit setups, where the unmanned unit wouldn't be affected
&& ( Controller == Humandriver )
@@ -3607,8 +3608,7 @@ bool TDynamicObject::Update(double dt, double dt1)
else {
pantspeedfactor = 0.0;
}
if( ( false == MoverParameters->Battery )
&& ( false == MoverParameters->ConverterFlag ) ) {
if( false == ( MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable ) ) {
pantspeedfactor = 0.0;
}
pantspeedfactor = std::max( 0.0, pantspeedfactor );
@@ -3952,7 +3952,7 @@ void TDynamicObject::RenderSounds() {
// NBMX dzwiek przetwornicy
if( MoverParameters->ConverterFlag ) {
if( MoverParameters->EngineType == TEngineType::ElectricSeriesMotor ) {
auto const voltage { std::max( MoverParameters->GetAnyTrainsetVoltage(), MoverParameters->PantographVoltage ) };
auto const voltage { std::max( MoverParameters->GetTrainsetHighVoltage(), MoverParameters->PantographVoltage ) };
if( voltage > 0.0 ) {
// NOTE: we do sound modulation here to avoid sudden jump on voltage loss
frequency = ( voltage / ( MoverParameters->NominalVoltage * MoverParameters->RList[ MoverParameters->RlistSize ].Mn ) );
@@ -4171,9 +4171,11 @@ void TDynamicObject::RenderSounds() {
}
// NBMX sygnal odjazdu
if( MoverParameters->Doors.has_warning ) {
auto const lowvoltagepower { MoverParameters->Power24vIsAvailable || MoverParameters->Power110vIsAvailable };
for( auto &departuresignalsound : m_departuresignalsounds ) {
// TBD, TODO: per-location door state triggers?
if( ( MoverParameters->DepartureSignal )
&& ( lowvoltagepower )
/*
|| ( ( MoverParameters->DoorCloseCtrl = control::autonomous )
&& ( ( ( false == MoverParameters->DoorLeftOpened ) && ( dDoorMoveL > 0.0 ) )
@@ -6209,7 +6211,9 @@ void TDynamicObject::Damage(char flag)
if (flag & 4) //blokada przetwornicy
{
MoverParameters->ConvOvldFlag = true;
if( MoverParameters->ConverterStart != start_t::disabled ) {
MoverParameters->ConvOvldFlag = true;
}
}
else
{
@@ -6522,7 +6526,7 @@ TDynamicObject::find_vehicle( int const Direction, double const Distance ) const
return { foundobject, foundcoupler, distance, true };
}
TDynamicObject * TDynamicObject::ControlledFind()
TDynamicObject * TDynamicObject::FindPowered()
{ // taka proteza:
// chcę podłączyć kabinę EN57 bezpośrednio z silnikowym, aby nie robić tego przez ukrotnienie
// drugi silnikowy i tak musi być ukrotniony, podobnie jak kolejna jednostka
@@ -6533,33 +6537,42 @@ TDynamicObject * TDynamicObject::ControlledFind()
// problematyczna może być kwestia wybranej kabiny (w silnikowym...)
// jeśli silnikowy będzie zapięty odwrotnie (tzn. -1), to i tak powinno jeździć dobrze
// również hamowanie wykonuje się zaworem w członie, a nie w silnikowym...
if( MoverParameters->Power > 1.0 ) { return this; }
auto const coupling { (
( MoverParameters->TrainType == dt_EZT ) || ( MoverParameters->TrainType == dt_DMU ) ) ?
coupling::permanent :
coupling::control };
auto const couplingtype { (
( MoverParameters->TrainType == dt_EZT )
|| ( MoverParameters->TrainType == dt_DMU ) ) ?
coupling::permanent :
coupling::control
};
// try first to look towards the rear
auto *d = this; // zaczynamy od aktualnego
auto *lookup {
find_vehicle(
coupling,
[]( TDynamicObject * vehicle ) {
return ( vehicle->MoverParameters->Power > 1.0 ); } ) };
while( ( d = d->NextC( couplingtype ) ) != nullptr ) {
if( d->MoverParameters->Power > 1.0 ) {
return d;
return( lookup != nullptr ? lookup : this ); // always return valid vehicle for backward compatibility
}
TDynamicObject *
TDynamicObject::FindPantographCarrier() {
// try first within a single unit, broaden to all vehicles under our control if first attempt fails
std::array<coupling, 2> const couplings = { coupling::permanent, coupling::control };
for( auto const coupling : couplings ) {
auto *result =
find_vehicle(
coupling,
[]( TDynamicObject * vehicle ) {
return (
( vehicle->MoverParameters->EnginePowerSource.SourceType == TPowerSource::CurrentCollector )
&& ( vehicle->MoverParameters->EnginePowerSource.CollectorParameters.CollectorsNo > 0 ) ); } );
if( result != nullptr ) {
return result;
}
}
// if we didn't yet find a suitable vehicle try in the other direction
d = this; // zaczynamy od aktualnego
// if we're still here, admit failure
return nullptr;
}
while( ( d = d->PrevC( couplingtype ) ) != nullptr ) {
if( d->MoverParameters->Power > 1.0 ) {
return d;
}
}
// if we still don't have a match give up
return this;
};
//---------------------------------------------------------------------------
void TDynamicObject::ParamSet(int what, int into)

View File

@@ -679,7 +679,11 @@ private:
void update_neighbours();
// locates potential collision source within specified range, scanning its route in specified direction
auto find_vehicle( int const Direction, double const Range ) const -> std::tuple<TDynamicObject *, int, double, bool>;
TDynamicObject * ControlledFind();
// locates potential vehicle connected with specific coupling type and satisfying supplied predicate
template <typename Predicate_>
auto find_vehicle( coupling const Coupling, Predicate_ const Predicate ) -> TDynamicObject *;
TDynamicObject * FindPowered();
TDynamicObject * FindPantographCarrier();
void ParamSet(int what, int into);
// zapytanie do AI, po którym segmencie skrzyżowania jechać
int RouteWish(TTrack *tr);
@@ -754,4 +758,25 @@ private:
erase_disabled();
};
template <typename Predicate_>
auto
TDynamicObject::find_vehicle( coupling const Coupling, Predicate_ const Predicate ) -> TDynamicObject * {
if( Predicate( this ) ) {
return this; }
// try first to look towards the rear
auto *vehicle { this };
while( ( vehicle = vehicle->NextC( Coupling ) ) != nullptr ) {
if( Predicate( vehicle ) ) {
return vehicle; } }
// if we didn't yet find a suitable vehicle try in the other direction
vehicle = this;
while( ( vehicle = vehicle->NextC( Coupling ) ) != nullptr ) {
if( Predicate( vehicle ) ) {
return vehicle; } }
// if we still don't have a match give up
return nullptr;
}
//---------------------------------------------------------------------------

View File

@@ -27,6 +27,12 @@ global_settings Global;
void
global_settings::LoadIniFile(std::string asFileName) {
// initialize season data in case the main config file doesn't
std::time_t timenow = std::time( 0 );
std::tm *localtime = std::localtime( &timenow );
fMoveLight = localtime->tm_yday + 1; // numer bieżącego dnia w roku
simulation::Environment.compute_season( fMoveLight );
cParser parser(asFileName, cParser::buffer_FILE);
ConfigParse(parser);
};
@@ -944,26 +950,8 @@ global_settings::ConfigParse(cParser &Parser) {
*/
if (iPause)
iTextMode = GLFW_KEY_F1; // jak pauza, to pokazać zegar
/* this won't execute anymore with the old parser removed
// TBD: remove, or launch depending on passed flag?
if (qp)
{ // to poniżej wykonywane tylko raz, jedynie po wczytaniu eu07.ini*/
#ifdef _WIN32
Console::ModeSet(iFeedbackMode, iFeedbackPort); // tryb pracy konsoli sterowniczej
Console::ModeSet(iFeedbackMode, iFeedbackPort); // tryb pracy konsoli sterowniczej
#endif
/*iFpsRadiusMax = 0.000025 * fFpsRadiusMax *
fFpsRadiusMax; // maksymalny promień renderowania 3000.0 -> 225
if (iFpsRadiusMax > 400)
iFpsRadiusMax = 400;
if (fDistanceFactor > 1.0)
{ // dla 1.0 specjalny tryb bez przeliczania
fDistanceFactor =
iWindowHeight /
fDistanceFactor; // fDistanceFactor>1.0 dla rozdzielczości większych niż bazowa
fDistanceFactor *=
(iMultisampling + 1.0) *
fDistanceFactor; // do kwadratu, bo większość odległości to ich kwadraty
}
}
*/
}

View File

@@ -160,7 +160,10 @@ enum coupling {
mainhose = 0x20,
heating = 0x40,
permanent = 0x80,
uic = 0x100
power24v = 0x100,
power110v = 0x200,
power3x400v = 0x400,
// uic = 0x1000,
};
// possible effect ranges for control commands; exclusive
enum class range_t {
@@ -180,11 +183,13 @@ enum class operation_t {
};
// start method for devices; exclusive
enum class start_t {
disabled,
manual,
automatic,
manualwithautofallback,
converter,
battery
battery,
direction
};
// recognized vehicle light locations and types; can be combined
enum light {
@@ -333,10 +338,10 @@ enum TProblem // lista problemów taboru, które uniemożliwiają jazdę
enum TCompressorList // lista parametrów w programatorze sprężarek
{ // pozycje kolejne
cl_Allow = 0, // zezwolenie na pracę sprężarek
cl_SpeedFactor = 1, // mnożnik wydajności
cl_MinFactor = 2, // mnożnik progu załącznika ciśnieniowego
cl_MaxFactor = 3 // mnożnik progu wyłącznika ciśnieniowego
cl_Allow = 0, // zezwolenie na pracę sprężarek
cl_SpeedFactor = 1, // mnożnik wydajności
cl_MinFactor = 2, // mnożnik progu załącznika ciśnieniowego
cl_MaxFactor = 3 // mnożnik progu wyłącznika ciśnieniowego
};
struct TLocation
@@ -352,7 +357,7 @@ struct TRotation
double Ry;
double Rz;
};
/*wymiary*/
struct TDimension
{
double W = 0.0;
@@ -653,6 +658,7 @@ struct TSecuritySystem
int VelocityAllowed;
int NextVelocityAllowed; /*predkosc pokazywana przez sygnalizacje kabinowa*/
bool RadioStop; // czy jest RadioStop
bool PoweredUp { false }; // helper, for detection of power state change
inline bool is_beeping() const {
return TestFlag( Status, s_SHPalarm );
@@ -687,8 +693,10 @@ struct TCoupling {
double beta = 0.0;
TCouplerType CouplerType = TCouplerType::NoCoupler; /*typ sprzegu*/
int AutomaticCouplingFlag = coupling::coupler;
int AllowedFlag = coupling::coupler | coupling::brakehose; //Ra: maska dostępnych
int AllowedFlag = ( coupling::coupler | coupling::brakehose ); //Ra: maska dostępnych
int PowerFlag = ( coupling::power110v | coupling::power24v );
/*zmienne*/
bool AutomaticCouplingAllowed { true }; // whether automatic coupling can be currently performed
int CouplingFlag = 0; /*0 - wirtualnie, 1 - sprzegi, 2 - pneumatycznie, 4 - sterowanie, 8 - kabel mocy*/
class TMoverParameters *Connected = nullptr; /*co jest podlaczone*/
int ConnectedNr = 0; //Ra: od której strony podłączony do (Connected): 0=przód, 1=tył
@@ -702,7 +710,8 @@ struct TCoupling {
TCouplerType adapter_type = TCouplerType::NoCoupler; // CouplerType override if other than NoCoupler
power_coupling power_high;
// power_coupling power_low; // TODO: implement this
power_coupling power_110v;
power_coupling power_24v;
int sounds { 0 }; // sounds emitted by the coupling devices
bool Render = false; /*ABu: czy rysowac jak zaczepiony sprzeg*/
@@ -884,6 +893,7 @@ private:
bool auto_include_remote { false }; // automatic door closure applies also to remote control
bool permit_needed { false };
std::vector<int> permit_presets; // permit presets selectable with preset switch
float voltage { 0.f }; // power type required for door movement
// ld inputs
bool lock_enabled { true };
bool step_enabled { true };
@@ -1013,6 +1023,7 @@ public:
double LightPower = 0.0; /*moc pobierana na ogrzewanie/oswietlenie*/
double BatteryVoltage = 0.0; /*Winger - baterie w elektrykach*/
bool Battery = false; /*Czy sa zalavzone baterie*/
start_t BatteryStart = start_t::manual;
bool EpFuse = true; /*Czy sa zalavzone baterie*/
bool Signalling = false; /*Czy jest zalaczona sygnalizacja hamowania ostatniego wagonu*/
bool Radio = true; /*Czy jest zalaczony radiotelefon*/
@@ -1302,7 +1313,9 @@ public:
std::string Name; /*nazwa wlasna*/
TCoupling Couplers[2]; //urzadzenia zderzno-sprzegowe, polaczenia miedzy wagonami
std::array<neighbour_data, 2> Neighbours; // potential collision sources
bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/
bool Power110vIsAvailable = false; // cached availability of 110v power
bool Power24vIsAvailable = false; // cached availability of 110v power
bool EventFlag = false; /*!o true jesli cos nietypowego sie wydarzy*/
int SoundFlag = 0; /*!o patrz stale sound_ */
int AIFlag{ 0 }; // HACK: events of interest for consist owner
double DistCounter = 0.0; /*! licznik kilometrow */
@@ -1365,6 +1378,8 @@ public:
bool ConverterAllow = false; /*zezwolenie na prace przetwornicy NBMX*/
bool ConverterAllowLocal{ true }; // local device state override (most units don't have this fitted so it's set to true not to intefere)
bool ConverterFlag = false; /*! czy wlaczona przetwornica NBMX*/
start_t ConverterOverloadRelayStart { start_t::manual }; // whether overload relay reset responds to dedicated button
bool ConverterOverloadRelayOffWhenMainIsOff { false };
fuel_pump FuelPump;
oil_pump OilPump;
water_pump WaterPump;
@@ -1482,6 +1497,7 @@ public:
bool NoVoltRelay{ true }; // switches off if the power level drops below threshold
bool OvervoltageRelay{ true }; // switches off if the power level goes above threshold
bool s_CAtestebrake = false; //hunter-091012: zmienna dla testu ca
std::array<std::pair<double, double>, 4> PowerCircuits; //24v, 110v, 3x400v and 3000v power circuits, voltage from local sources and current draw pairs
/*-zmienne dla lokomotywy spalinowej z przekladnia mechaniczna*/
double dizel_fill = 0.0; /*napelnienie*/
@@ -1612,7 +1628,7 @@ public:
// Q *******************************************************************************************
double GetTrainsetVoltage( int const Coupling = ( coupling::heating | coupling::highvoltage ) ) const;
double GetAnyTrainsetVoltage() const;
double GetTrainsetHighVoltage() const;
bool switch_physics(bool const State);
double LocalBrakeRatio(void);
double ManualBrakeRatio(void);
@@ -1657,7 +1673,7 @@ public:
bool SecuritySystemReset(void);
void SecuritySystemCheck(double dt);
bool BatterySwitch(bool State);
bool BatterySwitch( bool State, range_t const Notify = range_t::consist );
bool EpFuseSwitch(bool State);
bool SpringBrakeActivate(bool State);
bool SpringBrakeShutOff(bool State);
@@ -1735,7 +1751,7 @@ public:
/*-funkcje typowe dla lokomotywy elektrycznej*/
void LowVoltagePowerCheck( double const Deltatime );
void MainsCheck( double const Deltatime );
void PowerCouplersCheck( double const Deltatime );
void PowerCouplersCheck( double const Deltatime, coupling const Coupling );
void ConverterCheck( double const Timestep ); // przetwornica
void HeatingCheck( double const Timestep );
void WaterPumpCheck( double const Timestep );
@@ -1749,7 +1765,7 @@ public:
bool FuseFlagCheck(void) const; // sprawdzanie flagi nadmiarowego
void FuseOff(void); // wylaczenie nadmiarowego
bool UniversalResetButton( int const Button, range_t const Notify = range_t::consist );
bool RelayReset( int const Relays ); // resets specified relays
bool RelayReset( int const Relays, range_t const Notify = range_t::consist ); // resets specified relays
double ShowCurrent( int AmpN ) const; //pokazuje bezwgl. wartosc pradu na wybranym amperomierzu
double ShowCurrentP(int AmpN) const; //pokazuje bezwgl. wartosc pradu w wybranym pojezdzie //Q 20160722

File diff suppressed because it is too large Load Diff

View File

@@ -970,6 +970,11 @@ void TEStEP1::EPCalc(double dt)
LBP = LBP - dv;
}
void TEStEP1::SetEPS( double const nEPS )
{
EPS = nEPS;
}
//---EST3--
double TESt3::GetPF( double const PP, double const dt, double const Vel )

View File

@@ -418,6 +418,7 @@ class TEStEP1 : public TEStEP2 {
public:
void EPCalc(double dt);
void SetEPS( double const nEPS ) override; //stan hamulca EP
inline TEStEP1(double i_mbp, double i_bcr, double i_bcd, double i_brc, int i_bcn, int i_BD, int i_mat, int i_ba, int i_nbpa) :
TEStEP2(i_mbp, i_bcr, i_bcd, i_brc, i_bcn, i_BD, i_mat, i_ba, i_nbpa)

293
Train.cpp
View File

@@ -545,14 +545,14 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "name", DynamicObject->asName );
dict->insert( "cab", mvOccupied->CabOccupied );
// basic systems state data
dict->insert( "battery", mvControlled->Battery );
dict->insert( "battery", mvOccupied->Power24vIsAvailable );
dict->insert( "linebreaker", mvControlled->Mains );
dict->insert( "main_init", ( mvControlled->MainsInitTimeCountdown < mvControlled->MainsInitTime ) && ( mvControlled->MainsInitTimeCountdown > 0.0 ) );
dict->insert( "main_ready", ( false == mvControlled->Mains ) && ( fHVoltage > 0.0 ) && ( mvControlled->MainsInitTimeCountdown <= 0.0 ) );
dict->insert( "converter", mvControlled->ConverterFlag );
dict->insert( "converter", mvOccupied->Power110vIsAvailable );
dict->insert( "converter_overload", mvControlled->ConvOvldFlag );
dict->insert( "compress", mvControlled->CompressorFlag );
dict->insert( "pant_compressor", mvControlled->PantCompFlag );
dict->insert( "pant_compressor", mvPantographUnit->PantCompFlag );
dict->insert( "lights_front", mvOccupied->iLights[ end::front ] );
dict->insert( "lights_rear", mvOccupied->iLights[ end::rear ] );
dict->insert( "lights_compartments", mvOccupied->CompartmentLights.is_active || mvOccupied->CompartmentLights.is_disabled );
@@ -606,7 +606,7 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "ca", TestFlag( mvOccupied->SecuritySystem.Status, s_aware ) );
dict->insert( "shp", TestFlag( mvOccupied->SecuritySystem.Status, s_active ) );
dict->insert( "distance_counter", m_distancecounter );
dict->insert( "pantpress", std::abs( mvControlled->PantPress ) );
dict->insert( "pantpress", std::abs( mvPantographUnit->PantPress ) );
dict->insert( "universal3", InstrumentLightActive );
dict->insert( "radio_channel", RadioChannel() );
dict->insert( "radio_volume", Global.RadioVolume );
@@ -617,7 +617,7 @@ dictionary_source *TTrain::GetTrainState() {
dict->insert( "slipping_wheels", mvOccupied->SlippingWheels );
dict->insert( "sanding", mvOccupied->SandDose );
// electric current data
dict->insert( "traction_voltage", std::abs( mvControlled->PantographVoltage ) );
dict->insert( "traction_voltage", std::abs( mvPantographUnit->PantographVoltage ) );
dict->insert( "voltage", std::abs( mvControlled->EngineVoltage ) );
dict->insert( "im", std::abs( mvControlled->Im ) );
dict->insert( "fuse", mvControlled->FuseFlag );
@@ -745,7 +745,7 @@ bool TTrain::is_eztoer() const {
return
( ( mvControlled->TrainType == dt_EZT )
&& ( mvOccupied->BrakeSubsystem == TBrakeSubSystem::ss_ESt )
&& ( mvControlled->Battery == true )
&& ( mvControlled->Power24vIsAvailable == true )
&& ( mvControlled->EpFuse == true )
&& ( mvControlled->DirActive != 0 ) ); // od yB
}
@@ -2068,7 +2068,7 @@ void TTrain::OnCommand_batterytoggle( TTrain *Train, command_data const &Command
if( Command.action != GLFW_REPEAT ) {
// keep the switch from flipping back and forth if key is held down
if( false == Train->mvOccupied->Battery ) {
if( false == Train->mvOccupied->Power24vIsAvailable ) {
// turn on
OnCommand_batteryenable( Train, Command );
}
@@ -2086,18 +2086,11 @@ void TTrain::OnCommand_batteryenable( TTrain *Train, command_data const &Command
Train->ggBatteryButton.UpdateValue( 1.0f, Train->dsbSwitch );
Train->ggBatteryOnButton.UpdateValue( 1.0f, Train->dsbSwitch );
if( true == Train->mvOccupied->Battery ) { return; } // already on
Train->mvOccupied->BatterySwitch( true );
if( Train->mvOccupied->BatterySwitch( true ) ) {
// side-effects
if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->SetLights();
}
if( TestFlag( Train->mvOccupied->SecuritySystem.SystemType, 2 ) ) {
// Ra: znowu w kabinie jest coś, co być nie powinno!
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_active );
SetFlag( Train->mvOccupied->SecuritySystem.Status, s_SHPalarm );
}
// side-effects
if( Train->mvOccupied->LightsPosNo > 0 ) {
Train->SetLights();
}
}
else if( Command.action == GLFW_RELEASE ) {
@@ -2116,8 +2109,6 @@ void TTrain::OnCommand_batterydisable( TTrain *Train, command_data const &Comman
Train->ggBatteryButton.UpdateValue( 0.0f, Train->dsbSwitch );
Train->ggBatteryOffButton.UpdateValue( 1.0f, Train->dsbSwitch );
if( false == Train->mvOccupied->Battery ) { return; } // already off
Train->mvOccupied->BatterySwitch( false );
}
else if( Command.action == GLFW_RELEASE ) {
@@ -2136,7 +2127,7 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const &pantograph { Train->mvControlled->Pantographs[ end::front ] };
auto const &pantograph { Train->mvPantographUnit->Pantographs[ end::front ] };
auto const state {
pantograph.valve.is_enabled
|| pantograph.is_active }; // fallback for impulse switches
@@ -2150,7 +2141,7 @@ void TTrain::OnCommand_pantographtogglefront( TTrain *Train, command_data const
else if( Command.action == GLFW_RELEASE ) {
// impulse switches return automatically to neutral position
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
Train->mvControlled->OperatePantographValve( end::front, operation_t::none );
Train->mvOccupied->OperatePantographValve( end::front, operation_t::none );
}
}
}
@@ -2162,7 +2153,7 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const &pantograph { Train->mvControlled->Pantographs[ end::rear ] };
auto const &pantograph { Train->mvPantographUnit->Pantographs[ end::rear ] };
auto const state {
pantograph.valve.is_enabled
|| pantograph.is_active }; // fallback for impulse switches
@@ -2176,7 +2167,7 @@ void TTrain::OnCommand_pantographtogglerear( TTrain *Train, command_data const &
else if( Command.action == GLFW_RELEASE ) {
// impulse switches return automatically to neutral position
if( Train->mvOccupied->PantSwitchType == "impulse" ) {
Train->mvControlled->OperatePantographValve( end::rear, operation_t::none );
Train->mvOccupied->OperatePantographValve( end::rear, operation_t::none );
}
}
}
@@ -2191,7 +2182,7 @@ void TTrain::OnCommand_pantographraisefront( TTrain *Train, command_data const &
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
Train->mvControlled->OperatePantographValve( end::front,
Train->mvOccupied->OperatePantographValve( end::front,
Train->mvOccupied->PantSwitchType == "impulse" ?
operation_t::enable_on :
operation_t::enable );
@@ -2212,7 +2203,7 @@ void TTrain::OnCommand_pantographraiserear( TTrain *Train, command_data const &C
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
Train->mvControlled->OperatePantographValve( end::rear,
Train->mvOccupied->OperatePantographValve( end::rear,
Train->mvOccupied->PantSwitchType == "impulse" ?
operation_t::enable_on :
operation_t::enable );
@@ -2238,7 +2229,7 @@ void TTrain::OnCommand_pantographlowerfront( TTrain *Train, command_data const &
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
Train->mvControlled->OperatePantographValve( end::front,
Train->mvOccupied->OperatePantographValve( end::front,
Train->mvOccupied->PantSwitchType == "impulse" ?
operation_t::disable_on :
operation_t::disable );
@@ -2263,7 +2254,7 @@ void TTrain::OnCommand_pantographlowerrear( TTrain *Train, command_data const &C
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
Train->mvControlled->OperatePantographValve( end::rear,
Train->mvOccupied->OperatePantographValve( end::rear,
Train->mvOccupied->PantSwitchType == "impulse" ?
operation_t::disable_on :
operation_t::disable );
@@ -2289,9 +2280,9 @@ void TTrain::OnCommand_pantographlowerall( TTrain *Train, command_data const &Co
if( Train->ggPantAllDownButton.type() == TGaugeType::toggle ) {
// two-state switch, only cares about press events
if( Command.action == GLFW_PRESS ) {
Train->mvControlled->DropAllPantographs( false == Train->mvControlled->PantAllDown );
Train->mvPantographUnit->DropAllPantographs( false == Train->mvPantographUnit->PantAllDown );
// visual feedback
Train->ggPantAllDownButton.UpdateValue( ( Train->mvControlled->PantAllDown ? 1.0 : 0.0 ), Train->dsbSwitch );
Train->ggPantAllDownButton.UpdateValue( ( Train->mvPantographUnit->PantAllDown ? 1.0 : 0.0 ), Train->dsbSwitch );
}
}
else {
@@ -2327,8 +2318,8 @@ void TTrain::OnCommand_pantographtoggleselected( TTrain *Train, command_data con
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
auto const state {
Train->mvControlled->PantsValve.is_enabled
| Train->mvControlled->PantsValve.is_active }; // fallback for impulse switches
Train->mvPantographUnit->PantsValve.is_enabled
| Train->mvPantographUnit->PantsValve.is_active }; // fallback for impulse switches
if( state ) {
OnCommand_pantographlowerselected( Train, Command );
}
@@ -2341,12 +2332,12 @@ void TTrain::OnCommand_pantographtoggleselected( TTrain *Train, command_data con
if( Train->m_controlmapper.contains( "pantselectedoff_sw:" ) ) {
// two buttons setup
if( Train->ggPantSelectedButton.type() != TGaugeType::toggle ) {
Train->mvControlled->OperatePantographsValve( operation_t::enable_off );
Train->mvOccupied->OperatePantographsValve( operation_t::enable_off );
// visual feedback
Train->ggPantSelectedButton.UpdateValue( 0.0, Train->dsbSwitch );
}
if( Train->ggPantSelectedDownButton.type() != TGaugeType::toggle ) {
Train->mvControlled->OperatePantographsValve( operation_t::disable_off );
Train->mvOccupied->OperatePantographsValve( operation_t::disable_off );
// visual feedback
Train->ggPantSelectedDownButton.UpdateValue( 0.0, Train->dsbSwitch );
}
@@ -2355,7 +2346,7 @@ void TTrain::OnCommand_pantographtoggleselected( TTrain *Train, command_data con
if( Train->ggPantSelectedButton.type() != TGaugeType::toggle ) {
// special case, just one impulse switch controlling both states
// with neutral position mid-way
Train->mvControlled->OperatePantographsValve( operation_t::none );
Train->mvOccupied->OperatePantographsValve( operation_t::none );
// visual feedback
Train->ggPantSelectedButton.UpdateValue( 0.5, Train->dsbSwitch );
}
@@ -2369,7 +2360,7 @@ void TTrain::OnCommand_pantographraiseselected( TTrain *Train, command_data cons
if( Command.action == GLFW_PRESS ) {
// raise selected
Train->mvControlled->OperatePantographsValve(
Train->mvOccupied->OperatePantographsValve(
Train->ggPantSelectedButton.type() != TGaugeType::toggle ?
operation_t::enable_on :
operation_t::enable );
@@ -2388,7 +2379,7 @@ void TTrain::OnCommand_pantographlowerselected( TTrain *Train, command_data cons
if( Command.action == GLFW_PRESS ) {
// lower selected
Train->mvControlled->OperatePantographsValve(
Train->mvOccupied->OperatePantographsValve(
Train->ggPantSelectedDownButton.type() != TGaugeType::toggle ?
operation_t::disable_on :
operation_t::disable );
@@ -2424,8 +2415,8 @@ void TTrain::change_pantograph_selection( int const Change ) {
auto const frontstate{ ( m_pantselection == 2 ) || ( m_pantselection == ( swapends ? 1 : 3 ) ) };
auto const rearstate{ ( m_pantselection == 2 ) || ( m_pantselection == ( swapends ? 3 : 1 ) ) };
// potentially adjust pantograph valves
mvControlled->OperatePantographValve( end::front, ( frontstate ? operation_t::enable : operation_t::disable ) );
mvControlled->OperatePantographValve( end::rear, ( rearstate ? operation_t::enable : operation_t::disable ) );
mvOccupied->OperatePantographValve( end::front, ( frontstate ? operation_t::enable : operation_t::disable ) );
mvOccupied->OperatePantographValve( end::rear, ( rearstate ? operation_t::enable : operation_t::disable ) );
}
void TTrain::OnCommand_pantographcompressorvalvetoggle( TTrain *Train, command_data const &Command ) {
@@ -2489,7 +2480,7 @@ void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data
if( ( Train->ggPantCompressorValve.SubModel == nullptr )
&& ( Train->mvControlled->TrainType == dt_EZT ?
( Train->mvControlled != Train->mvOccupied ) :
( Train->mvOccupied == Train->mvPantographUnit ) :
( Train->iCabn != 0 ) ) ) {
// tylko w maszynowym
return;
@@ -2497,17 +2488,17 @@ void TTrain::OnCommand_pantographcompressoractivate( TTrain *Train, command_data
if( Command.action != GLFW_RELEASE ) {
// press or hold to activate
if( ( Train->mvControlled->PantPress < 4.8 )
&& ( true == Train->mvControlled->Battery ) ) {
if( ( Train->mvPantographUnit->PantPress < 4.8 )
&& ( true == Train->mvPantographUnit->Power24vIsAvailable ) ) {
// needs live power source and low enough pressure to work
Train->mvControlled->PantCompFlag = true;
Train->mvPantographUnit->PantCompFlag = true;
}
// visual feedback
Train->ggPantCompressorButton.UpdateValue( 1.0 );
}
else {
// release to disable
Train->mvControlled->PantCompFlag = false;
Train->mvPantographUnit->PantCompFlag = false;
// visual feedback
Train->ggPantCompressorButton.UpdateValue( 0.0 );
}
@@ -3021,7 +3012,7 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( ( false == Train->mvControlled->ConverterAllow )
if( ( false == Train->mvOccupied->Power110vIsAvailable )
&& ( Train->ggConverterButton.GetValue() < 0.5 ) ) {
// turn on
OnCommand_converterenable( Train, Command );
@@ -3043,30 +3034,16 @@ void TTrain::OnCommand_convertertoggle( TTrain *Train, command_data const &Comma
void TTrain::OnCommand_converterenable( TTrain *Train, command_data const &Command ) {
if( Train->mvControlled->ConverterStart == start_t::automatic ) {
// let the automatic thing do its automatic thing...
return;
}
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggConverterButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvControlled->ConverterAllow ) { return; } // already enabled
// impulse type switch has no effect if there's no power
// NOTE: this is most likely setup wrong, but the whole thing is smoke and mirrors anyway
if( ( Train->mvOccupied->ConvSwitchType != "impulse" )
|| ( Train->mvControlled->Mains ) ) {
// won't start if the line breaker button is still held
if( true == Train->mvControlled->ConverterSwitch( true ) ) {
// side effects
// control the compressor, if it's paired with the converter
if( Train->mvControlled->CompressorPower == 2 ) {
// hunter-091012: tak jest poprawnie
Train->mvControlled->CompressorSwitch( true );
}
}
// won't start if the line breaker button is still held
Train->mvOccupied->ConverterSwitch( true );
}
}
else if( Command.action == GLFW_RELEASE ) {
@@ -3077,11 +3054,6 @@ void TTrain::OnCommand_converterenable( TTrain *Train, command_data const &Comma
void TTrain::OnCommand_converterdisable( TTrain *Train, command_data const &Command ) {
if( Train->mvControlled->ConverterStart == start_t::automatic ) {
// let the automatic thing do its automatic thing...
return;
}
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggConverterButton.UpdateValue( 0.0, Train->dsbSwitch );
@@ -3089,20 +3061,7 @@ void TTrain::OnCommand_converterdisable( TTrain *Train, command_data const &Comm
Train->ggConverterOffButton.UpdateValue( 1.0, Train->dsbSwitch );
}
if( false == Train->mvControlled->ConverterAllow ) { return; } // already disabled
if( true == Train->mvControlled->ConverterSwitch( false ) ) {
// side effects
// control the compressor, if it's paired with the converter
if( Train->mvControlled->CompressorPower == 2 ) {
// hunter-091012: tak jest poprawnie
Train->mvControlled->CompressorSwitch( false );
}
if( ( Train->mvControlled->TrainType == dt_EZT )
&& ( false == TestFlag( Train->mvControlled->EngDmgFlag, 4 ) ) ) {
Train->mvControlled->ConvOvldFlag = false;
}
}
Train->mvOccupied->ConverterSwitch( false );
}
else if( Command.action == GLFW_RELEASE ) {
// potentially reset impulse switch position, using shared code branch
@@ -3190,7 +3149,12 @@ void TTrain::OnCommand_compressortoggle( TTrain *Train, command_data const &Comm
if( Command.action == GLFW_PRESS ) {
// only reacting to press, so the switch doesn't flip back and forth if key is held down
if( false == Train->mvControlled->CompressorAllow ) {
auto const compressorisenabled { (
Train->Dynamic()->Mechanik ?
Train->Dynamic()->Mechanik->IsAnyCompressorEnabled :
Train->mvOccupied->CompressorAllow ) };
if( false == compressorisenabled ) {
// turn on
OnCommand_compressorenable( Train, Command );
}
@@ -3214,22 +3178,16 @@ void TTrain::OnCommand_compressortoggle( TTrain *Train, command_data const &Comm
void TTrain::OnCommand_compressorenable( TTrain *Train, command_data const &Command ) {
if( Train->mvControlled->CompressorPower >= 2 ) {
return;
}
if( Command.action == GLFW_PRESS ) {
// visual feedback
Train->ggCompressorButton.UpdateValue( 1.0, Train->dsbSwitch );
if( true == Train->mvControlled->CompressorAllow ) { return; } // already enabled
// impulse type switch has no effect if there's no power
// NOTE: this is most likely setup wrong, but the whole thing is smoke and mirrors anyway
// if( ( Train->mvOccupied->CompSwitchType != "impulse" )
// || ( Train->mvControlled->Mains ) ) {
Train->mvControlled->CompressorSwitch( true );
Train->mvOccupied->CompressorSwitch( true );
// }
}
else if( Command.action == GLFW_RELEASE ) {
@@ -3251,9 +3209,7 @@ void TTrain::OnCommand_compressordisable( TTrain *Train, command_data const &Com
Train->ggCompressorOffButton.UpdateValue( 1.0, Train->dsbSwitch );
}
*/
if( false == Train->mvControlled->CompressorAllow ) { return; } // already disabled
Train->mvControlled->CompressorSwitch( false );
Train->mvOccupied->CompressorSwitch( false );
}
else if( Command.action == GLFW_RELEASE ) {
// potentially reset impulse switch position, using shared code branch
@@ -5695,7 +5651,7 @@ void TTrain::OnCommand_radiostopsend( TTrain *Train, command_data const &Command
if( Command.action == GLFW_PRESS ) {
if( ( true == Train->mvOccupied->Radio )
&& ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) {
&& ( Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable ) ) {
simulation::Region->RadioStop( Train->Dynamic()->GetPosition() );
}
// visual feedback
@@ -5712,7 +5668,7 @@ void TTrain::OnCommand_radiostoptest( TTrain *Train, command_data const &Command
if( Command.action == GLFW_PRESS ) {
if( ( Train->RadioChannel() == 10 )
&& ( true == Train->mvOccupied->Radio )
&& ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) {
&& ( Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable ) ) {
Train->Dynamic()->RadioStop();
}
// visual feedback
@@ -5729,7 +5685,7 @@ void TTrain::OnCommand_radiocall3send( TTrain *Train, command_data const &Comman
if( Command.action == GLFW_PRESS ) {
if( ( Train->RadioChannel() != 10 )
&& ( true == Train->mvOccupied->Radio )
&& ( Train->mvControlled->Battery || Train->mvControlled->ConverterFlag ) ) {
&& ( Train->mvOccupied->Power24vIsAvailable || Train->mvOccupied->Power110vIsAvailable) ) {
simulation::Events.queue_receivers( radio_message::call3, Train->Dynamic()->GetPosition() );
}
// visual feedback
@@ -5912,13 +5868,7 @@ bool TTrain::Update( double const Deltatime )
|| ( ( ggMainOnButton.SubModel != nullptr ) && ( ggMainOnButton.GetDesiredValue() > 0.95 )
|| ( ggIgnitionKey.GetDesiredValue() > 0.95 ) ) ) { // HACK: fallback
// keep track of period the line breaker button is held down, to determine when/if circuit closes
if( ( mvControlled->MainSwitchCheck() )
&& ( ( fHVoltage > 0.5 * mvControlled->EnginePowerSource.MaxVoltage )
|| ( ( mvControlled->EngineType != TEngineType::ElectricSeriesMotor )
&& ( mvControlled->EngineType != TEngineType::ElectricInductionMotor )
&& ( true == mvControlled->Battery ) ) ) ) {
// prevent the switch from working if there's no power
// TODO: consider whether it makes sense for diesel engines and such
if( mvControlled->MainSwitchCheck() ) {
fMainRelayTimer += Deltatime;
}
}
@@ -6034,7 +5984,7 @@ bool TTrain::Update( double const Deltatime )
&& ( 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->GetTrainsetHighVoltage() ); // Winger czy to nie jest zle?
}
// *mvControlled->Mains);
else {
@@ -6253,7 +6203,7 @@ bool TTrain::Update( double const Deltatime )
else
fConverterTimer = 0;
//------------------
auto const lowvoltagepower { mvControlled->Battery || mvControlled->ConverterFlag };
auto const lowvoltagepower { mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable };
// youBy - prad w drugim czlonie: galaz lub calosc
{
@@ -6356,11 +6306,11 @@ bool TTrain::Update( double const Deltatime )
// TODO: implement object-based circuits and power systems model so we can have this working more properly
ggLVoltage.UpdateValue(
std::max(
( mvControlled->ConverterFlag ?
mvControlled->NominalBatteryVoltage :
( mvOccupied->Power110vIsAvailable ?
mvOccupied->NominalBatteryVoltage :
0.0 ),
( mvControlled->Battery ?
mvControlled->BatteryVoltage :
( mvOccupied->Power24vIsAvailable ?
mvOccupied->BatteryVoltage :
0.0 ) ) );
ggLVoltage.Update();
}
@@ -6468,9 +6418,9 @@ bool TTrain::Update( double const Deltatime )
false :
true ) );
btLampkaPrzetw.Turn( mvControlled->ConverterFlag );
btLampkaPrzetwOff.Turn( false == mvControlled->ConverterFlag );
btLampkaNadmPrzetw.Turn( mvControlled->ConvOvldFlag );
btLampkaPrzetw.Turn( mvOccupied->Power110vIsAvailable );
btLampkaPrzetwOff.Turn( false == mvOccupied->Power110vIsAvailable );
btLampkaNadmPrzetw.Turn( Dynamic()->Mechanik ? Dynamic()->Mechanik->IsAnyConverterOverloadRelayOpen : mvControlled->ConvOvldFlag );
btLampkaOpory.Turn(
mvControlled->StLinFlag ?
@@ -6721,7 +6671,15 @@ bool TTrain::Update( double const Deltatime )
btLampkaStycznB.Turn( true ); // mozna prowadzic rozruch
}
// hunter-271211: sygnalizacja poslizgu w pierwszym pojezdzie, gdy wystapi w drugim
btLampkaPoslizg.Turn( mover->SlippingWheels );
if( mover->SlippingWheels ) {
// Ra 2014-12: lokomotywy 181/182 dostają SlippingWheels po zahamowaniu powyżej 2.85 bara i buczały
auto const veldiff { ( DynamicObject->GetVelocity() - fTachoVelocity ) / mvControlled->Vmax };
if( veldiff < -0.01 ) {
// 1% Vmax rezerwy, żeby 181/182 nie buczały po zahamowaniu, ale to proteza
auto const lightstate { std::abs( mover->Im ) > 10.0 };
btLampkaPoslizg.Turn( btLampkaPoslizg.GetValue() || lightstate );
}
}
btLampkaSprezarkaB.Turn( mover->CompressorFlag ); // mutopsitka dziala
btLampkaSprezarkaBOff.Turn( false == mover->CompressorFlag );
@@ -6931,11 +6889,11 @@ bool TTrain::Update( double const Deltatime )
// lights
auto const lightpower { (
InstrumentLightType == 0 ? mvControlled->Battery || mvControlled->ConverterFlag :
InstrumentLightType == 0 ? mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable :
InstrumentLightType == 1 ? mvControlled->Mains :
InstrumentLightType == 2 ? mvControlled->ConverterFlag :
InstrumentLightType == 3 ? mvControlled->Battery || mvControlled->ConverterFlag :
InstrumentLightType == 4 ? mvControlled->Battery || mvControlled->ConverterFlag :
InstrumentLightType == 2 ? mvOccupied->Power110vIsAvailable :
InstrumentLightType == 3 ? mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable :
InstrumentLightType == 4 ? mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable :
false ) };
InstrumentLightActive = (
InstrumentLightType == 3 ? true : // TODO: link the light state with the state of the master key
@@ -7058,10 +7016,6 @@ bool TTrain::Update( double const Deltatime )
// calculate current level of interior illumination
{
// TODO: organize it along with rest of train update in a more sensible arrangement
auto const converteractive{ (
( mvOccupied->ConverterFlag )
|| ( ( ( mvOccupied->Couplers[ end::front ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ end::front ].Connected->ConverterFlag )
|| ( ( ( mvOccupied->Couplers[ end::rear ].CouplingFlag & coupling::permanent ) != 0 ) && mvOccupied->Couplers[ end::rear ].Connected->ConverterFlag ) ) };
// Ra: uzeleżnic od napięcia w obwodzie sterowania
// hunter-091012: uzaleznienie jasnosci od przetwornicy
int cabidx { 0 };
@@ -7071,7 +7025,7 @@ bool TTrain::Update( double const Deltatime )
( ( cab.bLight == false ) ? 0.f :
( cab.bLightDim == true ) ? 0.4f :
1.f )
* ( converteractive ? 1.f : 0.5f );
* ( mvOccupied->Power110vIsAvailable ? 1.f : 0.5f );
if( cab.LightLevel != cablightlevel ) {
cab.LightLevel = cablightlevel;
@@ -7300,37 +7254,6 @@ TTrain::update_sounds( double const Deltatime ) {
rsHuntingNoise.stop( true == FreeFlyModeFlag );
}
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if (mvOccupied->SecuritySystem.Status != s_off ) {
// hunter-091012: rozdzielenie alarmow
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer
.pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor )
.gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor )
.play( sound_flags::looping );
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
else {
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
}
else {
// wylaczone
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
update_sounds_radio();
if( fTachoCount >= 3.f ) {
auto const frequency { (
true == dsbHasler.is_combined() ?
@@ -7346,7 +7269,28 @@ TTrain::update_sounds( double const Deltatime ) {
}
// power-reliant sounds
if( mvControlled->Battery || mvControlled->ConverterFlag ) {
if( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) {
// McZapkie-141102: SHP i czuwak, TODO: sygnalizacja kabinowa
if( mvOccupied->SecuritySystem.Status != s_off ) {
// hunter-091012: rozdzielenie alarmow
if( TestFlag( mvOccupied->SecuritySystem.Status, s_CAalarm )
|| TestFlag( mvOccupied->SecuritySystem.Status, s_SHPalarm ) ) {
if( false == dsbBuzzer.is_playing() ) {
dsbBuzzer
.pitch( dsbBuzzer.m_frequencyoffset + dsbBuzzer.m_frequencyfactor )
.gain( dsbBuzzer.m_amplitudeoffset + dsbBuzzer.m_amplitudefactor )
.play( sound_flags::looping );
Console::BitsSet( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
else {
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
}
}
// distance meter alert
auto const *owner { (
DynamicObject->ctOwner != nullptr ?
@@ -7364,8 +7308,14 @@ TTrain::update_sounds( double const Deltatime ) {
}
else {
// stop power-reliant sounds if power is cut
if( true == dsbBuzzer.is_playing() ) {
dsbBuzzer.stop();
Console::BitsClear( 1 << 14 ); // ustawienie bitu 16 na PoKeys
}
m_distancecounterclear.stop();
}
update_sounds_radio();
}
void TTrain::update_sounds_runningnoise( sound_source &Sound ) {
@@ -7434,7 +7384,7 @@ void TTrain::update_sounds_radio() {
std::end( m_radiomessages ) );
}
// adjust audibility of remaining messages based on current radio conditions
auto const radioenabled { ( true == mvOccupied->Radio ) && ( mvControlled->Battery || mvControlled->ConverterFlag ) };
auto const radioenabled { ( true == mvOccupied->Radio ) && ( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) };
for( auto &message : m_radiomessages ) {
auto const volume {
( true == radioenabled )
@@ -7455,7 +7405,7 @@ void TTrain::update_sounds_radio() {
void TTrain::add_distance( double const Distance ) {
auto const meterenabled { ( true == ( m_distancecounter >= 0 ) ) && ( mvControlled->Battery || mvControlled->ConverterFlag ) };
auto const meterenabled { ( m_distancecounter >= 0 ) && ( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable) };
if( true == meterenabled ) { m_distancecounter += Distance * Occupied()->CabOccupied; }
else { m_distancecounter = -1.f; }
@@ -7467,7 +7417,7 @@ bool TTrain::CabChange(int iDirection)
|| ( true == DynamicObject->Mechanik->AIControllFlag ) ) {
// jeśli prowadzi AI albo jest w innym członie
// jak AI prowadzi, to nie można mu mieszać
if (abs(DynamicObject->MoverParameters->CabOccupied + iDirection) > 1)
if (std::abs(DynamicObject->MoverParameters->CabOccupied + iDirection) > 1)
return false; // ewentualna zmiana pojazdu
DynamicObject->MoverParameters->CabOccupied =
DynamicObject->MoverParameters->CabOccupied + iDirection;
@@ -8056,7 +8006,7 @@ void TTrain::DynamicSet(TDynamicObject *d)
if( DynamicObject == nullptr ) { return; }
mvControlled = DynamicObject->ControlledFind()->MoverParameters;
mvControlled = DynamicObject->FindPowered()->MoverParameters;
mvSecond = NULL; // gdyby się nic nie znalazło
if (mvOccupied->Power > 1.0) // dwuczłonowe lub ukrotnienia, żeby nie szukać każdorazowo
if (mvOccupied->Couplers[1].Connected ?
@@ -8077,6 +8027,15 @@ void TTrain::DynamicSet(TDynamicObject *d)
mvSecond =
(TMoverParameters *)mvOccupied->Couplers[0].Connected; // wskaźnik na drugiego
}
// cache nearest unit equipped with pantographs
{
auto *lookup { DynamicObject->FindPantographCarrier() };
// HACK: set pointer to existing vehicle to avoid error checking all over the place
mvPantographUnit = (
lookup != nullptr ?
lookup->MoverParameters :
mvControlled );
}
};
void
@@ -8216,7 +8175,7 @@ TTrain::radio_message( sound_source *Message, int const Channel ) {
std::make_shared<sound_source>( m_radiosound ) );
// assign sound to the template and play it
auto &message = *( m_radiomessages.back().second.get() );
auto const radioenabled { ( true == mvOccupied->Radio ) && ( mvControlled->Battery || mvControlled->ConverterFlag ) };
auto const radioenabled { ( true == mvOccupied->Radio ) && ( mvOccupied->Power24vIsAvailable || mvOccupied->Power110vIsAvailable ) };
auto const volume {
( true == radioenabled )
&& ( Channel == RadioChannel() ) ?
@@ -8569,7 +8528,7 @@ void TTrain::set_cab_controls( int const Cab ) {
}
if( ggPantSelectedButton.type() == TGaugeType::toggle ) {
ggPantSelectedButton.PutValue(
( mvControlled->PantsValve.is_enabled ?
( mvPantographUnit->PantsValve.is_enabled ?
1.f :
0.f ) );
}
@@ -8581,7 +8540,7 @@ void TTrain::set_cab_controls( int const Cab ) {
}
if( ggPantSelectedDownButton.type() == TGaugeType::toggle ) {
ggPantSelectedDownButton.PutValue(
( mvControlled->PantsValve.is_disabled ?
( mvPantographUnit->PantsValve.is_disabled ?
1.f :
0.f ) );
}
@@ -8591,7 +8550,7 @@ void TTrain::set_cab_controls( int const Cab ) {
0.f : // default setting is pantographs connected with primary tank
1.f );
ggPantCompressorButton.PutValue(
mvControlled->PantCompFlag ?
mvPantographUnit->PantCompFlag ?
1.f :
0.f );
// converter
@@ -8934,7 +8893,7 @@ bool TTrain::initialize_button(cParser &Parser, std::string const &Label, int co
{ "i-doorpermit_right:", &mvOccupied->Doors.instances[ ( cab_to_end() == end::front ? side::right : side::left ) ].open_permit },
{ "i-doorstep:", &mvOccupied->Doors.step_enabled },
{ "i-mainpipelock:", &mvOccupied->LockPipe },
{ "i-battery:", &mvOccupied->Battery },
{ "i-battery:", &mvOccupied->Power24vIsAvailable },
{ "i-cablight:", &Cabine[ iCabn ].bLight },
};
{
@@ -9155,10 +9114,10 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
{ "doormode_sw:", &mvOccupied->Doors.remote_only },
{ "doorstep_sw:", &mvOccupied->Doors.step_enabled },
{ "coolingfans_sw:", &mvControlled->RVentForceOn },
{ "pantfront_sw:", &mvControlled->Pantographs[end::front].valve.is_enabled },
{ "pantrear_sw:", &mvControlled->Pantographs[end::rear].valve.is_enabled },
{ "pantfrontoff_sw:", &mvControlled->Pantographs[end::front].valve.is_disabled },
{ "pantrearoff_sw:", &mvControlled->Pantographs[end::rear].valve.is_disabled },
{ "pantfront_sw:", &mvPantographUnit->Pantographs[end::front].valve.is_enabled },
{ "pantrear_sw:", &mvPantographUnit->Pantographs[end::rear].valve.is_enabled },
{ "pantfrontoff_sw:", &mvPantographUnit->Pantographs[end::front].valve.is_disabled },
{ "pantrearoff_sw:", &mvPantographUnit->Pantographs[end::rear].valve.is_disabled },
{ "radio_sw:", &mvOccupied->Radio },
{ "cablight_sw:", &Cabine[ iCabn ].bLight },
{ "springbraketoggle_bt:", &mvOccupied->SpringBrake.Activate },
@@ -9307,7 +9266,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
// manometr zbiornika kontrolnego/rorz�du
auto &gauge = Cabine[Cabindex].Gauge(-1); // pierwsza wolna gałka
gauge.Load(Parser, DynamicObject, 0.1);
gauge.AssignDouble(&mvControlled->PantPress);
gauge.AssignDouble(&mvPantographUnit->PantPress);
}
else if (Label == "springbrakepress:")
{
@@ -9351,7 +9310,7 @@ bool TTrain::initialize_gauge(cParser &Parser, std::string const &Label, int con
// pantograph tank pressure
auto &gauge = Cabine[ Cabindex ].Gauge( -1 ); // pierwsza wolna gałka
gauge.Load( Parser, DynamicObject, 0.1 );
gauge.AssignDouble( &mvOccupied->PantPress );
gauge.AssignDouble( &mvPantographUnit->PantPress );
}
// yB - dla drugiej sekcji
else if (Label == "hvbcurrent1:")

View File

@@ -432,6 +432,7 @@ class TTrain {
TMoverParameters *mvOccupied { nullptr }; // człon, w którym sterujemy hamulcem
TMoverParameters *mvSecond { nullptr }; // drugi człon (ET40, ET41, ET42, ukrotnienia)
TMoverParameters *mvThird { nullptr }; // trzeci człon (SN61)
TMoverParameters *mvPantographUnit { nullptr }; // nearest pantograph equipped unit
// helper variable, to prevent immediate switch between closing and opening line breaker circuit
int m_linebreakerstate { 0 }; // 0: open, 1: closed, 2: freshly closed (and yes this is awful way to go about it)
static const commandhandler_map m_commandhandlers;

View File

@@ -676,22 +676,29 @@ debug_panel::update_section_vehicle( std::vector<text_line> &Output ) {
( mover.FuseFlag ? '!' : '.' ),
( false == mover.ConverterAllowLocal ? '-' : ( mover.ConverterAllow ? ( mover.ConverterFlag ? 'X' : 'x' ) : '.' ) ),
( mover.ConvOvldFlag ? '!' : '.' ),
( mover.CompressorFlag ? 'C' : ( false == mover.CompressorAllowLocal ? '-' : ( ( mover.CompressorAllow || mover.CompressorStart == start_t::automatic ) ? 'c' : '.' ) ) ),
( mover.CompressorFlag ? 'C' : ( false == mover.CompressorAllowLocal ? '-' : ( ( mover.CompressorAllow || ( mover.CompressorStart == start_t::automatic && mover.CompressorSpeed > 0.0 ) ) ? 'c' : '.' ) ) ),
( mover.CompressorGovernorLock ? '!' : '.' ),
( mover.StLinSwitchOff ? '-' : ( mover.ControlPressureSwitch ? '!' : ( mover.StLinFlag ? '+' : '.' ) ) ),
( mover.Heating ? 'H' : ( mover.HeatingAllow ? 'h' : '.' ) ),
std::string( isplayervehicle ? locale::strings[ locale::string::debug_vehicle_radio ] + ( mover.Radio ? std::to_string( m_input.train->RadioChannel() ) : "-" ) : "" ).c_str(),
std::string( isdieselenginepowered ? locale::strings[ locale::string::debug_vehicle_oilpressure ] + to_string( mover.OilPump.pressure, 2 ) : "" ).c_str(),
// power transfers
// 3000v
mover.Couplers[ end::front ].power_high.voltage,
mover.Couplers[ end::front ].power_high.current,
std::string( mover.Couplers[ end::front ].power_high.is_local ? ":" : ":=" ).c_str(),
std::string( vehicle.DirectionGet() ? "<<" : ">>" ).c_str(),
mover.EngineVoltage,
std::string( vehicle.DirectionGet() ? "<<" : ">>" ).c_str(),
std::string( mover.Couplers[ end::rear ].power_high.is_local ? ":" : "=:" ).c_str(),
mover.Couplers[ end::rear ].power_high.voltage,
mover.Couplers[ end::rear ].power_high.current );
mover.Couplers[ end::rear ].power_high.current,
// 110v
mover.Couplers[ end::front ].power_110v.voltage,
mover.Couplers[ end::front ].power_110v.current,
std::string( mover.Couplers[ end::front ].power_110v.is_local ? ":" : ":=" ).c_str(),
mover.PowerCircuits[ 1 ].first,
std::string( mover.Couplers[ end::rear ].power_110v.is_local ? ":" : "=:" ).c_str(),
mover.Couplers[ end::rear ].power_110v.voltage,
mover.Couplers[ end::rear ].power_110v.current );
Output.emplace_back( m_buffer.data(), Global.UITextColor );

View File

@@ -57,8 +57,8 @@ light_array::update() {
light.direction.z = -light.direction.z;
}
// determine intensity of this light set
if( ( true == light.owner->MoverParameters->Battery )
|| ( true == light.owner->MoverParameters->ConverterFlag ) ) {
if( ( true == light.owner->MoverParameters->Power24vIsAvailable )
|| ( true == light.owner->MoverParameters->Power110vIsAvailable ) ) {
// with power on, the intensity depends on the state of activated switches
// first we cross-check the list of enabled lights with the lights installed in the vehicle...
auto const lights { light.owner->iLights[ light.index ] & light.owner->LightList( static_cast<end>( light.index ) ) };

View File

@@ -70,7 +70,7 @@ init() {
"Name: %s%s\nLoad: %.0f %s\nStatus: %s%s\nCouplers:\n front: %s\n rear: %s",
", owned by: ",
"none",
"Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s%s[%.0f]%s%s%.0f@%.0f",
"Devices: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nPower transfers: %.0f@%.0f%s[%.0f]%s%.0f@%.0f :: %.0f@%.0f%s[%.0f]%s%.0f@%.0f",
" radio: ",
" oil pressure: ",
"Controllers:\n master: %d(%d), secondary: %s\nEngine output: %.1f, current: %.0f\nRevolutions:\n engine: %.0f, motors: %.0f\n engine fans: %.0f, motor fans: %.0f+%.0f, cooling fans: %.0f+%.0f",
@@ -271,7 +271,7 @@ init() {
"Nazwa: %s%s\nLadunek: %.0f %s\nStatus: %s%s\nSprzegi:\n przedni: %s\n tylny: %s",
", wlasciciel: ",
"wolny",
"Urzadzenia: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nTransfer pradow: %.0f@%.0f%s%s[%.0f]%s%s%.0f@%.0f",
"Urzadzenia: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s\nTransfer pradow: %.0f@%.0f%s[%.0f]%s%.0f@%.0f :: %.0f@%.0f%s[%.0f]%s%.0f@%.0f",
" radio: ",
" cisn.oleju: ",
"Nastawniki:\n glowny: %d(%d), dodatkowy: %s\nMoc silnika: %.1f, prad silnika: %.0f\nObroty:\n silnik: %.0f, motory: %.0f\n went.silnika: %.0f, went.motorow: %.0f+%.0f, went.chlodnicy: %.0f+%.0f",