Skip to content

Commit a406a69

Browse files
committed
Officially support common circuit breaker variants
1 parent 1c55709 commit a406a69

File tree

3 files changed

+271
-10
lines changed

3 files changed

+271
-10
lines changed

Source/Documentation/Manual/features-rollingstock.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,8 +1912,18 @@ Use the following .eng parameter to load a circuit breaker script::
19121912
)
19131913

19141914
``ORTSCircuitBreaker`` refers to the circuit breaker script in the engine's ``Script``
1915-
subfolder. For this field, the .cs extension is optional. "Automatic" and "Manual" load the generic OR
1916-
circuit breaker implementation, so do `not` use these names for your own script.
1915+
subfolder. For this field, the .cs extension is optional. Alternatively, there are several
1916+
built-in OR circuit breaker implementations:
1917+
1918+
- "Automatic": no driver intervention required, circuit breaker is closed when conditions are met.
1919+
- "Manual": a circuit breaker switch with open and closed positions.
1920+
- "PushButtons": a circuit breaker with dedicated open and close buttons.
1921+
- "TwoStage": circuit breaker closing is authorized by a switch. If the switch is off,
1922+
the circuit breaker is kept open. Once the switch is activated, it is required to use
1923+
a second button to order the closing.
1924+
1925+
Please do `not` use these names for your own script, since the generic implementation will
1926+
be loaded instead.
19171927

19181928
``ORTSCircuitBreakerClosingDelay`` refers to the delay between the closing command of the circuit breaker
19191929
and the effective closing of the circuit breaker.

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/CircuitBreaker.cs

