fix(train): the wheel is learnt from rides GPS covered, whatever its size (ADR 0030, D56)
The measure was held to GPS making 90 % of the wheel's way at the circumference taken, 2105 mm to start: a real wheel under some 1.9 m fell short of it on every ride and was never learnt. A ride now measures where precise fixes followed it for 95 % of its moving time, its quotient between 1 and 3 m as one typed may be. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
ca62ed1aee
commit
9b9b8d08ca
1 changed files with 127 additions and 19 deletions
|
|
@ -168,9 +168,10 @@ int? _wheelTurns(Recording recording) {
|
|||
|
||||
/// The wheel's circumference, in millimetres, [recording] measured by GPS
|
||||
/// (D49): its track's length over the wheel's revolutions, where GPS
|
||||
/// covered the ride (its distance is GPS's: a tunnel's stretch would read
|
||||
/// as a smaller wheel), it went 2 km at least by both and they make a wheel
|
||||
/// (1.5 to 2.5 m); else null.
|
||||
/// covered the ride's moving time (`_gpsCovered`; a tunnel's straight line
|
||||
/// would read as another wheel), it went 2 km at least and they make a
|
||||
/// wheel (1 to 3 m, as one typed may be); else null. Held to time, not to
|
||||
/// the wheel taken: a smaller wheel's ride falls short of it.
|
||||
int? measuredWheelMm(Recording recording) {
|
||||
final gps = _metres(recording);
|
||||
final turns = _wheelTurns(recording);
|
||||
|
|
@ -178,11 +179,79 @@ int? measuredWheelMm(Recording recording) {
|
|||
turns == null ||
|
||||
turns == 0 ||
|
||||
gps < 2000 ||
|
||||
usesWheel(gps, wheelMetresOf(recording))) {
|
||||
!_gpsCovered(recording)) {
|
||||
return null;
|
||||
}
|
||||
final mm = (gps * 1000 / turns).round();
|
||||
return mm >= 1500 && mm <= 2500 ? mm : null;
|
||||
return mm >= 1000 && mm <= 3000 ? mm : null;
|
||||
}
|
||||
|
||||
/// The longest GPS may go without a precise fix while moving, its track
|
||||
/// still the way it went.
|
||||
const _longestGap = Duration(seconds: 30);
|
||||
|
||||
/// The share of the moving time GPS must cover for its track to measure
|
||||
/// the wheel.
|
||||
const _coveredShare = 0.95;
|
||||
|
||||
/// Whether precise fixes followed [recording] for [_coveredShare] of its
|
||||
/// moving time, from its first wheel reading to its last: the time between
|
||||
/// two fixes counts where it is at most [_longestGap] and no pause falls
|
||||
/// between them.
|
||||
bool _gpsCovered(Recording recording) {
|
||||
final wheel = recording.wheel;
|
||||
if (wheel.length < 2) {
|
||||
return false;
|
||||
}
|
||||
final from = wheel.first.time;
|
||||
final to = wheel.last.time;
|
||||
final pauses = recording.pauses;
|
||||
var next = 0;
|
||||
var paused = false;
|
||||
Fix? last;
|
||||
var covered = Duration.zero;
|
||||
for (final fix in recording.fixes) {
|
||||
if (fix.time.isBefore(from) || fix.time.isAfter(to)) {
|
||||
continue;
|
||||
}
|
||||
while (next < pauses.length && !pauses[next].time.isAfter(fix.time)) {
|
||||
paused = pauses[next++].paused;
|
||||
last = null;
|
||||
}
|
||||
if (paused || fix.accuracyCm > maxAccuracyCm) {
|
||||
continue;
|
||||
}
|
||||
if (last != null) {
|
||||
final gap = fix.time.difference(last.time);
|
||||
if (gap <= _longestGap) {
|
||||
covered += gap;
|
||||
}
|
||||
}
|
||||
last = fix;
|
||||
}
|
||||
final moving = _movingBetween(recording, from, to);
|
||||
return moving > Duration.zero &&
|
||||
covered.inMilliseconds >= moving.inMilliseconds * _coveredShare;
|
||||
}
|
||||
|
||||
/// How long [recording] moved between [from] and [to], its pauses left out.
|
||||
Duration _movingBetween(Recording recording, DateTime from, DateTime to) {
|
||||
DateTime clamp(DateTime time) =>
|
||||
time.isBefore(from) ? from : (time.isAfter(to) ? to : time);
|
||||
var moving = to.difference(from);
|
||||
DateTime? pausedAt;
|
||||
for (final mark in recording.pauses) {
|
||||
if (mark.paused) {
|
||||
pausedAt ??= clamp(mark.time);
|
||||
} else if (pausedAt != null) {
|
||||
moving -= clamp(mark.time).difference(pausedAt);
|
||||
pausedAt = null;
|
||||
}
|
||||
}
|
||||
if (pausedAt != null) {
|
||||
moving -= to.difference(pausedAt);
|
||||
}
|
||||
return moving;
|
||||
}
|
||||
|
||||
/// The metres the rower counted while not paused: each frame's growth over
|
||||
|
|
|
|||
Loading…
Reference in a new issue