In this document we explain the physics behind the OpenRowingMonitor, to allow for independent review and software maintenance. This document is to be read in conjuntion with the mathematical foundations of OpenRowingMonitor, as that describes the implementation choices for the specific (regression) algorithms used for specific functions. This work wouldn't have been possible without some solid physics, described by some people with real knowledge of the subject matter. Please note that any errors in our implementation probably is on us, not them. When appropriate, we link to these sources. When possible, we also link to the source code to allow further investigation and keep the link with the actual implementation.
Please note that this text is used as a rationale for design decissions of the physics used in OpenRowingMonitor. So it is of interest for people maintaining the code (as it explains why we do things the way we do) and for academics to verify or improve our solution. For these academics, we conclude with a section of open design issues as they might provide avenues of future research. If you are interested in just using OpenRowingMonitor as-is, this might not be the text you are looking for.
Before we analyze the physics of a rowing engine, we first need to define the basic concepts. First we identify the key physical systems at play, then we define the key phases in the rowing stroke.
A rowing machine effectively has two fundamental movements:
- a linear movement (the rowing person moving up and down the rail, or a boat moving forward) and
- a rotational movement where the energy that the rower inputs in the system is absorbed through a flywheel (either a solid one, or a liquid one) [1].
Physically these movements are related, as they are connected by a chain or belt, allowing the rowing person to move the flywheel. This is shown in the following figure:
A basic view of an indoor rower's energy systemsThe linear and rotational speeds are related: the stronger/faster you pull in the linear direction, the faster the flywheel will rotate. The rotation of the flywheel simulates the effect of a boat in the water: after the stroke, the boat will continue to glide only be dampened by the drag of the boat, so does the flywheel.
There are several types of rowers:
-
Water resistance, where rowing harder will increase the resistance
-
Air resistance: where rowing harder will increase the resistance
-
Magnetic resistance: where the resistance is constant
There are also hybrid rowers, which combine air resistance and magnetic resistance. The differences in physical behavior can be significant, for example a magnetic rower has a constant resistance while a air rower's resistance is dependent on the flywheel's speed. We suspect that on a water rower behaves slightly different from an air rower, as the rotated water mass changes shape when the rotational velocity changes. Currently for OpenRowingMonitor, we consider that the key principle is similar enough for all these rowers (some mass is made to spin and drag brings its speed down) to treat them all as an air rower as a first approximation. However, we are still investigating how to adapt for these specific machines.
What seperates rowing from many other sports is its discontinous nature: for example, in Cycling the force constantly shifts between left and right leg, but remains relatively constant throughout the rotation. In rowing, a stroke begins with a powerful Drive phase, which is followed by an unpowered Recovery. Visually, it can be depicted as follows:
stateDiagram-v2
direction LR
Drive --> Recovery
Recovery --> Drive
Basic phases of a rowing stroke
On an indoor rower, the rowing cycle will always start with a stroke, followed by a recovery. We define them as follows:
-
The Drive phase, where the rower pulls on the handle
-
The Recovery Phase, where the rower returns to his starting position
Combined, we define a Drive followed by a Recovery a Stroke. In the calculation of several metrics, the requirement is that it should include a Drive and a Recovery, but order isn't a strict requirement for some metrics [2]. We define such combination of a Drive and Recovery without perticular order a Cycle, which allows us to calculate these metrics twice per stroke.
As described in the architecture, the rowing engine is the core of OpenRowingMonitor and consists of three major parts:
-
engine/Flywheel.js, which determines rotational metrics, -
engine/Rower.js, which transforms rotational metrics in a rowing state and linear metrics, -
engine/RowingStatistics.js, which manages session state, session metrics and optimizes metrics for presentation.
Although the physics is well-understood and even well-described publicly (see [1],[2],[3] and [4]), applying these formulae in a practical solution for multiple rowers delivering reliable results is quite challenging. Especially small errors, noise, tends to produce visible effects on the recorded metrics. Therefore, in our design of the physics engine, we obey the following principles (see also the architecture document):
-
stay as close to the original data as possible (thus depend on direct measurements as much as possible) instead of heavily depend on derived data. This means that there are two absolute values we try to stay close to as much as possible: the time between an impulse and the Number of Impulses, where we consider Number of Impulses most reliable, and time between an impulse reliable but containing noise (the origin and meaning of these metrics, as well the effects of this approach are explained later);
-
use robust calculations wherever possible (i.e. not depend on a single measurements, extrapolations, derivation, etc.) to reduce effects of measurement errors. A typical issue is the role of CurrentDt, which is often used as a divisor with small numers as Δt, increasing the effect of measurement errors in most metrics. When we do need to calculate a derived function, we choose to use a robust linear regression method to reduce the impact of noise and than use the function to calculate the derived function;
-
Be as close to the results of the Concept2 when possible and realistic, as they are considered the golden standard in indoor rowing metrics.
Typically, actual measurements are done in the rotational part of the rower, on the flywheel. We explicitly assume that OpenRowingMonitor measures the flywheel movement (directly or indirectly). Some rowing machines are known to measure the movement of the driving axle and thus the velocity and direction of the handle, and not the driven flywheel. This type of measurement blocks access to the physical behaviour of the flywheel (especially acceleration and coast down behaviour), thus making most of the physics engine irrelevant. OpenRowingMonitor can handle some of these rowing machines by fixing specific parameters, but as this measurement approach excludes any meaningful measurement, we will exclude it in the further description.
In a typical rowing machine, there is a magnetic reed sensor or optical sensor that will measure time between either magnets or reflective stripes on the flywheel or impellor, which gives an Impulse each time a magnet or stripe passes. For example, when the flywheel rotates on a NordicTrack RX800, the passing of a magnet on the flywheel triggers a reed-switch, that delivers a pulse to our Raspberry Pi.
Depending on the number of impulse providers (i.e. the number of magnets or stripes), the number of impulses per rotation increases, increasing the resolution of the measurement. As described in the architecture, OpenRowingMonitor's GpioTimerService.js measures the time between two subsequent impulses and reports as a currentDt value. The constant stream of currentDt values is the basis for all our angular calculations, which are typically performed in the pushValue() function of engine/Flywheel.js.
OpenRowingMonitor needs to keep track of several metrics about the flywheel and its state, including:
-
The Angular Distance of the flywheel in Radians (denoted with θ): in essence the distance the flywheel has traveled (i.e. the number of Radians the flywheel has rotated) since the start of the session;
-
The Time since start of the flywheel in seconds (denoted with t): in essence the time the flywheel has been spinning since the start of the session;
-
The Angular Velocity of the flywheel in Radians * s-1 (denoted with ω): in essence the number of (partial) rotations of the flywheel per second;
-
The Angular Acceleration of the flywheel in Radians * s-2 (denoted with α): the acceleration/deceleration of the flywheel;
-
The flywheel inertia of the flywheel in kg * m2 (denoted with I): the resistance of the flywheel to acceleration/deceleration;
-
The estimated drag factor of the flywheel in N * m * s2 (denoted with k): the level of (air/water/magnet) drag encountered by the flywheel, as a result of a damper setting.
-
The Torque of the flywheel in kg * m2 * s-2 (denoted with τ): the momentum of force on the flywheel.
-
Detecting power on the flywheel: whether there is a force on the flywheel.
Being limited to the time between impulses, currentDt, as only measurement means we can't measure any of these metrics directly, and that we have to accept some deviations in these measurements as they are reported in discrete intervals.
Additionally, small mechanical deviations, vibrations in the chassis (due to tiny unbalance in the flywheel) and latency inside the software stack can lead to small deviations the measurement of currentDt. Dealing with these deviations is an dominant issue, especially because we have to deal with a wide range machines. Aside from implementing noise reduction, we also focus on using robust calculations: calculations that don't deliver radically different results when a small measurement error is introduced in the measurement of currentDt. We typically avoid things like direct deriviations based on single values, as directly deriving over small values of currentDt with small errors typically produce huge deviations in the resulting estimate. As an alternative, we use (robust) regression over multiple values, and use the deriviations of the resulting function instead. We do this at the cost of reducing the accuracy of the data, as this approach tends to dampen real occuring peaks in the stroke data. However, this inaccuracy with respect to the perfect theoretical model is needed to prevent estimates to become too unstable for practical use or which can only be used with heavy smoothing later on in the process (typically smoothing across strokes by engine/RowingStatistics.js).
This can easily be measured by summarising the time between an impulse. Noise has little to no impact to this metric as on average the noise cancels out.
As the impulse-givers are evenly spread over the flywheel, this can be robustly measured by counting the total number of impulses, Number of Impulses, and multiply it with the angular displacement between two impulses (i.e.
In theory, there are two threats here:
- Potentially missed impulses due to sticking sensors or too short intervals for the Raspberry Pi to detect them. So far, this hasn't happened.
- Ghost impulses, typically caused by bounce effects of the sensor where the same magnet is seen twice by the sensor. The best resolution is a better mechanical construction of magnets and sensors or adjust the debounce filter.
The traditional approach [1], [8], [13] suggeste a numerical approach to Angular Velocity ω:
This formula is dependent on Δt, which is suspect to noise, making this numerical approach to the calculation of ω volatile. From a more robust perspective, we approach ω as the the first derivative of the function between time since start and the angular position θ, where we use a robust regression algorithm to determine the function and thus the first derivative.
The traditional numerical approach [1], [8], [13] Angular Acceleration α would be:
Again, the presence of Δt would make this alculation of α volatile. From a more robust perspective, we approach α as the the second derivative of the function between time since start and the angular position θ, where we use a robust regression algorithm to determine the function and thus the second derivative.
Summarizing, both Angular Velocity ω and Angular Acceleration α are determined through the same regression algorithm based on the derivatives of the function between time since start and the angular position θ, where the first derivative of the function represents the Angular Velocity ω and the second derivative represents the Angular Acceleration α.
In the recovery phase, the only force exerted on the flywheel is the (air-/water-/magnetic-)resistance. Thus we can calculate the drag factor of the flywheel based on deceleration through the recovery phase [1]. This calculation is performed in the markRecoveryPhaseCompleted() function of engine/Flywheel.js. There are several approaches described in literature [1], which OpenRowingMonitor extends to deliver a reliable and practically applicable approach.
A first numerical approach is presented by through [1] in formula 7.2a:
Where the resulting k should be averaged across the rotations of the flywheel. The downside of this approach is that it introduces Δt in the divider of the drag calculation, making this calculation potentially volatile, especially in the presence of systematic errors in the flywheel construction (as is the case with Concept2 Model D and later). Our practical experience based on testing confirms this volatility. An alternative numerical approach is presented by through [1] in formula 7.2b:
Where this is calculated across the entire recovery phase. Again, the presence of Δt in the divider potentially introduces a type of undesired volatility. Testing has shown that even when Δt is chosen to span the entire recovery phase, reducing the effect of single values of CurrentDt, the calculated drag factor is more stable but still is too unstable to be used as both the ω's used in this calculation still depend on single values of CurrentDt. Additionally, small errors in detection of the drive or recovery phase would change ω dramatically, throwing off the drag calculation significantly (see also this elaboration). Therefore, such an approach typically requires averaging across strokes to prevent drag poisoning (i.e. a single bad measurement of currentDt throwing off the drag factor significantly, and thus throwing off all dependent linear metrics significantly), which still lacks robustness of results as drag tends to fluctuate throughout a session.
We can transform formula 7.2b to the definition of the slope of a line, by doing the following:
Thus k/I represents the slope of the graph depicted by time since start on the x-axis and
However, formula 7.2b can be simplified further, as the angular velocity ω is defined by:
this can be rewritten as:
As the left-hand of the equation only contains constants and the dragfactor, and the right-hand a division of two delta's, we can use regression analyses to calculate the drag based on the raw measured currentDt. As the slope of the line currentDt over time since start is equal to
As this formula shows, the drag factor is effectively determined by the slope of the line created by time since start on the x-axis and the corresponding CurrentDt on the y-axis, for each recovery phase. This approach also brings this calculation as close as possible to the raw currentDt data, while not using an individual currentDt's as a divider, which are explicit design goals to reduce data volatility.
Both slopes can be determined through linear regression (see [5] and [6]) for the collection of datapoints for a specific recovery phase. For determining the slope, we use the linear Theil-Sen Estimator, which is sufficiently robust against noise, especially when filtering on low R2. The approach of using r2 has the benefit of completely relying on metrics contained in the algorithm itself for quality control: the algorithm itself signals a bad fit due to too much noise in the calculation. Additionally, as the drag does not change much from stroke to stroke, a running weighed average across several strokes is used, where the R2 is used as its weight. This has the benefit of favouring better fitting curves over less optimal fitting curves (despite all being above the R2 threshold set). Practical experiments show that this approach outperforms any other noise dampening filter.
Although both regression approaches are mathematically valid, they do yield different results: the first approach depends on (noise filtered) angular velocity ω as its input where the second approach depends on raw currentDt values. Comparing the results for both approaches:
- For approach 1, on a Concept2, the typical R2 is around @@ (low drag) to @@ (high drag) for steady state rowing. Also, calculated drag has a standard deviation of @@ (low drag) to @@ (high drag) across a session.
- For approach 2, On a Concept2, the typical R2 is around 0.96 (low drag) to 0.99 (high drag) for steady state rowing. Also, calculated drag has a standard deviation of @@ (low drag) to @@ (high drag) across an entire session.
Therefore, we choose @@
The torque τ on the flywheel can be determined based on formula 8.1 [1]:
As
As α and ω have been derived in a robust manner, and there are no alternative more robust approaches to determining instant τ that allows for handle force curves, we consider this the best attainable result. Testing shows that the results are quite useable.
One of the key elements of rowing is detecting the stroke phases and thus calculate the associated metrics for that phase. Assuming that engine/Flywheel.js has determined whether there is a force present on the flywheel, engine/Rower.js can now transform this information into the phase of the rowing stroke. On an indoor rower, the rowing cycle will always start with a drive, followed by a recovery. This results in the follwing phases:
-
The Drive phase, where the rower pulls on the handle, some force on the flywheel is excerted and the flywheel is accelerating or at least not decelerating in accordance with the drag;
-
The Recovery Phase, where the rower returns to his starting position and the flywheel decelerates as the drag on the flywheel is slowing it down;
As the rowing cycle always follows this fixed schema, OpenRowingMonitor models it as a finite state machine (implemented in handleRotationImpulse in engine/Rower.js).
stateDiagram-v2
direction LR
Drive --> Recovery: Flywheel<br>isn't powered
Drive --> Drive: Flywheel<br>is powered
Recovery --> Drive: Flywheel<br>is powered
Recovery --> Recovery: Flywheel<br>isn't powered
Finite state machine of rowing cycle
From the perspective of OpenRowingMonitor, there only is a stream of CurrentDt's, which should form the basis of this detection:
The following picture shows the time between impulses through time:
example currentDt Measurements of a flywheel
OpenRowingMonitor combines two types of force detection, which work independently: basic force detection and advanced stroke detection. Both can detect a stroke accuratly, and the combination has proven its use.
In engine/Flywheel.js, two functions provide force detection, which use the following criteria before attempting a stroke phase transition:
-
isPowered(): which indicates a force is present, suggesting a drive phase. This is true when the slope of a series of flankLength times between impulses is below the minumumRecoverySlope (i.e. accelerating, as is the case in the measurements in above figure before the dotted line) AND the handleforce is above minumumForceBeforeStroke (i.e. the torque τ is above a certain threshold); -
isUnpowered(): which indicates that there is no force present, suggesting a recovery phase. This is true when the slope of a series of flankLength times between impulses is above the minumumRecoverySlope (i.e. decelerating, as is the case in the measurements in above figure after the dotted line) where the goodness of fit of that slope exceeds the minimumStrokeQuality OR the handleforce is below minumumForceBeforeStroke (i.e. the torque τ is below a certain threshold)
The choice for the logical relations between the two types of force detection is based on testing: where a sudden presence of force on a flywheel (i.e. the start of a drive) is quite easily and consistently detected, its abscence has proven to be more difficult. In practice, the beginning of a drive is easily recognised as strong leg muscles excert much force onto the flywheel in a very short period of time, leading to an easily recognisable (large) torque τ and a sudden decrease in currentDt's. The end of the drive is more difficult to assess, as the dragforce of the flywheel increases with its speed, and the weaker arm muscles have taken over, making the transition to the recovery much harder to detect. In theory, in the end of the drive phase the drag force might be bigger than the force from the arms, resulting in an overall negative torque.
In the remainder of this paragraph, we describe the underlying physics of both these force detection methods.
One of the key indicator is the acceleration/decelleration of the flywheel. Looking at a simple visualisation of the rowing stroke, we try to achieve the following:
Impulses, impulse lengths and rowing cycle phasesHere we plot the currentDt against its sequence number. So, a high currentDt means a long time between impulses (so a low angular velocity), and a low currentDt means that there is a short time between impulses (so a high angular velocity).
Here, it is clear that the flywheel first accelerates (i.e. the time between impulses become smaller), suggesting a powered flywheel. Next it decelerates (i.e. the time between impulses become bigger), which suggests an unpowered flywheel. This pattern is typical for the rowing motion.
The simple force detection uses this approach by looking at the slope of currentDt over time. Given that the Angular Displacement between impulses is fixed, we can deduct some things simply from looking at the subsequent time between impulses, currentDt. When the currentDt shortens, Angular Velocity is increasing, and thus the flywheel is accelerating (i.e. we are in the drive phase of the rowing cycle). When times between subsequent impulses become longer, the Angular Velocity is decreasing and thus the flywheel is decelerating (i.e. we are the recovery phase of the rowing cycle). As a rough but very robust approximation, a descending (negative) slope indicates a powered flywheel, an (positive) ascending slope indicates an unpowered flywheel. This approach seems to be similar to the implementation used by industry leaders like Concept2. Concept2 are generally considered the golden standard when it comes to metrics, and they state (see this Concept2 FAQ:
Drive time is measured by the amount of time the flywheel is accelerating. Note: It is possible that the athlete may pull on the handle and not accelerate the flywheel due to no energy being put into it and therefore no effective effort. This portion of the handle pull is not measured.
A more nuanced, but more vulnerable, approach is to compare the slope of this function with the typical slope encountered during the recovery phase of the stroke (which routinely is determined during the drag calculation). When the flywheel is unpowered, the slope will be close to the recovery slope, and otherwise it is powered. This is a more accurate, but more vulnerable, approach, as small deviations could lead to missed strokes. It is noted that practical testing has shown that this works reliably for many machines.
In OpenRowingMonitor, the settings allow for using the more robust ascending/descending approach (by setting minumumRecoverySlope to 0), for a more accurate approach (by setting minumumRecoverySlope to a static value) or even a dynamic approach (by setting autoAdjustRecoverySlope to true)
The more advanced, but more vulnerable approach depends on the calculated torque. When looking at CurrentDt and Torque over time, we get the following picture:
Average currentDt (red) and Acceleration (blue) of a single stroke on a rowing machineIn this graph, we plot currentDt and Torque against the time in the stroke. As soon as the Torque of the flywheel becomes below the 0, the currentDt begins to lengthen again (i.e. the flywheel is decelerating). As indicated earlier, this is the trigger for the basic force detection algorithm (i.e. when minumumRecoverySlope is set to 0): when the currentDt starts to lengthen, the drive-phase is considered complete.
However, from the acceleration/deceleration curve it is also clear that despite the deceleration, there is still a force present: the Torque-curve hasn't reached its stable minimum despite crossing 0. This is due to the pull still continuing through the arms: the net force is negative due to a part drive-phase (the arm-movement) delivering weaker forces than the drag-forces of the flywheel. Despite being weaker than the other forces on the flywheel, the rower is still working. In this specific example, at around 0.52 sec the rower's force was weaker than all drag-forces combined. However, only at 0,67 seconds (thus approx. 150 ms later) the net force reaches its stable bottom: the only force present is the drag from the flywheel. Getting closer to this moment is a goal.
We do this by setting a minimum Torque (through setting minumumForceBeforeStroke) before a Drive phase can be initiated.
OpenRowingMonitor only will get impulses at discrete points in time. As OpenRowingMonitor doesn't measure torque on the flywheel directly, it can't determine where the flywheel exactly accelerates/decelerates as there is no continous measurement. OpenRowingMonitor can only detect a change in the times across several impulses, but it can't detect the exact time of torque change. In essence, at best we only can conclude that the torque has changes somewhere near a specific impulse, but we can't be certain about where the acceleration exactly has taken place and we can only estimate how big the force must have been.
Knowing that Time since start, Angular Velocity ω, Angular Acceleration α, flywheel Torque τ and dragfactor k have been determined in a robust manner by engine/Flywheel.js, engine/Rower.js can now transform these key rotational metrics in linear metrics. This is done in the handleRotationImpulse() function of engine/Rower.js, where based on the flywheel state, the relevant metrics are calculated. The following metrics need to be determined:
-
The estimated flywheel power produced by the rower (in Watts, denoted with P): the power the rower produced during the stroke;
-
The estimated Linear Velocity of the boat (in Meters/Second, denoted with u): the speed at which the boat is expected to travel;
-
The estimated Linear Distance of the boat (in Meters, denoted with s): the distance the boat is expected to travel;
-
The estimated Drive length (in meters): the estimated distance travelled by the handle during the drive phase;
-
The estimated speed of the handle (in m/s): the speed the handle/chain/belt of the rower;
-
The estimated force on the handle (in Newtons): the force excerted on the handle/chain/belt of the rower;
-
The estimated power on the handle (in Watts): the power on the handle/chain/belt of the rower;
As the only source for adding energy to the rotational part of the rower is the linear part of the rower, the power calculation is the key calculation to translate between rotational and linear metrics.
We can calculate the energy added to the flywheel through [1], formula 8.2:
The power then becomes [1], formula 8.3:
Combining these formulae, makes
This is an easy technical implementable algorithm by calculating a running sum of this function (see [3], and more specifically [4]). However, the presence of the many small ω's makes the outcome of this calculation potentially quite volatile, even despite the robust underlying calculation for ω. Calculating this across the stroke might be an option, but the presence of Δω would make the power calculation highly dependent on both accurate stroke detection and the accurate determination of instantanous ω.
An alternative approach is given in [1], [2] and [3], which describe that power on a Concept 2 is determined through ([1] formula 9.1), which proposes:
Where
Dave Venrooy indicates that this formula is accurate with a 5% margin [3]. Testing this on live data confirms this behavior. Academic research on the accuracy of the Concept 2 RowErg PM5's power measurements [15] shows that:
-
It seems that Concept 2 is also using this simplified formula, or something quite similar, in the PM5;
-
For stable steady state rowing, the results of this approach are quite reliable;
-
For unstable rowing, the power calcuation is not reliable. The article seems to suggest that this is caused by ommitting the element of
${I * ({Δω \over Δt}) * ω}$ , essentially assuming that Δω is near zero across strokes. This is problematic at moments of deliberate acceleration across strokes (like starts and sprints), where Δω can be very significant, and at unstable rowing, where there also can be a sigificant Δω present across strokes.
Still, we currently choose to use
-
Despite its flaws, Concept 2's PM5 is widely regarded as the golden standard in rowing. For us, we rather stay close to this golden standard than make a change without the guarantee of delivering more accurate and robust results than Concept 2's PM5;
-
The simpler algorithm removes any dependence on instantaneous angular velocities ω at the flanks of the stroke from the power calculation and subsequent linear calculations. This makes the power calculation (and thus any subsequent calculations that are based on it) more robust against "unexpected" behavior of the rowing machine. There are several underlying causes for the need to remove this dependence:
- First of all, measurement errors in CurrentDt could introduce variations in Δω across the cycle and thus in all dependent linear metrics;
- Secondly, water rowers are known to experience cavitation effects at the end of the Drive Phase when used with sub-optimal technique, leading to extremely volatile results;
- Last, the determination of Δω across a stroke heavily depends on a very repeatable stroke detection that minimizes Δω to 0 during a stable series of stroke in steady state rowing. Such a repeatable stroke detection across the many types of rowing machines in itself is difficult to achieve;
-
As the flywheelinertia I is mostly guessed based on its effects on the Power outcome anyway (as most users aren't willing to take their rower apart for callibration purposses), a systematic error wouldn't matter much in most practical applications as it is corrected during the callibration of a monitor: the flywheelinertia will simply be modified to get to the correct power in the display.
-
It allows the user to removing/disabling all instantaneous angular velocities from linear metric calculations (i.e. only using average angular velocity calculated over the entire phase, which doesn't depend on a single measurement) by setting autoAdjustDragFactor to "false". This makes OpenRowingMonitor a viable option for rowers with noisy data or otherwise unstable/unreliable individual measurements;
-
Given the stability of the measurements, it might be a realistic option for users to remove the filter in the presentation layer completely by setting numOfPhasesForAveragingScreenData to 2, making the monitor much more responsive to user actions.
Given these advantages and that in practice it won't have a practical implications for users, we have chosen to use the robust implementation. It should be noted that this definition is also robust against missed strokes: a missed drive or recovery phase will lump two strokes together, but as the Average Angular Velocity
In [1] and [2], it is described that flywheel power on a Concept 2 is determined through (formula 9.1):
Where c is a constant (2.8 according to [1]),
In [1] and [2], it is suggested that flywheel power on a Concept 2 might be determined through (formula 9.4, [1]):
Based on a simple experiment, downloading the exported data of several rowing sessions from Concept 2's logbook, and comparing the reported velocity and flywheel power for each stroke, it can be determined that
As both k and
[1]'s formula 9.3 provides a formula for linear distance:
Here, as k can slightly change from cycle to cycle, this calculation should be performed at least once per cycle. As θ isn't dependent on stroke state and changes constantly, it could be recalculated continously throughout the stroke, providing the user with direct feedback of his stroke. It should be noted that this formula is also robust against missed strokes: a missed drive or recovery phase will lump two strokes together, but as the angular displacement θ is stroke independent, it will not be affected by it at all. Although missing strokes is undesired behaviour, this approach isolates linear distance calculations from errors in the stroke detection in practice.
Given the distance travelled by the handle can be calculated from angular distance θ traveled by the sprocket during the Drive Phase. During the drive, the angular distance travelled by the flywheel is identical to the angular distance θ travelled by the flywheel during the drive phase. Thus
As the number of rotations of the flywheel =
Which can be simplified into:
Where r is the radius of the sprocket in meters and θ the angular distance travelled by the flywheel during the drive.
As the distance travelled by the handle is
Here, ω can be the instantanous or average angular velocity of the flyhweel in Radians, and r is the radius of the sprocket (in meters).
From theory [12]) and practical application [7], we know the handle force is equal to:
Where r is the radius of the sprocket in meters.
From theory [13]), we know that the handle Power is
The power calculation is the bridge connecting the linear and rotational energy systems of an ergometer. However, from a robustness perspective, we optimised this formula. The complete formula for power throughout a stroke can be deduced from formulae 8.2 and 8.3 [1], which lead to:
A simplified formula is provided by [1] (formula 9.1), [2] and [3]:
OpenRowingMonitor uses the latter simplified version. As shown by academic research [15], this is sufficiently reliable and accurate providing that that ω doesn't vary much across subsequent strokes. When there is a significant acceleration or decelleration of the flywheel across subsequent strokes (at the start, during acceleration in sprints or due to stroke-by-stroke variation), the reported/calculated power starts to deviate from the externally applied power.
Currently, this is an accepted issue, as the simplified formula has the huge benefit of being much more robust against errors in both the CurrentDt/ω measurement and the stroke detection algorithm. As Concept 2 seems to have taken shortcut in a thoroughly matured product [15], we are not inclined to change this quickly. Especially as the robustness of both the ω calculation and stroke phase detection varies across types of rowing machines, it is an improvement that should be handled with extreme caution.
[1] Anu Dudhia, "The Physics of ErgoMeters" http://eodg.atm.ox.ac.uk/user/dudhia/rowing/physics/ergometer.html
[2] Marinus van Holst, "Behind the Ergometer Display"
[3] Dave Vernooy, "Open Source Ergometer ErgWare" https://dvernooy.github.io/projects/ergware/
[4] Dave Vernooy, ErgWare source code https://github.com/dvernooy/ErgWare/blob/master/v0.5/main/main.ino
[5] Wikipedia, "Simple Linear Regression" https://en.wikipedia.org/wiki/Simple_linear_regression
[6] University of Colorado, "Simple Linear Regression" https://www.colorado.edu/amath/sites/default/files/attached-files/ch12_0.pdf
[7] Nomath, "Fan blade Physics and a Peek inside C2's Black Box" https://www.c2forum.com/viewtopic.php?f=7&t=194719
[8] Glenn Elert, The Physics Hypertextbook, "Rotational Kinematics" https://physics.info/rotational-kinematics/
[9] Wikipedia, "Linear regression" https://en.wikipedia.org/wiki/Linear_regression
[10] Wikipedia, "Robust regression" https://en.wikipedia.org/wiki/Robust_regression
[11] Incomplete Theil-Sen Regression https://www.fon.hum.uva.nl/praat/manual/theil_regression.html
[12] Glenn Elert, The Physics Hypertextbook, "Rotational Dynamics" https://physics.info/rotational-dynamics/
[13] Glenn Elert, The Physics Hypertextbook, "Rotational Energy" https://physics.info/rotational-energy/
[14] Dave Vernooy, ErgWare source code V0.6 https://github.com/dvernooy/ErgWare/blob/master/v0.6/Standard_version/source/main.c
[15] Gunnar Treff, Lennart Mentz, Benjamin Mayer and Kay Winkert, "Initial Evaluation of the Concept-2 Rowing Ergometer's Accuracy Using a Motorized Test Rig" https://www.researchgate.net/publication/358107352_Initial_Evaluation_of_the_Concept-2_Rowing_Ergometer%27s_Accuracy_Using_a_Motorized_Test_Rig