Lines changed: 257 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,22 @@ public void Initialize()
109109
{
110110
if (ScriptName != null)
111111
{
112-
switch(ScriptName)
112+
switch(ScriptName.ToLowerInvariant())
113113
{
114-
case "Automatic":
115-
Script = new AutomaticCircuitBreaker() as CircuitBreaker;
114+
case "automatic":
115+
Script = new AutomaticCircuitBreaker();
116116
break;
117117

118-
case "Manual":
119-
Script = new ManualCircuitBreaker() as CircuitBreaker;
118+
case "manual":
119+
Script = new ManualCircuitBreaker();
120+
break;
121+
122+
case "pushbuttons":
123+
Script = new PushButtonsCircuitBreaker();
124+
break;
125+
126+
case "twostage":
127+
Script = new TwoStageCircuitBreaker();
120128
break;
121129

122130
default:
@@ -128,7 +136,7 @@ public void Initialize()
128136
// Fallback to automatic circuit breaker if the above failed.
129137
if (Script == null)
130138
{
131-
Script = new AutomaticCircuitBreaker() as CircuitBreaker;
139+
Script = new AutomaticCircuitBreaker();
132140
}
133141

134142
Script.AttachToHost(this);
@@ -371,6 +379,7 @@ public override void HandleEvent(PowerSupplyEvent evt)
371379
{
372380
switch (evt)
373381
{
382+
case PowerSupplyEvent.QuickPowerOn:
374383
case PowerSupplyEvent.CloseCircuitBreaker:
375384
SetDriverClosingOrder(true);
376385
SetDriverOpeningOrder(false);
@@ -383,6 +392,7 @@ public override void HandleEvent(PowerSupplyEvent evt)
383392
}
384393
break;
385394

395+
case PowerSupplyEvent.QuickPowerOff:
386396
case PowerSupplyEvent.OpenCircuitBreaker:
387397
SetDriverClosingOrder(false);
388398
SetDriverOpeningOrder(true);
@@ -393,4 +403,245 @@ public override void HandleEvent(PowerSupplyEvent evt)
393403
}
394404
}
395405
}
406+
407+
public class PushButtonsCircuitBreaker : CircuitBreaker
408+
{
409+
private Timer ClosingTimer;
410+
private CircuitBreakerState PreviousState;
411+
private bool QuickPowerOn;
412+
413+
public override void Initialize()
414+
{
415+
ClosingTimer = new Timer(this);
416+
ClosingTimer.Setup(ClosingDelayS());
417+
418+
SetDriverClosingAuthorization(true);
419+
}
420+
421+
public override void Update(float elapsedSeconds)
422+
{
423+
SetClosingAuthorization(TCSClosingAuthorization() && CurrentPantographState() == PantographState.Up);
424+
425+
switch (CurrentState())
426+
{
427+
case CircuitBreakerState.Closed:
428+
if (!ClosingAuthorization() || DriverOpeningOrder() || TCSOpeningOrder())
429+
{
430+
SetCurrentState(CircuitBreakerState.Open);
431+
}
432+
break;
433+
434+
case CircuitBreakerState.Closing:
435+
if (ClosingAuthorization() && (DriverClosingOrder() || TCSClosingOrder() || QuickPowerOn))
436+
{
437+
if (!ClosingTimer.Started)
438+
{
439+
ClosingTimer.Start();
440+
}
441+
442+
if (ClosingTimer.Triggered)
443+
{
444+
QuickPowerOn = false;
445+
ClosingTimer.Stop();
446+
SetCurrentState(CircuitBreakerState.Closed);
447+
}
448+
}
449+
else
450+
{
451+
QuickPowerOn = false;
452+
ClosingTimer.Stop();
453+
SetCurrentState(CircuitBreakerState.Open);
454+
}
455+
break;
456+
457+
case CircuitBreakerState.Open:
458+
if (ClosingAuthorization() && (DriverClosingOrder() || TCSClosingOrder() || QuickPowerOn))
459+
{
460+
SetCurrentState(CircuitBreakerState.Closing);
461+
}
462+
break;
463+
}
464+
465+
if (PreviousState != CurrentState())
466+
{
467+
switch (CurrentState())
468+
{
469+
case CircuitBreakerState.Open:
470+
SignalEvent(Event.CircuitBreakerOpen);
471+
break;
472+
473+
case CircuitBreakerState.Closing:
474+
SignalEvent(Event.CircuitBreakerClosing);
475+
break;
476+
477+
case CircuitBreakerState.Closed:
478+
SignalEvent(Event.CircuitBreakerClosed);
479+
break;
480+
}
481+
}
482+
483+
PreviousState = CurrentState();
484+
}
485+
486+
public override void HandleEvent(PowerSupplyEvent evt)
487+
{
488+
switch (evt)
489+
{
490+
case PowerSupplyEvent.CloseCircuitBreakerButtonPressed:
491+
SetDriverOpeningOrder(false);
492+
SetDriverClosingOrder(true);
493+
SignalEvent(Event.CircuitBreakerClosingOrderOn);
494+
Confirm(CabControl.CircuitBreakerClosingOrder, CabSetting.On);
495+
if (!ClosingAuthorization())
496+
{
497+
Message(ConfirmLevel.Warning, Simulator.Catalog.GetString("Circuit breaker closing not authorized"));
498+
}
499+
break;
500+
case PowerSupplyEvent.CloseCircuitBreakerButtonReleased:
501+
SetDriverClosingOrder(false);
502+
break;
503+
case PowerSupplyEvent.OpenCircuitBreakerButtonPressed:
504+
SetDriverClosingOrder(false);
505+
SetDriverOpeningOrder(true);
506+
SignalEvent(Event.CircuitBreakerClosingOrderOff);
507+
Confirm(CabControl.CircuitBreakerClosingOrder, CabSetting.Off);
508+
break;
509+
case PowerSupplyEvent.OpenCircuitBreakerButtonReleased:
510+
SetDriverOpeningOrder(false);
511+
break;
512+
case PowerSupplyEvent.QuickPowerOn:
513+
QuickPowerOn = true;
514+
break;
515+
case PowerSupplyEvent.QuickPowerOff:
516+
QuickPowerOn = false;
517+
SetCurrentState(CircuitBreakerState.Open);
518+
break;
519+
}
520+
}
521+
}
522+
523+
public class TwoStageCircuitBreaker : CircuitBreaker
524+
{
525+
private Timer ClosingTimer;
526+
private CircuitBreakerState PreviousState;
527+
528+
private Timer InitTimer;
529+
private bool QuickPowerOn;
530+
531+
public override void Initialize()
532+
{
533+
ClosingTimer = new Timer(this);
534+
ClosingTimer.Setup(ClosingDelayS());
535+
}
536+
537+
public override void Update(float elapsedSeconds)
538+
{
539+
540+
SetClosingAuthorization(TCSClosingAuthorization() && DriverClosingAuthorization() && CurrentPantographState() == PantographState.Up);
541+
542+
switch (CurrentState())
543+
{
544+
case CircuitBreakerState.Closed:
545+
if (!ClosingAuthorization() || TCSOpeningOrder())
546+
{
547+
SetCurrentState(CircuitBreakerState.Open);
548+
}
549+
break;
550+
551+
case CircuitBreakerState.Closing:
552+
if (ClosingAuthorization() && (DriverClosingOrder() || TCSClosingOrder() || QuickPowerOn))
553+
{
554+
if (!ClosingTimer.Started)
555+
{
556+
ClosingTimer.Start();
557+
}
558+
559+
if (ClosingTimer.Triggered)
560+
{
561+
QuickPowerOn = false;
562+
ClosingTimer.Stop();
563+
SetCurrentState(CircuitBreakerState.Closed);
564+
}
565+
}
566+
else
567+
{
568+
QuickPowerOn = false;
569+
ClosingTimer.Stop();
570+
SetCurrentState(CircuitBreakerState.Open);
571+
}
572+
break;
573+
574+
case CircuitBreakerState.Open:
575+
if (ClosingAuthorization() && (DriverClosingOrder() || TCSClosingOrder() || QuickPowerOn))
576+
{
577+
SetCurrentState(CircuitBreakerState.Closing);
578+
}
579+
break;
580+
}
581+
582+
if (PreviousState != CurrentState())
583+
{
584+
switch (CurrentState())
585+
{
586+
case CircuitBreakerState.Open:
587+
SignalEvent(Event.CircuitBreakerOpen);
588+
break;
589+
590+
case CircuitBreakerState.Closing:
591+
SignalEvent(Event.CircuitBreakerClosing);
592+
break;
593+
594+
case CircuitBreakerState.Closed:
595+
SignalEvent(Event.CircuitBreakerClosed);
596+
break;
597+
}
598+
}
599+
600+
PreviousState = CurrentState();
601+
}
602+
603+
public override void HandleEvent(PowerSupplyEvent evt)
604+
{
605+
switch (evt)
606+
{
607+
case PowerSupplyEvent.CloseCircuitBreakerButtonPressed:
608+
SetDriverClosingOrder(true);
609+
SignalEvent(Event.CircuitBreakerClosingOrderOn);
610+
Confirm(CabControl.CircuitBreakerClosingOrder, CabSetting.On);
611+
if (!ClosingAuthorization())
612+
{
613+
Message(ConfirmLevel.Warning, Simulator.Catalog.GetString("Circuit breaker closing not authorized"));
614+
}
615+
break;
616+
617+
case PowerSupplyEvent.CloseCircuitBreakerButtonReleased:
618+
SetDriverClosingOrder(false);
619+
SignalEvent(Event.CircuitBreakerClosingOrderOff);
620+
break;
621+
622+
case PowerSupplyEvent.GiveCircuitBreakerClosingAuthorization:
623+
SetDriverClosingAuthorization(true);
624+
SignalEvent(Event.CircuitBreakerClosingAuthorizationOn);
625+
Confirm(CabControl.CircuitBreakerClosingAuthorization, CabSetting.On);
626+
break;
627+
628+
case PowerSupplyEvent.RemoveCircuitBreakerClosingAuthorization:
629+
SetDriverClosingAuthorization(false);
630+
SignalEvent(Event.CircuitBreakerClosingAuthorizationOff);
631+
Confirm(CabControl.CircuitBreakerClosingAuthorization, CabSetting.Off);
632+
break;
633+
634+
case PowerSupplyEvent.QuickPowerOn:
635+
QuickPowerOn = true;
636+
SetDriverClosingAuthorization(true);
637+
break;
638+
639+
case PowerSupplyEvent.QuickPowerOff:
640+
QuickPowerOn = false;
641+
SetDriverClosingAuthorization(false);
642+
SetCurrentState(CircuitBreakerState.Open);
643+
break;
644+
}
645+
}
646+
}
396647
}

