/// <summary> /// When updates are time synchronous, interpret the two given messages to determine if the /// wheel is not rotating. /// /// I would think that you would probably want to count how many times this happens in a /// row and then once it passes some threshold interpert that as zero speed (?). /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <returns><c>True</c> if the speed appears to be zero.</returns> public static bool IsZeroVelocityTimeSynchronous(WheelTorqueDataPage message1, WheelTorqueDataPage message2) { // See ANT+ Device Profile - Bicycle Power, page 36 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return(message1.WheelTicks == message2.WheelTicks); }
/// <summary> /// Calculates distance travelled in m. /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <param name="circumference">The circumference of the bicycle wheel, in m.</param> /// <returns>The distance travelled in m.</returns> public static float CalculateDistance(WheelTorqueDataPage message1, WheelTorqueDataPage message2, float circumference) { // See ANT+ Device Profile - Bicycle Power, page 37 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return(circumference * AntUtilFunctions.rolloverDiff(message1.WheelTicks, message2.WheelTicks)); }
/// <summary> /// Calculates the average speed in m/s. /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <param name="circumference">The circumference of the bicycle wheel, in m.</param> /// <returns>The average linear speed of the bike in m/s.</returns> public static float CalculateAvgSpeed(WheelTorqueDataPage message1, WheelTorqueDataPage message2, float circumference) { // See ANT+ Device Profile - Bicycle Power, page 36 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return(circumference * AntUtilFunctions.rolloverDiff(message1.UpdateEventCount, message2.UpdateEventCount) / (AntUtilFunctions.rolloverDiff(message1.WheelPeriod, message2.WheelPeriod) / 2048f)); }
/// <summary> /// When updates are event synchronous, interpret the two given messages to determine if /// the wheel is not rotating. /// /// I would think that you would probably want to count how many times this happens in a /// row and then once it passes some threshold interpert that as zero speed (?). /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <returns><c>True</c> if the speed appears to be zero.</returns> public static bool IsZeroVelocityEventSynchronous(WheelTorqueDataPage message1, WheelTorqueDataPage message2) { // See ANT+ Device Profile - Bicycle Power, page 36 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return((message1.UpdateEventCount == message2.UpdateEventCount) && (message1.WheelPeriod == message2.WheelPeriod) && (message1.WheelTicks == message2.WheelTicks)); }
void WheelTorqueReceived(object sender, EventArgs e) { WheelTorqueDataPage wheelTorque = (WheelTorqueDataPage)sender; if (lastWheelTorque != null) { float speed = WheelTorqueDataPage.CalculateAvgSpeed(wheelTorque, lastWheelTorque, bikeData.BikeWheelDiameter * (float) Math.PI); if (WheelTorqueDataPage.IsZeroVelocityEventSynchronous(wheelTorque, lastWheelTorque)) { if (++zeroSpeedCount > zeroSpeedCountThreshold) { if (zeroSpeedCount == zeroSpeedCountThreshold + 1) //Debug.LogFormat("Zero speed detected (zeroSpeedCountThreshold was {0})", // zeroSpeedCountThreshold); speed = 0f; } } else { if (zeroSpeedCountThreshold > ZERO_SPEED_COUNT_IDLE_THRESHOLD) { zeroSpeedCounts.Reset(); zeroSpeedCounts.Add(ZERO_SPEED_COUNT_MIN_THRESHOLD); } else { zeroSpeedCounts.Add(AntUtilFunctions.IntegerClamp( ZERO_SPEED_COUNT_THRESHOLD_OFFSET + zeroSpeedCount, ZERO_SPEED_COUNT_MIN_THRESHOLD, ZERO_SPEED_COUNT_MAX_THRESHOLD)); } zeroSpeedCountThreshold = zeroSpeedCounts.Average(); //Debug.LogFormat("zeroSpeedCount reset at {0} (zeroSpeedCountThreshold updated to {1})", // zeroSpeedCount, zeroSpeedCountThreshold); zeroSpeedCount = 0; } if (!float.IsNaN(speed)) bikeData.AntSpeed = speed; } lastWheelTorque = wheelTorque; }
/// <summary> /// When updates are time synchronous, interpret the two given messages to determine if the /// wheel is not rotating. /// /// I would think that you would probably want to count how many times this happens in a /// row and then once it passes some threshold interpert that as zero speed (?). /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <returns><c>True</c> if the speed appears to be zero.</returns> public static bool IsZeroVelocityTimeSynchronous(WheelTorqueDataPage message1, WheelTorqueDataPage message2) { // See ANT+ Device Profile - Bicycle Power, page 36 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return (message1.WheelTicks == message2.WheelTicks); }
/// <summary> /// Calculates distance travelled in m. /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <param name="circumference">The circumference of the bicycle wheel, in m.</param> /// <returns>The distance travelled in m.</returns> public static float CalculateDistance(WheelTorqueDataPage message1, WheelTorqueDataPage message2, float circumference) { // See ANT+ Device Profile - Bicycle Power, page 37 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return circumference * AntUtilFunctions.rolloverDiff(message1.WheelTicks, message2.WheelTicks); }
/// <summary> /// Calculates the average speed in m/s. /// </summary> /// <param name="message1">The most recent WheelTorqueDataPage message recieved.</param> /// <param name="message2">The second most recent WheelTorqueDataPage message recieved. /// </param> /// <param name="circumference">The circumference of the bicycle wheel, in m.</param> /// <returns>The average linear speed of the bike in m/s.</returns> public static float CalculateAvgSpeed(WheelTorqueDataPage message1, WheelTorqueDataPage message2, float circumference) { // See ANT+ Device Profile - Bicycle Power, page 36 (ver. 4.2) // https://www.thisisant.com/resources/bicycle-power/ return circumference * AntUtilFunctions.rolloverDiff(message1.UpdateEventCount, message2.UpdateEventCount) / (AntUtilFunctions.rolloverDiff(message1.WheelPeriod, message2.WheelPeriod) / 2048f); }