Small changes to docs.
Node.js CI / build (14.x) (push) Has been cancelled Details
Node.js CI / build (16.x) (push) Has been cancelled Details

This commit is contained in:
cyteen 2024-12-06 21:31:32 +00:00
parent 1e3091c746
commit a5c11bf173
2 changed files with 251 additions and 30 deletions

View File

@ -375,14 +375,20 @@ data; however, this method easily introduces noise due to friction during motion
##### Holyiot nRF52840 USB Dongle
##### DIY nRF52840 implementing [Reefwing-AHRS](https://github.com/Reefwing-Software/Reefwing-AHRS) to provide reliable roll, pitch and yaw angles.
* [LSM9DS1](https://www.st.com/en/mems-and-sensors/lsm9ds1.html) 9-axis IMU [Reefwing-LSM9DS1](https://github.com/Reefwing-Software/Reefwing-LSM9DS1)
* [MPU6050](https://invensense.tdk.com/products/motion-tracking/6-axis/mpu-6050/) 6-axis IMU [Reefwing-MPU6050](https://github.com/Reefwing-Software/Reefwing-MPU6050)
* [MPU6500](https://invensense.tdk.com/products/motion-tracking/6-axis/mpu-6500/) 6-axis IMU [Reefwing-MPU6x00](https://github.com/Reefwing-Software/MPU6x00)
##### Beacon for handle, seat and trunk
| NRF chip | RAM | ROM | Notes |
|----------|-----|-----|-------|
| 52810 | 24k | 192k | BARELY enough RAM for "broadcast only" function |
| 52820 | 32k | 256k | Untested, should work just as the 832 does |
| 52832 | 64/32 KB | 512/256 KB | Enough RAM for additional sensors |
| 52840 | 256 KB | 1 MB | Untested; probably overkill for this application |
| NRF chip | RAM | ROM | Notes |
|----------|----------|------------|-------------------------------------------------|
| 52810 | 24k | 192k | BARELY enough RAM for "broadcast only" function |
| 52820 | 32k | 256k | Untested, should work just as the 832 does |
| 52832 | 64/32 KB | 512/256 KB | Enough RAM for additional sensors |
| 52840 | 256 KB | 1 MB | Untested; probably overkill for this application|
* 3x [holyiot 21014]() nRF52810 + lis2dh12 + RGB LED + button
* [holyiot 21014 zephyr project](https://github.com/danielstuart14/wlen_project/tree/master/beacon/boards/arm/holyiot_21014)
@ -410,7 +416,10 @@ using a simple camera.
* Automatic Rowing Kinematic Analysis Using OpenPose and Dynamic Time Warping]
* [An introduction to Dynamic Time Warping](https://rtavenar.github.io/blog/dtw.html)
* [dtw-python](https://dynamictimewarping.github.io/py-api/html/index.html)
In order to apply the DTW algorithm, we first need to choose a reference or desired rowing cycle. The paper above chooses to take the rowing cycle from a known good rower, we want to take the rowing cycle from the Biomechanics of Rowing book chapter 4: Technique.
In order to apply the DTW algorithm, we first need to choose a reference or
desired rowing cycle. The paper above chooses to take the rowing cycle from a
known good rower, we want to take the rowing cycle from the Biomechanics of
Rowing book chapter 4: Technique.
[Intelligent Performance Evaluation in Rowing Sport Using a Graph-Matching Network](https://pmc.ncbi.nlm.nih.gov/articles/PMC10532480/)
This study aimed to develop a video-based approach to analyze the performance of
@ -419,6 +428,17 @@ poses, the OpenPose system was used to extract robust rowing pose features and
convert them into a graph structure. Subsequently, the GEM and GMN models were
utilized to analyze the similarities in rowing postures between each pair of rowers.
[Inaccurate Action Detection Algorithm for Rowing Machine Exercise Based on
Attention-CNN](https://ieeexplore.ieee.org/iel8/6287639/10380310/10638659.pdf)
Assessing the conformity of a rowers actions using [OpenPose](https://github.com/CMU-Perceptual-Computing-Lab/openpose)
, [1D CNN](https://www.mdpi.com/2076-3417/14/18/8500) and
[CoT](https://www.ibm.com/topics/chain-of-thoughts) to recognize
whether the movement is standard.
[1D Convolutional Neural Network Models for Human Activity Recognition](https://machinelearningmastery.com/cnn-models-for-human-activity-recognition-time-series-classification/)
Classifying sequences of accelerometer data recorded by specialized harnesses or
smart phones into known well-defined movements.
### [Rowsandall](https://analytics.rowsandall.com/) Rowsandall Rowing Data Analytics
For our Basic user, the website is Free. Within this package you get

View File

@ -1,4 +1,4 @@
# Wattage predictions
# Wattage predictions
See:
@ -7,29 +7,24 @@ See:
## Zones
See:
* Indoor Rowing Training Guide, Version 2 by Terry ONeill and Alex Skelton.
* [Interactive_Training_Plans.xlsx](Interact_Training_Plans.xlsx)
Heart rate zones are calculated based on HRR calculated from:
Resting heart rate (RHR) 58
Maximum heart rate (MHR) 165
Heart rate reserve (HRR) (MHR minus RHR) 107
| Training Band | %HRR | %2k (W) | range |
|------------------------------|--------|---------------|-------|
| Oxygen Utilisation 2 (UT2) | 65-70 | 45-60 | 15% |
| Oxygen Utilisation 1 (UT1) | 70-80 | 60-70 | 10% |
| Anaerobic Threshold (AT) | 80-85 | 70-80 | 10% |
| VO2 Max/Transport (TR) | 85-95 | 80-105 | 25% |
| Peak Power/Anaerobic (AN) | 95-100 | 105-115 | 10% |
From [Stumpy](https://thestumpyrower.wordpress.com/rowing-on-the-concept-2-ergometer/56-2/)
| Training Band | s.min1* | %2k (w)** | HRR*** |
|---------------|---------|-----------|--------|
| Oxygen Utilisation 2 | UT2 | 16-20 | 45-60 |
| Oxygen Utilisation 1 | UT1 | 20-24 | 60-70 |
| Anaerobic Threshold | AT | 24-28 | 70-80 |
| VO2 Max/Transport | TR | 28-32 | 80-105 |
| Peak Power/Anaerobic | AN | 32+ | 105-115 |
| Training Band | s.min-1 | %HRR | %2k (W) | range |
|------------------------------|---------|--------|---------------|-------|
| Oxygen Utilisation 2 (UT2) | 16-20 | 65-70 | 45-60 | 15% |
| Oxygen Utilisation 1 (UT1) | 20-24 | 70-80 | 60-70 | 10% |
| Anaerobic Threshold (AT) | 24-28 | 80-85 | 70-80 | 10% |
| VO2 Max/Transport (TR) | 28-32 | 85-95 | 80-105 | 25% |
| Peak Power/Anaerobic (AN) | 32+ | 95-100 | 105-115 | 10% |
*s.min-1 is scientific notation for strokes/minute
@ -56,9 +51,9 @@ so 132 bmp should be 4 fifths into that 15% = 12%
so expected power is 110W/(45%+12%) = 193W
## Example 2
## Example 2
### Take the result of example 1 and a zone and provide a suitable training session.
### Take the result of example 1 and a zone and provide a suitable training session
Given zone: UT2 is midpoint of range:
0.5*(45+60) = 52.5% of 192W = 101.3W
@ -66,9 +61,215 @@ Given zone: UT2 is midpoint of range:
Given zone: AT:
0.5*(70+80) = 75% of 193W = 144.7W
### Examples 3
## Examples 3
### Return a training zone from a [training table](Interactive_Training_Plans.xlsx) Level 5 | 8 sessions | 26 weeks
### Return a training zone from a [training table](Interactive_Training_Plans.xlsx)
Given a level 1-5 and a week number and a session number return the associated
Given a level 1-5, a session number and a week number return the associated
session eg 3x16'UT1
#### Available Levels
Level 1 | 3 Sessions | 26 Weeks
Level 2 | 3 Sessions | 26 Weeks
Level 2 | 4 Sessions | 26 Weeks
Level 3 | 4 Sessions | 26 Weeks
Level 4 | 4 Sessions | 26 Weeks
Level 4 | 5 Sessions | 26 Weeks
Level 4 | 6 Sessions | 26 Weeks
Level 5 | 6 Sessions | 26 Weeks
Level 5 | 7 Sessions | 26 Weeks
Level 5 | 8 Sessions | 26 Weeks
cat level-1_3-session_26-weeks.csv
```csv
"Interactive 2,000m Programme",,,
2000m 26 Week Training Programme,,,
"Athlete Level 1, 3 Sessions a Week",,,
Week,Session 1,Session 2,Session 3
1,TEST,12'UT2,15'UT2
2,14'UT2,16'UT2,18'UT2
3,17'UT2,19'UT2,20'UT2
4,10'UT1,25'UT2,30'UT2
5,12'UT1,18'UT1,8'AT
6,30'UT2,2x10'UT1,2x7'AT
7,15'UT1,20'UT2,7'AT
8,18'UT1,25UT2,9'AT
9,4x2'TR,30'UT2,2X12'UT1
10,2x2'TR,15'UT1,20'UT2
11,4x2'TR,18'UT1,25'UT2
12,6x2'TR,2X12'UT1,30'UT2
13,TEST,2x3'TR,2x7'AT
14,4x2'TR,16'UT1,25'UT2
15,2x4'TR,2x12'UT1,3x7'AT
16,6x2'TR,2x8'UT1,20'UT2
17,2x9'AT,18'UT1,30'UT2
18,2x10'AT,3x2'TR,20'UT1
19,4x1.5'AN,2x12UT1,2x8'AT
20,3x2'TR,25'UT1,2x9'AT
21,2x4'TR,30'UT2,2x10'AT
22,2x4'TR,15'UT1,2x7'AT
23,30'UT2,18'UT1,2x9'AT
24,3x2'TR,30'UT2,2x12'UT1
25,5x2'TR,6x1.5'AN,3x3'TR
26,2x1.5'AN,3x45s AN,RACE
```
Interactive 2,000m Programme
2000m 26 Week Training Programme
Athlete Level 5, 8 Sessions a Week
| Week | Session 1 | Session 2 | Session 3 | Session 4 | Session 5 | Session 6 | Session 7 | Session 8 |
|------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|-----------|
| 1 | TEST | 2x15'UT1 | 55'UT2 | 2x18'UT1 | 68'UT2 | 3x15'UT1 | 55'UT2 | 2x15'UT1 |
| 2 | 65'UT2 | 2x21'UT1 | 72'UT2 | 3x16'UT1 | 80'UT2 | 4x13'UT1 | 72'UT2 | 3x12'UT1 |
| 3 | 76'UT2 | 3x17'UT1 | 85'UT2 | 3x19'UT1 | 90'UT2 | 3x20'UT1 | 85'UT2 | 2x25'UT1 |
| 4 | 45'UT2 | 2x15'UT1 | 2x6'AT | 3x12'UT1 | 2x7'AT | 3x15'UT1 | 2x10'AT | 3x12'UT2 |
| 5 | 65'UT2 | 2x24'UT1 | 4x5'AT | 3x16'UT1 | 3x8'AT | 3x18'UT1 | 2x12'AT | 3x16'UT1 |
| 6 | 76'UT2 | 2x25'UT1 | 3x7'AT | 3x19'UT1 | 3x10'AT | 5x12'UT1 | 3x8'AT | 3x18'UT1 |
| 7 | 45'UT2 | 2x15'UT1 | 2x8'AT | 3x12'UT1 | 2x10'AT | 3x15'UT1 | 2x9'AT | 2x3'TR |
| 8 | 65'UT2 | 3x14'UT1 | 2x9'AT | 75'UT2 | 2x8' AT | 4x14'UT1 | 2x7'AT | 3x4'TR |
| 9 | 76'UT2 | 3x17'UT1 | 3x7'AT | 90'UT2 | 4x5'TR | 4X15'UT1 | 3x8'AT | 4x4'TR |
| 10 | 45'UT2 | 2x15'UT1 | 2x8'AT | 60'UT2 | 4x2'TR | 3x12'UT1 | 2x9'AT | 3x3'TR |
| 11 | 65'UT2 | 3x15'UT1 | 2x10'AT | 75'UT2 | 4x3'TR | 3x15'UT1 | 2x10'AT | 4x3'TR |
| 12 | 75'UT2 | 4x15'UT1 | 3x8'AT | 90'UT2 | 4x4'TR | 4x12'UT1 | 3x10'AT | 5x4'TR |
| 13 | TEST | 2X15'UT1 | 2x8'AT | 60'UT2 | 3x1'AN | 3x15'UT1 | 2x8'AT | 4x2'TR |
| 14 | 65'UT2 | 3X15'UT1 | 2x10'AT | 75'UT2 | 4x1.5'AN | 4x12'UT1 | 3x7'AT | 6x2'TR |
| 15 | 75'UT2 | 5x12'UT1 | 3x10'AT | 90'UT2 | 6x1'AN | 5x12'UT1 | 3x10'AT | 6x4'TR |
| 16 | 45'UT2 | 2X15'UT1 | 2x9'AT | 60'UT2 | 8x45sAN | 4x14'UT1 | 2x10'AT | 5x2'TR |
| 17 | 65'UT2 | 3X15'UT1 | 3x10'AT | 75'UT2 | 6x1.5'AN | 3x12'UT1 | 3x8'AT | 6x3'TR |
| 18 | 75'UT2 | 4x15'UT1 | 4x8'AT | 90'UT2 | 8x1'AN | 2x15'UT1 | 4x9'AT | 7x4'TR |
| 19 | 45'UT2 | 2X15'UT1 | 2x10'AT | 60'UT2 | 4x1.5'AN | 3x12'UT1 | 3x8'AT | 6x2'TR |
| 20 | 65'UT2 | 3X15'UT1 | 3x12'AT | 75'UT2 | 6x1'AN | 3x15'UT1 | 3x10'AT | 7x3'TR |
| 21 | 75'UT2 | 5x12'UT1 | 5x8'AT | 90'UT2 | 8x45sAN | 5x12'UT1 | 4x10'AT | 8x4'TR |
| 22 | 45'UT2 | 2x15'UT1 | 2x10'AT | 60'UT2 | 8x1.5'AN | 3x12'UT1 | 2x7'AT | 4x2'TR |
| 23 | 65'UT2 | 3x15'UT1 | 3x8'AT | 75'UT2 | 10x45sAN | 3x15'UT1 | 3x7'AT | 4x3'TR |
| 24 | 76'UT2 | 4x15'UT1 | 4x8'AT | 90'UT2 | 2(6x1')AN | 4x15'UT1 | 2x10'AT | 4x4'TR |
| 25 | 50'UT2 | 2x12'UT1 | 6' AT | 40'UT2 | 2x1.5'AN | 20'UT2 | 2x2'TR | 3x45sAN |
| 26 | OFF | 1x15'UT1 | 5'AT | 1x3'TR | 20'UT2 | 2x2'TR | 3x45sAN | RACE |
cat level-5_8-session_26-weeks.csv
```csv
"Interactive 2,000m Programme",,,,,,,,
2000m 26 Week Training Programme,,,,,,,,
"Athlete Level 5, 8 Sessions a Week",,,,,,,,
Week,Session 1,Session 2,Session 3,Session 4,Session 5,Session 6,Session 7,Session 8
1,TEST,2x15'UT1,55'UT2,2x18'UT1,68'UT2,3x15'UT1,55'UT2,2x15'UT1
2,65'UT2,2x21'UT1,72'UT2,3x16'UT1,80'UT2,4x13'UT1,72'UT2,3x12'UT1
3,76'UT2,3x17'UT1,85'UT2,3x19'UT1,90'UT2,3x20'UT1,85'UT2,2x25'UT1
4,45'UT2,2x15'UT1,2x6'AT,3x12'UT1,2x7'AT,3x15'UT1,2x10'AT,3x12'UT2
5,65'UT2,2x24'UT1,4x5'AT,3x16'UT1,3x8'AT,3x18'UT1,2x12'AT,3x16'UT1
6,76'UT2,2x25'UT1,3x7'AT,3x19'UT1,3x10'AT,5x12'UT1,3x8'AT,3x18'UT1
7,45'UT2,2x15'UT1,2x8'AT,3x12'UT1,2x10'AT,3x15'UT1,2x9'AT,2x3'TR
8,65'UT2,3x14'UT1,2x9'AT,75'UT2,2x8' AT,4x14'UT1,2x7'AT,3x4'TR
9,76'UT2,3x17'UT1,3x7'AT,90'UT2,4x5'TR,4X15'UT1,3x8'AT,4x4'TR
10,45'UT2,2x15'UT1,2x8'AT,60'UT2,4x2'TR,3x12'UT1,2x9'AT,3x3'TR
11,65'UT2,3x15'UT1,2x10'AT,75'UT2,4x3'TR,3x15'UT1,2x10'AT,4x3'TR
12,75'UT2,4x15'UT1,3x8'AT,90'UT2,4x4'TR,4x12'UT1,3x10'AT,5x4'TR
13,TEST,2X15'UT1,2x8'AT,60'UT2,3x1'AN,3x15'UT1,2x8'AT,4x2'TR
14,65'UT2,3X15'UT1,2x10'AT,75'UT2,4x1.5'AN,4x12'UT1,3x7'AT,6x2'TR
15,75'UT2,5x12'UT1,3x10'AT,90'UT2,6x1'AN,5x12'UT1,3x10'AT,6x4'TR
16,45'UT2,2X15'UT1,2x9'AT,60'UT2,8x45sAN,4x14'UT1,2x10'AT,5x2'TR
17,65'UT2,3X15'UT1,3x10'AT,75'UT2,6x1.5'AN,3x12'UT1,3x8'AT,6x3'TR
18,75'UT2,4x15'UT1,4x8'AT,90'UT2,8x1'AN,2x15'UT1,4x9'AT,7x4'TR
19,45'UT2,2X15'UT1,2x10'AT,60'UT2,4x1.5'AN,3x12'UT1,3x8'AT,6x2'TR
20,65'UT2,3X15'UT1,3x12'AT,75'UT2,6x1'AN,3x15'UT1,3x10'AT,7x3'TR
21,75'UT2,5x12'UT1,5x8'AT,90'UT2,8x45sAN,5x12'UT1,4x10'AT,8X4'TR
22,45'UT2,2x15'UT1,2x10'AT,60'UT2,8x1.5'AN,3x12'UT1,2x7'AT,4x2'TR
23,65'UT2,3x15'UT1,3x8'AT,75'UT2,10x45sAN,3x15'UT1,3x7'AT,4x3'TR
24,76'UT2,4x15'UT1,4x8'AT,90'UT2,2(6x1')AN,4x15'UT1,2x10'AT,4x4'TR
25,50'UT2,2x12'UT1,6' AT,40'UT2,2x1.5'AN,2x15'UT1,4'TR,2x12'UT1
26,OFF,1x15'UT1,5'AT,1x3'TR,20'UT2,2x2'TR,3x45sAN,RACE
```
cat concept2_prediction.py
```python
def calculate_wattage(resting_heart_rate, maximum_heart_rate, heart_rate, base_power_output):
def get_zone_percentile(heart_rate, resting_heart_rate, maximum_heart_rate):
HRR = maximum_heart_rate - resting_heart_rate
zone = ((heart_rate - resting_heart_rate) / HRR) * 100
return round(zone, 2)
def get_hrr_range(zone):
if zone <= 65:
return (0, 65)
elif zone <= 70:
print("UT2 Zone")
return (65, 70)
elif zone <= 80:
print("UT1 Zone")
return (70, 80)
elif zone <= 85:
print("AT Zone")
return (80, 85)
elif zone <= 95:
print("TR Zone")
return (85, 95)
else:
print("AN Zone")
return (95, 100)
def get_power_range(zone):
if zone <= 65:
return (0, 45)
elif zone <= 70:
print("UT2 Zone")
return (45, 60)
elif zone <= 80:
print("UT1 Zone")
return (60, 70)
elif zone <= 85:
print("AT Zone")
return (70, 80)
elif zone <= 95:
print("TR Zone")
return (80, 105)
else:
print("AN Zone")
return (105, 115)
zone_percentage = get_zone_percentile(heart_rate, resting_heart_rate, maximum_heart_rate)
print("Zone: " + str(zone_percentage))
min_power, max_power = get_power_range(zone_percentage)
print("Min power: " + str(min_power))
print("Max power: " + str(max_power))
min_hrr, max_hrr = get_hrr_range(zone_percentage)
print("Min hrr: " + str(min_hrr))
print("Max hrr: " + str(max_hrr))
power_range = max_power - min_power
print("Power range: " + str(power_range))
hrr_range = max_hrr - min_hrr
print("HRR range: " + str(hrr_range))
print("Zone minus min hrr: " + str(zone_percentage - min_hrr))
# Calculate percentage of hrr range
hrr_percentage = ((zone_percentage - min_hrr) / hrr_range)
print("hrr %: " + str(hrr_percentage))
power_percentage = (min_power + hrr_percentage * power_range) / 100
print("Power percentage: " + str(power_percentage))
# Add base power output
# predicted_power = power_percentage + base_power_output
predicted_power = base_power_output / power_percentage
return round(predicted_power, 0)
# Example usage
resting_heart_rate = 58
maximum_heart_rate = 165
heart_rate = 132
base_power_output = 110
watts = calculate_wattage(resting_heart_rate, maximum_heart_rate, heart_rate, base_power_output)
print(f"Predicted power: {watts} watts")
```