Manufacturing
A machine tool's spindle temperature and load are sampled at 1 Hz without timestamps, so the Detector is built with a sampling rate and derives each Sample's timestamp from its position (sampling-rate mode). Here the spindle heats up at 1 °C/s to 100 °C under load, stays there, and cools down again.
The live chart and its controls need JavaScript. The tables show the Events at the default parameters.
The site cannot run the default parameters: (JavaScript) TypeError: Cannot read properties of undefined (reading 'length')
import static io.github.romanhaendler.rbed.Conditions.*;
import io.github.romanhaendler.rbed.*;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Channel load = Channel.named("load");
Channel temp = Channel.named("temp");
Rule highLoad = Rule.named("HighLoad")
.when(load.above(80)).forDuration(Duration.ofSeconds(10))
.endWhen(load.below(60));
Rule overheat = Rule.named("Overheat")
.when(temp.above(80)).forDuration(Duration.ofSeconds(30))
.endWhen(temp.below(70)).forDuration(Duration.ofMinutes(1));
Rule overheatUnderLoad = Rule.named("OverheatUnderLoad")
.when(during(overheat).and(during(highLoad)));
Rule fastHeating = Rule.named("FastHeating").when(temp.rate().above(0.5)).forSamples(5);
Detector detector = Detector.builder()
.samplingRate(1) // 1 Hz: values without timestamps
.rules(highLoad, overheat, overheatUnderLoad, fastHeating)
.build();
List<Map<Channel, Double>> series = new ArrayList<>();
for (int s = 0; s < 600; s++) series.add(Map.of(temp, spindleTemp(s), load, spindleLoad(s)));
List<Event> events = detector.detectValues(series);
// In the enclosing class:
static double spindleTemp(int s) { // °C
if (s < 100) return 60;
if (s < 140) return 60 + (s - 100); // heating at 1 °C/s
if (s < 300) return 100;
if (s < 335) return 100 - (s - 300); // cooling at 1 °C/s
return 65;
}
static double spindleLoad(int s) { // %
return s < 100 ? 50 : s < 400 ? 90 : 40;
}
The Rules
- Overheat: above 80 °C for 30 s, over only once below 70 °C for a minute (hysteresis).
- HighLoad: load above 80 % for 10 s, over below 60 %.
- OverheatUnderLoad: both at once,
duringcombined withand. - FastHeating: heating faster than 0.5 °C/s for 5 consecutive Samples.
At the defaults, the load is 90 % from 100 s to 400 s, so HighLoad runs from 100 s to 400 s, Confirmed at 110 s. The temperature rises from 101 s, and FastHeating runs from there, Confirmed at the fifth Sample at 105 s, to 141 s, the first Sample without a rise. It passes 80 °C at 121 s: Overheat is Confirmed 30 s later, at 151 s, and OverheatUnderLoad starts with it. The temperature falls below 70 °C at 331 s, where Overheat Ends.
OverheatUnderLoad Ends only at 391 s: during(overheat) stays true until Overheat's End Condition has held for its minute (391 s), although its end timestamp is where the End Condition began (331 s). A streaming Detector cannot know earlier that the Event is over.
Things to try
- Raise Overheat for to 60 s:
Overheatis Confirmed at 181 s instead of 151 s, andOverheatUnderLoadwith it.
Reference
The example is MachineToolOverheatExample, a test with its expected Events, listed in the README's Examples.
Methods used: Channel.named, Rule.named, Rule.when, Expression.above, Rule.forDuration, Rule.endWhen, Expression.below, Conditions.during, Condition.and, ChannelExpression.rate, Rule.forSamples, Detector.builder, Detector.Builder.samplingRate, Detector.Builder.rules, Detector.Builder.build, Detector.detectValues.
The concepts at work, each on a page of its own: Batch processing and sampling rates, Conditions and Expressions, During another Event, End Conditions and hysteresis.