Source/Orts.Simulation/Simulation/RollingStocks/SubSystems/PowerSupplies/ElectricPowerSupply.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public override void Update(float elapsedClockSeconds)
205205
if (QuickPowerOn)
206206
{
207207
QuickPowerOn = false;
208-
SignalEventToCircuitBreaker(PowerSupplyEvent.CloseCircuitBreaker);
208+
SignalEventToCircuitBreaker(PowerSupplyEvent.QuickPowerOn);
209209
}
210210

211211
if (PowerOnTimer.Started)
@@ -277,7 +277,7 @@ public override void HandleEvent(PowerSupplyEvent evt)
277277
case PowerSupplyEvent.QuickPowerOff:
278278
QuickPowerOn = false;
279279
SignalEventToElectricTrainSupplySwitch(PowerSupplyEvent.SwitchOffElectricTrainSupply);
280-
SignalEventToCircuitBreaker(PowerSupplyEvent.OpenCircuitBreaker);
280+
SignalEventToCircuitBreaker(PowerSupplyEvent.QuickPowerOff);
281281
SignalEventToPantographs(PowerSupplyEvent.LowerPantograph);
282282
SignalEventToOtherTrainVehicles(PowerSupplyEvent.LowerPantograph);
283283
SignalEventToMasterKey(PowerSupplyEvent.TurnOffMasterKey);

0 commit comments

Comments
 (0)