implements better flank detection, adds spreadsheet for analysis
Added the flankdetector, to reliably detect an acceleration or deceleration of the flywheel Added extra metrics for the creation of TCX-files Added extra metrics (speed in m/s and cadence) to allow future export of this data to Garmin TCX files, which everybody seems to love. I increased the priority of the GPIO-service, as I noticed that much of the measurement noise originates from delayed read-outs of the GPIO. An Excel tool to "play" with the settings of a rower, to adjust the settings found in the rowerprofiles.js Adds test and data for RX800 rower Lightweight version of Excel file Co-authored-by: Lars Berning <151194+laberning@users.noreply.github.com>
This commit is contained in:
parent
1f947bd1d8
commit
2c6819ca02
|
|
@ -0,0 +1,68 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
|
||||
This keeps an array, which we can test for an upgoing or downgoing flank
|
||||
|
||||
Please note: The array contains flankLenght + 1 measured currentDt's, thus flankLenght number of flanks between them
|
||||
They are arranged that dataPoints[0] is the youngest, and dataPoints[flankLength] the youngest
|
||||
*/
|
||||
function createMovingFlankDetector (flankLength, initValue, numberOfErrorsAllowed) {
|
||||
const dataPoints = new Array(flankLength + 1)
|
||||
dataPoints.fill(initValue)
|
||||
|
||||
function pushValue (dataPoint) {
|
||||
// add the new dataPoint to the array, we have to move datapoints starting at the oldst ones
|
||||
let i = flankLength
|
||||
while (i > 0) {
|
||||
// older datapoints are moved toward the higher numbers
|
||||
dataPoints[i] = dataPoints[i - 1]
|
||||
i = i - 1
|
||||
}
|
||||
dataPoints[0] = dataPoint
|
||||
}
|
||||
|
||||
function isDecelerating () {
|
||||
let i = flankLength
|
||||
let numberOfErrors = 0
|
||||
while (i > 0) {
|
||||
if (dataPoints[i] < dataPoints[i - 1]) {
|
||||
// Oldest interval (dataPoints[i]) is shorter than the younger one (datapoint[i-1], as the distance is fixed, we are decelerating
|
||||
} else {
|
||||
numberOfErrors = numberOfErrors + 1
|
||||
}
|
||||
i = i - 1
|
||||
}
|
||||
if (numberOfErrors > numberOfErrorsAllowed) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
function isAccelerating () {
|
||||
let i = flankLength
|
||||
let numberOfErrors = 0
|
||||
while (i > 0) {
|
||||
if (dataPoints[i] > dataPoints[i - 1]) {
|
||||
// Oldest interval (dataPoints[i]) is longer than the younger one (datapoint[i-1], as the distance is fixed, we are accelerating
|
||||
} else {
|
||||
numberOfErrors = numberOfErrors + 1
|
||||
}
|
||||
i = i - 1
|
||||
}
|
||||
if (numberOfErrors > numberOfErrorsAllowed) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pushValue,
|
||||
isDecelerating,
|
||||
isAccelerating
|
||||
}
|
||||
}
|
||||
|
||||
export { createMovingFlankDetector }
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
import loglevel from 'loglevel'
|
||||
import { createWeightedAverager } from './WeightedAverager.js'
|
||||
import { createMovingFlankDetector } from './MovingFlankDetector.js'
|
||||
import { createTimer } from './Timer.js'
|
||||
|
||||
const log = loglevel.getLogger('RowingEngine')
|
||||
|
|
@ -55,6 +56,8 @@ function createRowingEngine (rowerSettings) {
|
|||
|
||||
let workoutHandler
|
||||
const kDampEstimatorAverager = createWeightedAverager(3)
|
||||
const flankDetector = createMovingFlankDetector(rowerSettings.numOfImpulsesPerRevolution, rowerSettings.maximumTimeBetweenMagnets, 0)
|
||||
let prevDt = rowerSettings.maximumTimeBetweenMagnets
|
||||
let kPower = 0.0
|
||||
let jPower = 0.0
|
||||
let kDampEstimator = 0.0
|
||||
|
|
@ -84,6 +87,18 @@ function createRowingEngine (rowerSettings) {
|
|||
return
|
||||
}
|
||||
|
||||
// remember the state of drive phase from the previous impulse, we need it to detect state changes
|
||||
wasInDrivePhase = isInDrivePhase
|
||||
|
||||
// STEP 1: reduce noise in the measurements by applying some sanity checks
|
||||
// noise filter on the value of currentDt: it should be within sane levels and should not deviate too much from the previous reading
|
||||
if (currentDt < rowerSettings.minimumTimeBetweenMagnets || currentDt > rowerSettings.maximumTimeBetweenMagnets || currentDt < (rowerSettings.maximumDownwardChange * prevDt) || currentDt > (rowerSettings.maximumUpwardChange * prevDt)) {
|
||||
// impulses are outside plausible ranges, so we assume it is close to the previous one
|
||||
currentDt = prevDt
|
||||
log.debug(`noise filter corrected currentDt, ${currentDt} was dubious, changed to ${prevDt}`)
|
||||
}
|
||||
prevDt = currentDt
|
||||
|
||||
// each revolution of the flywheel adds distance of distancePerRevolution
|
||||
strokeDistance += distancePerRevolution / numOfImpulsesPerRevolution
|
||||
|
||||
|
|
@ -109,8 +124,7 @@ function createRowingEngine (rowerSettings) {
|
|||
// used to be 15
|
||||
const accelerationIsPositive = omegaDotVector[0] > 0
|
||||
|
||||
wasInDrivePhase = isInDrivePhase
|
||||
|
||||
// STEP 2: detect where we are in the rowing phase (drive or recovery)
|
||||
if (liquidFlywheel) {
|
||||
// Identification of drive and recovery phase on water rowers is still Work in Progress
|
||||
// ω does not seem to decay that linear on water rower in recovery phase, so this would not be
|
||||
|
|
@ -121,11 +135,23 @@ function createRowingEngine (rowerSettings) {
|
|||
// todo: do some measurements and find a better stable indicator for water rowers
|
||||
isInDrivePhase = accelerationIsPositive
|
||||
} else {
|
||||
// ω decays linear on rowers with a solid flywheel, so we can use that to differentiate the phases
|
||||
isInDrivePhase = accelerationIsChanging || (accelerationIsPositive && wasInDrivePhase)
|
||||
flankDetector.pushValue(currentDt)
|
||||
// Here we use a finite state machine that goes between "Drive" and "Recovery", provinding sufficient time has passed and there is a credible flank
|
||||
// We analyse the current impulse, depending on where we are in the stroke
|
||||
if (wasInDrivePhase) {
|
||||
// during the previous impulse, we were in the "Drive" phase
|
||||
const strokeElapsed = timer.getValue('drive')
|
||||
// finish drive phase if we have been long enough in the Drive phase, and we see a clear deceleration
|
||||
isInDrivePhase = !((strokeElapsed > rowerSettings.minimumDriveTime) && flankDetector.isDecelerating())
|
||||
} else {
|
||||
// during the previous impulse, we were in the "Recovery" phase
|
||||
const recoveryElapsed = timer.getValue('stroke')
|
||||
// if we are long enough in the Recovery phase, and we see a clear acceleration, we need to change to the Drive phase
|
||||
isInDrivePhase = ((recoveryElapsed > rowerSettings.minimumRecoveryTime) && flankDetector.isAccelerating())
|
||||
}
|
||||
}
|
||||
|
||||
// handle the current impulse, depending on where we are in the stroke
|
||||
// STEP 3: handle the current impulse, depending on where we are in the stroke
|
||||
if (isInDrivePhase && !wasInDrivePhase) { startDrivePhase(currentDt) }
|
||||
if (!isInDrivePhase && wasInDrivePhase) { startRecoveryPhase() }
|
||||
if (isInDrivePhase && wasInDrivePhase) { updateDrivePhase(currentDt) }
|
||||
|
|
@ -166,7 +192,9 @@ function createRowingEngine (rowerSettings) {
|
|||
|
||||
if (strokeElapsed !== 0 && workoutHandler) {
|
||||
workoutHandler.handleStroke({
|
||||
power: (jPower + kPower) / strokeElapsed,
|
||||
// if the recoveryPhase is shorter than 0.2 seconds we set it to 2 seconds, this mitigates the problem
|
||||
// that we do not have a recovery phase on the first stroke
|
||||
power: (jPower + kPower) / (((strokeElapsed - driveElapsed) < 0.2) ? strokeElapsed + 2 : strokeElapsed),
|
||||
duration: strokeElapsed,
|
||||
durationDrivePhase: driveElapsed,
|
||||
distance: strokeDistance,
|
||||
|
|
|
|||
|
|
@ -48,9 +48,7 @@ test('sample data for WRX700 should produce plausible results with rower profile
|
|||
rowingEngine.notify(workoutEvaluator)
|
||||
await replayRowingSession(rowingEngine.handleRotationImpulse, { filename: 'recordings/WRX700_2magnets.csv' })
|
||||
assert.is(workoutEvaluator.getNumOfStrokes(), 16, 'number of strokes does not meet expectation')
|
||||
// todo: maximum power of the first stroke is too high because it does not contain a recovery part
|
||||
// should fix that in the RowingEngine and adjust the maximum power here to 220
|
||||
assert.ok(workoutEvaluator.getMaxStrokePower() < 370, `maximum stroke power should be below 370w, but is ${workoutEvaluator.getMaxStrokePower()}w`)
|
||||
assert.ok(workoutEvaluator.getMaxStrokePower() < 220, `maximum stroke power should be below 220w, but is ${workoutEvaluator.getMaxStrokePower()}w`)
|
||||
assert.ok(workoutEvaluator.getMinStrokePower() > 50, `minimum stroke power should be above 50w, but is ${workoutEvaluator.getMinStrokePower()}w`)
|
||||
})
|
||||
|
||||
|
|
@ -60,10 +58,18 @@ test('sample data for DKNR320 should produce plausible results with rower profil
|
|||
rowingEngine.notify(workoutEvaluator)
|
||||
await replayRowingSession(rowingEngine.handleRotationImpulse, { filename: 'recordings/DKNR320.csv' })
|
||||
assert.is(workoutEvaluator.getNumOfStrokes(), 10, 'number of strokes does not meet expectation')
|
||||
// todo: maximum power of the first stroke is too high because it does not contain a recovery part
|
||||
// should fix that in the RowingEngine and adjust the maximum power here to 200
|
||||
assert.ok(workoutEvaluator.getMaxStrokePower() < 370, `maximum stroke power should be below 370w, but is ${workoutEvaluator.getMaxStrokePower()}w`)
|
||||
assert.ok(workoutEvaluator.getMaxStrokePower() < 200, `maximum stroke power should be below 200w, but is ${workoutEvaluator.getMaxStrokePower()}w`)
|
||||
assert.ok(workoutEvaluator.getMinStrokePower() > 75, `minimum stroke power should be above 75w, but is ${workoutEvaluator.getMinStrokePower()}w`)
|
||||
})
|
||||
|
||||
test('sample data for RX800 should produce plausible results with rower profile', async () => {
|
||||
const rowingEngine = createRowingEngine(rowerProfiles.RX800)
|
||||
const workoutEvaluator = createWorkoutEvaluator()
|
||||
rowingEngine.notify(workoutEvaluator)
|
||||
await replayRowingSession(rowingEngine.handleRotationImpulse, { filename: 'recordings/RX800.csv' })
|
||||
assert.is(workoutEvaluator.getNumOfStrokes(), 10, 'number of strokes does not meet expectation')
|
||||
assert.ok(workoutEvaluator.getMaxStrokePower() < 260, `maximum stroke power should be below 260, but is ${workoutEvaluator.getMaxStrokePower()}w`)
|
||||
assert.ok(workoutEvaluator.getMinStrokePower() > 160, `minimum stroke power should be above 160w, but is ${workoutEvaluator.getMinStrokePower()}w`)
|
||||
})
|
||||
|
||||
test.run()
|
||||
|
|
|
|||
|
|
@ -8,8 +8,21 @@
|
|||
*/
|
||||
import process from 'process'
|
||||
import { Gpio } from 'onoff'
|
||||
import os from 'os'
|
||||
import config from '../tools/ConfigManager.js'
|
||||
import log from 'loglevel'
|
||||
|
||||
log.setLevel(config.loglevel.default)
|
||||
|
||||
export function createGpioTimerService () {
|
||||
// setting top (near-real-time) priority for the Gpio process, as we don't want to miss anything
|
||||
log.debug('setting priority for the Gpio-service to maximum (-20)')
|
||||
try {
|
||||
// setting priority of current process
|
||||
os.setPriority(-20)
|
||||
} catch (err) {
|
||||
log.error('error while setting priority of Gpio-Thread: ', err)
|
||||
}
|
||||
// mode can be rising, falling, both
|
||||
const reedSensor = new Gpio(17, 'in', 'rising')
|
||||
// use hrtime for time measurement to get a higher time precision
|
||||
|
|
|
|||
|
|
@ -75,6 +75,21 @@ rowingStatistics.on('strokeFinished', (metrics) => {
|
|||
`, split: ${metrics.splitFormatted}, ratio: ${metrics.powerRatio}, dist: ${metrics.distanceTotal}m` +
|
||||
`, cal: ${metrics.caloriesTotal}kcal, SPM: ${metrics.strokesPerMinute}, speed: ${metrics.speed}km/h` +
|
||||
`, cal/hour: ${metrics.caloriesPerHour}kcal, cal/minute: ${metrics.caloriesPerMinute}kcal`)
|
||||
// Quick hack to generate tcx-trackpoints to get the basic concepts of TCX-export working
|
||||
/*
|
||||
const d = new Date()
|
||||
const timestamp = d.toISOString()
|
||||
fs.appendFile('exports/currentlog.tcx',
|
||||
`<Trackpoint>\n <Time>${timestamp}</Time>\n` +
|
||||
`<DistanceMeters>${metrics.distanceTotal}</DistanceMeters>\n` +
|
||||
`<Cadence>${Math.round(metrics.strokesPerMinute)}</Cadence>\n` +
|
||||
'<SensorState>Present</SensorState>\n' +
|
||||
'<Extensions>\n <ns3:TPX>\n' +
|
||||
`<ns3:Watts>${metrics.power}</ns3:Watts>\n` +
|
||||
`<ns3:Speed>${(metrics.speed / 3.6).toFixed(2)}</ns3:Speed>\n` +
|
||||
'</ns3:TPX>\n </Extensions>\n</Trackpoint>\n',
|
||||
(err) => { if (err) log.error(err) })
|
||||
*/
|
||||
webServer.notifyClients(metrics)
|
||||
peripheralManager.notifyMetrics('strokeFinished', metrics)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -16,6 +16,18 @@ export default {
|
|||
// i.e. the number of magnets if used with a reed sensor
|
||||
numOfImpulsesPerRevolution: 1,
|
||||
|
||||
// Filter values for sanity checks
|
||||
// First are the sane minimum and maximum times between magnets during active rows
|
||||
minimumTimeBetweenMagnets: 0.014,
|
||||
maximumTimeBetweenMagnets: 0.5,
|
||||
// Procentual change between successive intervals
|
||||
maximumDownwardChange: 0.2, // effectively the maximum deceleration
|
||||
maximumUpwardChange: 1.75, // effectively the maximum acceleration
|
||||
// Settings for the phase detection
|
||||
minimumDriveTime: 0.300,
|
||||
minimumRecoveryTime: 0.750,
|
||||
|
||||
|
||||
// Needed to determine the damping constant of the rowing machine. This value can be measured in the recovery phase
|
||||
// of the stroke (some ergometers do this constantly).
|
||||
// However I still keep it constant here, as I still have to figure out the damping physics of a water rower (see below)
|
||||
|
|
@ -50,10 +62,10 @@ export default {
|
|||
// Sportstech WRX700
|
||||
WRX700: {
|
||||
numOfImpulsesPerRevolution: 2,
|
||||
minimumTimeBetweenMagnets: 0.1,
|
||||
maximumTimeBetweenMagnets: 0.4,
|
||||
maximumDownwardChange: 0.40,
|
||||
maximumUpwardChange: 1.50,
|
||||
minimumTimeBetweenMagnets: 0.05,
|
||||
maximumTimeBetweenMagnets: 1,
|
||||
maximumDownwardChange: 0.25,
|
||||
maximumUpwardChange: 2,
|
||||
minimumDriveTime: 0.500,
|
||||
minimumRecoveryTime: 0.800,
|
||||
omegaDotDivOmegaSquare: 0.046,
|
||||
|
|
@ -77,8 +89,8 @@ export default {
|
|||
|
||||
// NordicTrack RX800 Air Rower
|
||||
RX800: {
|
||||
liquidFlywheel: false,
|
||||
numOfImpulsesPerRevolution: 4,
|
||||
liquidFlywheel: false,
|
||||
|
||||
// Damper setting 10
|
||||
minimumTimeBetweenMagnets: 0.018,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
# Set Up of the Open Rowing Monitor settings for a specific rower
|
||||
|
||||
This guide helps you to adjust the rowing monitor specifically for your rower or even for you
|
||||
|
||||
## Why have setings
|
||||
|
||||
No rowingmachine is the same, and their physical construction is important for the Rowing Monitor to understand to be able to understand your rowing. Easiest way is to select your rower from owerProfiles.js and put its name in default.config.js instead of "rowerProfiles.DEFAULT".
|
||||
|
||||
If your rower isn't there, this guide will help you set it up (please send in the data and settings, so we can add it to the OpenRowingMonitor).
|
||||
|
||||
Settings important for Open Rowing Monitor:
|
||||
|
||||
* numOfImpulsesPerRevolution: tells Open Rowing Monitor how many impulses per rotation of the flywheel to expect. Although sometimes not easy to detect, you can sometimes find it in the manual under the parts-list
|
||||
* liquidFlywheel: tells OpenRowingMonitor if you are using a waterrower (true) or a solid flywheel with magnetic or air-resistance (false)
|
||||
* omegaDotDivOmegaSquare: tells OpenRowingMonitor how much damping and thus resistance your flywheel is offering. This is typically also dependent on your damper-setting (if present). To measure it for your rowing machine, comment in the logging at the end of "startDrivePhase" function. Then do some strokes on the rower and estimate a value based on the logging.
|
||||
* jMoment: The inertia of the flywheel, which in practice influences your power values and distance. This typically is set by rowing and see what kind of power is displayed on the monitor. Typical ranges are weigth dependent (see [this explanation](https://www.rowingmachine-guide.com/tabata-rowing-workouts.html)).
|
||||
* Noise reduction settings. You should only change these settings if you experience issues.
|
||||
* minimumTimeBetweenImpulses
|
||||
* maximumTimeBetweenImpulses
|
||||
* maximumDownwardChange
|
||||
* maximumUpwardChange
|
||||
* Stroke detection settings.
|
||||
* minimumDriveTime
|
||||
* minimumRecoveryTime
|
||||
|
||||
For the noise reduction settings and stroke detection settings, you can use the Excel tool. When OpenRowingMonitor records a log (comment out the line in server.js), you can paste the values in the first column of the "Raw Data" tab (please observe that the Raspberry uses a point as seperator, and your version of Excel might expect a comma). From there, the Excel file simulates the calculations the OpenRowingMonitor makes, allowing you to play with these settings.
|
||||
|
||||
By changing the noise reduction settings, you can remove any obvious errors. You don't need to filter everything: it is just to remove obvious errors that might frustrate the stroke detection, but in the end you can't prevent every piece of noise out there. Begin with the noise filtering, when you are satisfied, you can adjust the stroke detection.
|
||||
|
||||
Please note that changing the noise filtering and stroke detection settings will affect your omegaDotDivOmegaSquare and jMoment. So it is best to start with rowing a few strokes to determine settings for noise filtering and stroke detection, and then move on to the other settings.
|
||||
Binary file not shown.
|
|
@ -25,7 +25,8 @@ print "This script will set up Open Rowing Monitor on a Raspberry Pi 3 / 4 with
|
|||
print "You should only run this script on a SD Card that does not contain any important data."
|
||||
print
|
||||
|
||||
if [[ "$(uname -n)" != "raspberrypi" ]]; then
|
||||
OSID=$(grep -oP '(?<=^ID=).+' /etc/os-release | tr -d '"')
|
||||
if [[ $OSID != "raspbian" ]]; then
|
||||
cancel "This script currently only works on Raspberry Pi OS, you will have to do a manual installation."
|
||||
fi
|
||||
|
||||
|
|
@ -35,6 +36,8 @@ if [[ $VERSION != "10 (buster)" ]]; then
|
|||
print "You are running Raspberry Pi OS $VERSION, are you sure that you want to continue?"
|
||||
fi
|
||||
|
||||
# todo: once we know what hardware we support we can check for that via /sys/firmware/devicetree/base/model
|
||||
|
||||
print
|
||||
read -p "Press RETURN to continue or CTRL + C to abort"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,931 @@
|
|||
115.678730412
|
||||
7.94730349
|
||||
0.110655271
|
||||
0.077529811
|
||||
0.062992882
|
||||
0.053962555
|
||||
0.047993133
|
||||
0.043563433
|
||||
0.040500379
|
||||
0.037841367
|
||||
0.035730194
|
||||
0.033988063
|
||||
0.032694066
|
||||
0.031287698
|
||||
0.03023863
|
||||
0.029224544
|
||||
0.028584529
|
||||
0.027804209
|
||||
0.027228518
|
||||
0.026601604
|
||||
0.02622834
|
||||
0.025706705
|
||||
0.025334405
|
||||
0.025007717
|
||||
0.024811381
|
||||
0.02453186
|
||||
0.024368987
|
||||
0.024340543
|
||||
0.024487044
|
||||
0.024602878
|
||||
0.024564859
|
||||
0.024720028
|
||||
0.025279589
|
||||
0.02465499
|
||||
0.025149718
|
||||
0.025149365
|
||||
0.025259812
|
||||
0.025432313
|
||||
0.025509907
|
||||
0.02563813
|
||||
0.025838689
|
||||
0.025927634
|
||||
0.025995875
|
||||
0.026110136
|
||||
0.026352212
|
||||
0.026413232
|
||||
0.026417213
|
||||
0.026604456
|
||||
0.026904274
|
||||
0.026781476
|
||||
0.026986071
|
||||
0.027189332
|
||||
0.027265704
|
||||
0.027384224
|
||||
0.027518281
|
||||
0.027624877
|
||||
0.027859003
|
||||
0.027958782
|
||||
0.028054579
|
||||
0.028164673
|
||||
0.028417454
|
||||
0.028516639
|
||||
0.028558973
|
||||
0.028746289
|
||||
0.028958662
|
||||
0.029114553
|
||||
0.029130072
|
||||
0.029342333
|
||||
0.02957265
|
||||
0.02962728
|
||||
0.029873597
|
||||
0.029832375
|
||||
0.030176193
|
||||
0.030259786
|
||||
0.030379659
|
||||
0.03055529
|
||||
0.030806885
|
||||
0.030893256
|
||||
0.031081851
|
||||
0.031216426
|
||||
0.031459502
|
||||
0.031524466
|
||||
0.03170106
|
||||
0.031872858
|
||||
0.032085064
|
||||
0.031965693
|
||||
0.031717746
|
||||
0.031340261
|
||||
0.030476501
|
||||
0.029614239
|
||||
0.028671859
|
||||
0.027737258
|
||||
0.027034733
|
||||
0.026210503
|
||||
0.025537071
|
||||
0.024957325
|
||||
0.024545025
|
||||
0.023962463
|
||||
0.023533571
|
||||
0.023152975
|
||||
0.022930417
|
||||
0.022550007
|
||||
0.022305263
|
||||
0.02208515
|
||||
0.021964297
|
||||
0.021756721
|
||||
0.021738295
|
||||
0.02186987
|
||||
0.02129668
|
||||
0.021308476
|
||||
0.02200065
|
||||
0.02156783
|
||||
0.021978149
|
||||
0.022081743
|
||||
0.022036594
|
||||
0.022198206
|
||||
0.022369301
|
||||
0.022337801
|
||||
0.022457524
|
||||
0.022883991
|
||||
0.022335375
|
||||
0.022751897
|
||||
0.023201587
|
||||
0.02251482
|
||||
0.023127364
|
||||
0.023257346
|
||||
0.022998529
|
||||
0.023309106
|
||||
0.023810389
|
||||
0.023168789
|
||||
0.023598238
|
||||
0.023773503
|
||||
0.023775277
|
||||
0.023906482
|
||||
0.02399452
|
||||
0.02407765
|
||||
0.02429867
|
||||
0.02432617
|
||||
0.024424042
|
||||
0.024526765
|
||||
0.02470647
|
||||
0.024749545
|
||||
0.02486149
|
||||
0.024947824
|
||||
0.02514453
|
||||
0.025196197
|
||||
0.025300939
|
||||
0.02539544
|
||||
0.02559533
|
||||
0.025752202
|
||||
0.025703349
|
||||
0.025826313
|
||||
0.026817266
|
||||
0.025348124
|
||||
0.026221317
|
||||
0.026347614
|
||||
0.026551283
|
||||
0.026602727
|
||||
0.026710135
|
||||
0.02684221
|
||||
0.027094694
|
||||
0.027109639
|
||||
0.027203381
|
||||
0.027410289
|
||||
0.027474068
|
||||
0.027628144
|
||||
0.027736478
|
||||
0.02788259
|
||||
0.028100203
|
||||
0.028185202
|
||||
0.028227738
|
||||
0.028413369
|
||||
0.028648815
|
||||
0.028713298
|
||||
0.028844187
|
||||
0.02902467
|
||||
0.029164005
|
||||
0.029129375
|
||||
0.029028003
|
||||
0.028715371
|
||||
0.028230942
|
||||
0.027403268
|
||||
0.026514317
|
||||
0.025669996
|
||||
0.024969342
|
||||
0.024160336
|
||||
0.023867796
|
||||
0.022693047
|
||||
0.022650991
|
||||
0.022198247
|
||||
0.021833022
|
||||
0.021517908
|
||||
0.021319777
|
||||
0.021019479
|
||||
0.02080281
|
||||
0.020632549
|
||||
0.020567141
|
||||
0.020413788
|
||||
0.020344436
|
||||
0.020309991
|
||||
0.020409881
|
||||
0.020586994
|
||||
0.020312269
|
||||
0.020637864
|
||||
0.020928477
|
||||
0.020416677
|
||||
0.020740883
|
||||
0.020987478
|
||||
0.020907348
|
||||
0.02105222
|
||||
0.021295684
|
||||
0.021022905
|
||||
0.021335929
|
||||
0.021515244
|
||||
0.021309335
|
||||
0.021518485
|
||||
0.022034063
|
||||
0.021357094
|
||||
0.021787838
|
||||
0.021993932
|
||||
0.021921672
|
||||
0.022061507
|
||||
0.022377343
|
||||
0.021966987
|
||||
0.022375287
|
||||
0.022552585
|
||||
0.022377416
|
||||
0.022565288
|
||||
0.022832345
|
||||
0.022696567
|
||||
0.022873383
|
||||
0.02302668
|
||||
0.023156644
|
||||
0.023027884
|
||||
0.023247089
|
||||
0.023342738
|
||||
0.023537554
|
||||
0.023543684
|
||||
0.023658611
|
||||
0.023728593
|
||||
0.023912001
|
||||
0.023941057
|
||||
0.024042724
|
||||
0.024150688
|
||||
0.024311671
|
||||
0.024365264
|
||||
0.024458969
|
||||
0.02459095
|
||||
0.024706136
|
||||
0.02478936
|
||||
0.02489062
|
||||
0.02503525
|
||||
0.025131491
|
||||
0.02523614
|
||||
0.025332048
|
||||
0.025463773
|
||||
0.025590698
|
||||
0.02568518
|
||||
0.025785125
|
||||
0.025866958
|
||||
0.026099515
|
||||
0.026158257
|
||||
0.026251517
|
||||
0.026376573
|
||||
0.026573501
|
||||
0.026637482
|
||||
0.026751112
|
||||
0.026859835
|
||||
0.027081652
|
||||
0.027135022
|
||||
0.027240986
|
||||
0.027369543
|
||||
0.027756878
|
||||
0.02733606
|
||||
0.027475525
|
||||
0.027725655
|
||||
0.026831743
|
||||
0.026708927
|
||||
0.02611533
|
||||
0.025523067
|
||||
0.024970472
|
||||
0.024312819
|
||||
0.023734927
|
||||
0.023239386
|
||||
0.022890662
|
||||
0.0224464
|
||||
0.022083583
|
||||
0.021769211
|
||||
0.021553709
|
||||
0.021266226
|
||||
0.021045892
|
||||
0.020831131
|
||||
0.020753186
|
||||
0.020596592
|
||||
0.020478981
|
||||
0.020447655
|
||||
0.020518947
|
||||
0.020718467
|
||||
0.020377187
|
||||
0.02065504
|
||||
0.020983727
|
||||
0.0206228
|
||||
0.020881115
|
||||
0.021115654
|
||||
0.020988597
|
||||
0.021144858
|
||||
0.021619786
|
||||
0.020896857
|
||||
0.021452508
|
||||
0.021660101
|
||||
0.021355119
|
||||
0.021634879
|
||||
0.021936677
|
||||
0.021694602
|
||||
0.021868417
|
||||
0.022137752
|
||||
0.022055548
|
||||
0.022093381
|
||||
0.022786312
|
||||
0.021745472
|
||||
0.022486846
|
||||
0.022588588
|
||||
0.022551013
|
||||
0.022682996
|
||||
0.023087721
|
||||
0.022701644
|
||||
0.02297509
|
||||
0.023565094
|
||||
0.022699311
|
||||
0.023277999
|
||||
0.023439278
|
||||
0.023387926
|
||||
0.023629464
|
||||
0.023870855
|
||||
0.023559964
|
||||
0.023847577
|
||||
0.024125004
|
||||
0.023969429
|
||||
0.024162949
|
||||
0.02427719
|
||||
0.02443412
|
||||
0.024506765
|
||||
0.024580248
|
||||
0.024685433
|
||||
0.024856397
|
||||
0.024947324
|
||||
0.025012602
|
||||
0.025120306
|
||||
0.025315232
|
||||
0.025371011
|
||||
0.02546277
|
||||
0.025564974
|
||||
0.025774457
|
||||
0.025814421
|
||||
0.025928513
|
||||
0.026035995
|
||||
0.026229459
|
||||
0.026297274
|
||||
0.026674164
|
||||
0.026244977
|
||||
0.026738276
|
||||
0.026812517
|
||||
0.026804499
|
||||
0.027016852
|
||||
0.027338446
|
||||
0.0271385
|
||||
0.027401335
|
||||
0.027507335
|
||||
0.027737189
|
||||
0.027782097
|
||||
0.027756096
|
||||
0.02761417
|
||||
0.027369761
|
||||
0.026738572
|
||||
0.026071699
|
||||
0.025357288
|
||||
0.024756082
|
||||
0.024050819
|
||||
0.023470031
|
||||
0.022975463
|
||||
0.022622389
|
||||
0.022212831
|
||||
0.021848144
|
||||
0.021575162
|
||||
0.021398828
|
||||
0.021141956
|
||||
0.020915696
|
||||
0.02076764
|
||||
0.020709103
|
||||
0.020557825
|
||||
0.020475083
|
||||
0.020441435
|
||||
0.020516324
|
||||
0.0208824
|
||||
0.020203137
|
||||
0.020692196
|
||||
0.02093166
|
||||
0.020601936
|
||||
0.020884067
|
||||
0.021384161
|
||||
0.0209749
|
||||
0.02081214
|
||||
0.02122542
|
||||
0.02151481
|
||||
0.021201642
|
||||
0.021485569
|
||||
0.02173194
|
||||
0.021428605
|
||||
0.02175733
|
||||
0.021974497
|
||||
0.021782348
|
||||
0.021889848
|
||||
0.022251368
|
||||
0.02207333
|
||||
0.022183312
|
||||
0.022623666
|
||||
0.022233942
|
||||
0.022455424
|
||||
0.023861967
|
||||
0.021408809
|
||||
0.022842278
|
||||
0.022991705
|
||||
0.022864871
|
||||
0.023062835
|
||||
0.023389387
|
||||
0.023109059
|
||||
0.023356763
|
||||
0.023604745
|
||||
0.023485616
|
||||
0.02361943
|
||||
0.023870246
|
||||
0.02372219
|
||||
0.024017266
|
||||
0.024178858
|
||||
0.024056617
|
||||
0.024241692
|
||||
0.0244936
|
||||
0.024421378
|
||||
0.024563156
|
||||
0.024694472
|
||||
0.024843916
|
||||
0.024890064
|
||||
0.025007287
|
||||
0.025220621
|
||||
0.025245287
|
||||
0.025292621
|
||||
0.025450344
|
||||
0.025550529
|
||||
0.02584179
|
||||
0.025754974
|
||||
0.025907957
|
||||
0.026291644
|
||||
0.025872864
|
||||
0.02625768
|
||||
0.026443736
|
||||
0.026446569
|
||||
0.026693478
|
||||
0.026781571
|
||||
0.026840941
|
||||
0.026994571
|
||||
0.027214905
|
||||
0.027294202
|
||||
0.027376851
|
||||
0.027500962
|
||||
0.027689521
|
||||
0.027693276
|
||||
0.027614202
|
||||
0.027347034
|
||||
0.026932607
|
||||
0.026196346
|
||||
0.025462437
|
||||
0.02478951
|
||||
0.024261415
|
||||
0.023633858
|
||||
0.023142356
|
||||
0.022748615
|
||||
0.022468522
|
||||
0.022088687
|
||||
0.021797298
|
||||
0.02154026
|
||||
0.02138689
|
||||
0.021137555
|
||||
0.020965888
|
||||
0.021211
|
||||
0.020445998
|
||||
0.020534424
|
||||
0.020850128
|
||||
0.020236257
|
||||
0.020565758
|
||||
0.020728795
|
||||
0.020597035
|
||||
0.020743072
|
||||
0.021064647
|
||||
0.020751036
|
||||
0.020997666
|
||||
0.021524094
|
||||
0.020719554
|
||||
0.021249
|
||||
0.021410889
|
||||
0.021312722
|
||||
0.02156389
|
||||
0.021988947
|
||||
0.021290593
|
||||
0.021679482
|
||||
0.02222691
|
||||
0.021593593
|
||||
0.02198328
|
||||
0.02211454
|
||||
0.022137443
|
||||
0.022277172
|
||||
0.022386858
|
||||
0.022454154
|
||||
0.022589191
|
||||
0.022630709
|
||||
0.022718191
|
||||
0.022811062
|
||||
0.022959359
|
||||
0.023008136
|
||||
0.0230971
|
||||
0.023185081
|
||||
0.023357304
|
||||
0.023393267
|
||||
0.023487859
|
||||
0.023575934
|
||||
0.023742934
|
||||
0.023786082
|
||||
0.023881971
|
||||
0.023974749
|
||||
0.024267824
|
||||
0.024098416
|
||||
0.024273398
|
||||
0.024496565
|
||||
0.024459028
|
||||
0.024605084
|
||||
0.024733862
|
||||
0.024814399
|
||||
0.024967084
|
||||
0.025036047
|
||||
0.025147215
|
||||
0.025273307
|
||||
0.025447678
|
||||
0.025470512
|
||||
0.025604327
|
||||
0.025772049
|
||||
0.025838604
|
||||
0.025945308
|
||||
0.02606729
|
||||
0.026149939
|
||||
0.026373217
|
||||
0.026454032
|
||||
0.026514106
|
||||
0.029372646
|
||||
0.024299214
|
||||
0.026766809
|
||||
0.02724531
|
||||
0.026901568
|
||||
0.027349848
|
||||
0.027429551
|
||||
0.027561421
|
||||
0.027643163
|
||||
0.027711385
|
||||
0.027513069
|
||||
0.027226773
|
||||
0.026645383
|
||||
0.026096439
|
||||
0.025404752
|
||||
0.02491753
|
||||
0.02416527
|
||||
0.023825102
|
||||
0.023376584
|
||||
0.023004805
|
||||
0.022632083
|
||||
0.022424563
|
||||
0.022105786
|
||||
0.021883989
|
||||
0.021674544
|
||||
0.021585711
|
||||
0.021380896
|
||||
0.021255248
|
||||
0.021153784
|
||||
0.021188803
|
||||
0.021369507
|
||||
0.020650302
|
||||
0.02102997
|
||||
0.021639322
|
||||
0.020711599
|
||||
0.021290358
|
||||
0.021449136
|
||||
0.021460099
|
||||
0.021547359
|
||||
0.021632507
|
||||
0.021699227
|
||||
0.021858288
|
||||
0.021883992
|
||||
0.021968288
|
||||
0.022047715
|
||||
0.022206011
|
||||
0.02223627
|
||||
0.022318511
|
||||
0.02240103
|
||||
0.022560566
|
||||
0.022594752
|
||||
0.022694862
|
||||
0.022755863
|
||||
0.022924955
|
||||
0.022977196
|
||||
0.023081604
|
||||
0.023109603
|
||||
0.023290623
|
||||
0.023350901
|
||||
0.023434623
|
||||
0.023632197
|
||||
0.023634919
|
||||
0.02369479
|
||||
0.023831845
|
||||
0.023930901
|
||||
0.024107937
|
||||
0.02416579
|
||||
0.024232456
|
||||
0.024347252
|
||||
0.024517975
|
||||
0.024571716
|
||||
0.024661068
|
||||
0.024767623
|
||||
0.024945161
|
||||
0.024998513
|
||||
0.025097456
|
||||
0.025206586
|
||||
0.025402365
|
||||
0.025430549
|
||||
0.025545383
|
||||
0.025717457
|
||||
0.02578229
|
||||
0.025925289
|
||||
0.025969365
|
||||
0.026119921
|
||||
0.026331216
|
||||
0.026384106
|
||||
0.026482976
|
||||
0.02660679
|
||||
0.026809643
|
||||
0.026838698
|
||||
0.026979143
|
||||
0.027098568
|
||||
0.027311364
|
||||
0.027379698
|
||||
0.02750018
|
||||
0.027600605
|
||||
0.027821254
|
||||
0.027885901
|
||||
0.028153308
|
||||
0.028103772
|
||||
0.028140494
|
||||
0.028043754
|
||||
0.027678864
|
||||
0.027128254
|
||||
0.026512716
|
||||
0.025741198
|
||||
0.025076476
|
||||
0.024474588
|
||||
0.024034013
|
||||
0.023519421
|
||||
0.023091736
|
||||
0.02275818
|
||||
0.022489625
|
||||
0.022155087
|
||||
0.021895365
|
||||
0.02167757
|
||||
0.021563291
|
||||
0.021364347
|
||||
0.021239402
|
||||
0.021144329
|
||||
0.02111657
|
||||
0.02099871
|
||||
0.020966167
|
||||
0.020930685
|
||||
0.021043888
|
||||
0.02142337
|
||||
0.020759722
|
||||
0.021209795
|
||||
0.021955146
|
||||
0.020781815
|
||||
0.021602759
|
||||
0.021749869
|
||||
0.02132761
|
||||
0.021719147
|
||||
0.022234442
|
||||
0.021459685
|
||||
0.021988258
|
||||
0.022147887
|
||||
0.022077683
|
||||
0.022227073
|
||||
0.022466146
|
||||
0.022376554
|
||||
0.022639387
|
||||
0.022535221
|
||||
0.022700831
|
||||
0.022835294
|
||||
0.022798497
|
||||
0.022958887
|
||||
0.023137498
|
||||
0.023184683
|
||||
0.023257386
|
||||
0.023339756
|
||||
0.023519997
|
||||
0.023562108
|
||||
0.02372422
|
||||
0.023726738
|
||||
0.023924756
|
||||
0.023944386
|
||||
0.024020608
|
||||
0.024135182
|
||||
0.024329737
|
||||
0.024366404
|
||||
0.024470422
|
||||
0.024548015
|
||||
0.024751811
|
||||
0.024793636
|
||||
0.024921683
|
||||
0.024996386
|
||||
0.025196293
|
||||
0.025206812
|
||||
0.0253172
|
||||
0.025433626
|
||||
0.025633977
|
||||
0.025681829
|
||||
0.025790866
|
||||
0.025897236
|
||||
0.026101403
|
||||
0.026144403
|
||||
0.026283698
|
||||
0.026368218
|
||||
0.026574309
|
||||
0.026627531
|
||||
0.026738124
|
||||
0.026992809
|
||||
0.026950994
|
||||
0.027134568
|
||||
0.027158456
|
||||
0.027364123
|
||||
0.027576641
|
||||
0.027657159
|
||||
0.027778993
|
||||
0.0278644
|
||||
0.028082862
|
||||
0.028053992
|
||||
0.027852677
|
||||
0.027509141
|
||||
0.027151179
|
||||
0.026383958
|
||||
0.025696848
|
||||
0.025127849
|
||||
0.024619202
|
||||
0.02399948
|
||||
0.023564759
|
||||
0.023171753
|
||||
0.022900725
|
||||
0.022543079
|
||||
0.022238283
|
||||
0.021994709
|
||||
0.021873709
|
||||
0.021626618
|
||||
0.021497229
|
||||
0.021381673
|
||||
0.021356896
|
||||
0.021232896
|
||||
0.021182452
|
||||
0.021129859
|
||||
0.021221303
|
||||
0.021639802
|
||||
0.02084012
|
||||
0.021332581
|
||||
0.021859987
|
||||
0.0211616
|
||||
0.021616432
|
||||
0.021803154
|
||||
0.021856265
|
||||
0.021751969
|
||||
0.021956338
|
||||
0.022520189
|
||||
0.021661544
|
||||
0.02219006
|
||||
0.022312912
|
||||
0.022391634
|
||||
0.022559208
|
||||
0.0226248
|
||||
0.022659504
|
||||
0.022757171
|
||||
0.022910596
|
||||
0.022977632
|
||||
0.023024559
|
||||
0.02313167
|
||||
0.023295188
|
||||
0.023340984
|
||||
0.023412484
|
||||
0.02351565
|
||||
0.023694205
|
||||
0.023731242
|
||||
0.023812872
|
||||
0.023918353
|
||||
0.024087379
|
||||
0.024130596
|
||||
0.024223317
|
||||
0.02434028
|
||||
0.024493947
|
||||
0.024544853
|
||||
0.024653464
|
||||
0.024725742
|
||||
0.024928223
|
||||
0.024975778
|
||||
0.025079556
|
||||
0.025208258
|
||||
0.025392425
|
||||
0.025399388
|
||||
0.025553888
|
||||
0.025549906
|
||||
0.025823424
|
||||
0.025998868
|
||||
0.025865461
|
||||
0.026131404
|
||||
0.02625683
|
||||
0.026343107
|
||||
0.02645757
|
||||
0.026576032
|
||||
0.026783606
|
||||
0.02683655
|
||||
0.026965624
|
||||
0.027074512
|
||||
0.027281401
|
||||
0.027333271
|
||||
0.027407993
|
||||
0.027577807
|
||||
0.027798677
|
||||
0.027872695
|
||||
0.02796725
|
||||
0.028118935
|
||||
0.028317305
|
||||
0.028374564
|
||||
0.028373278
|
||||
0.028223657
|
||||
0.027903992
|
||||
0.027208883
|
||||
0.02650146
|
||||
0.025809925
|
||||
0.02528102
|
||||
0.0246758
|
||||
0.024167727
|
||||
0.023704191
|
||||
0.023414211
|
||||
0.022959065
|
||||
0.022660677
|
||||
0.022364233
|
||||
0.022168698
|
||||
0.021985957
|
||||
0.02162994
|
||||
0.021570847
|
||||
0.021424348
|
||||
0.021360163
|
||||
0.021154164
|
||||
0.021102313
|
||||
0.021189923
|
||||
0.021629218
|
||||
0.020866979
|
||||
0.021217053
|
||||
0.021707366
|
||||
0.021245071
|
||||
0.021565181
|
||||
0.021939309
|
||||
0.0214702
|
||||
0.021823032
|
||||
0.02204005
|
||||
0.021857828
|
||||
0.022149271
|
||||
0.022573678
|
||||
0.021833292
|
||||
0.022337364
|
||||
0.022574104
|
||||
0.022462474
|
||||
0.022607436
|
||||
0.023096434
|
||||
0.022456122
|
||||
0.022914917
|
||||
0.023221312
|
||||
0.022849865
|
||||
0.023207345
|
||||
0.023634213
|
||||
0.022982902
|
||||
0.023455807
|
||||
0.023694343
|
||||
0.02362138
|
||||
0.02376875
|
||||
0.023959212
|
||||
0.023906064
|
||||
0.024067211
|
||||
0.024217618
|
||||
0.024209637
|
||||
0.024437506
|
||||
0.024557228
|
||||
0.024516469
|
||||
0.024703375
|
||||
0.024877041
|
||||
0.02496567
|
||||
0.025000023
|
||||
0.02504167
|
||||
0.02529617
|
||||
0.025353243
|
||||
0.025516891
|
||||
0.025564668
|
||||
0.02575537
|
||||
0.025809833
|
||||
0.025912666
|
||||
0.025995129
|
||||
0.026223461
|
||||
0.026277035
|
||||
0.026386886
|
||||
0.026501924
|
||||
0.026742237
|
||||
0.026711737
|
||||
0.02687557
|
||||
0.027060735
|
||||
0.027143124
|
||||
0.027273271
|
||||
0.027341164
|
||||
0.027508437
|
||||
0.027724863
|
||||
0.027823955
|
||||
0.027899121
|
||||
0.028032565
|
||||
0.028283527
|
||||
0.028205564
|
||||
0.028228415
|
||||
|
Loading…
Reference in New Issue