CMAltimeter reports wrong relativeAltitude values while an active HKWorkoutSession is paused on watchOS

Our app allows you to record trails on Apple Watch. It uses CMAltimeter to get the elevation for the recorded trail and HKWorkoutSession to record the user's workout.

Some of our users started reporting huge punctual elevation spikes when pausing the app in Apple Watch. After a thorough investigation, it turns out the altimeter reports wrong data while the workout session is paused.

CMAltimeter starts reporting offsetted relativeAltitude values while the HKWorkoutSession is paused. This offset, in our experience, ranges from 1.5 meters to +1000 meters. When the HKWorkoutSession is resumed, after a couple of seconds, the reported relativeAltitude value goes back to a similar range to the values before pausing. Strangely, the pressure value seems to be unaffected by this problem.

I've been able to reproduce this on my Series 5 Apple Watch with watchOS 6.2.8. Is this a known issue?

I've already submitted a bug report: FB7972487

I added elevation gain tracking to my fitness app earlier this year in my Hiking update. I haven't seen anything like this in development or heard any reporting from the field. I have a Series 3 with 6.2.8 and have never noticed anything like this.

As far as I know, CMAltimeter solely uses a barometric pressure sensor under the hood, well at least until the new watches that use GPS and Wi-Fi for improved data in that always-on scenario. Barometric pressure sensors have a sampling time where they 'accumulate' change, so we are limited by the update frequency of both the hardware and software.

I'll probably put something like this in my code to account for this; so I appreciate your share! I'd start by keeping track of my last known presumed good/first CMAltitudeData, then put the following (pseudo-code) guards into my update handler:
  1. guard newData.timestamp > lastData.timestamp else { BAD }

  2. guard abs(newData.relativeAltitude - lastData.relativeAltitude) < Constants.reasonableAltitudeDelta else { BAD }

Unless your app supports cliff jumping or some other crazy activity, assuming the update frequency of the altimeter API is 1hz, maybe it would be appropriate for the user to change say 2 m/s? So in guard 2, compare your elevation change over time to some velocity number. Furthermore, you'd need to understand and handle the cases where your lastData is actually the bad one, or enough time has passed where you just wanna give up start accumulating +/- elevation again.

I applied similar filtering (plus more) to my CLLocation data before adding to my workout route.

Questions:
  1. By chance, do you have any CLLocation data during the 'paused' portion of your workout to correlate it against?

  2. Could you share an example print out of your [CMAltitudeData] as well as markers where you paused your workout?

  3. Roughly how many seconds after you paused the workout session did you see the elevation return to 'normal' values?

  4. Any difference when you are doing a running workout with your watch set to auto-pause, vs you programmatically calling session.pause()?

As I mentioned, I have a Series 3, and a new Series 6 on the way. I will do some testing to see if I can reproduce what you're seeing and reply with my results.
I observed the same problem: when a workout session is switched to pause() or end(), the relativeAltitude starts to report erroneous level at ~5825 feet or 1775 meters. Appreciate an investigation or recommendation.

2 years later, watchOS 9.4 and this bug is still not fixed. How typical Apple...

If somebody experince this issue you can use raw CMAltitudeData.pressure which is not suffering from this bug and get altitude using this function:

    func getAltitude(pressureKpa: Double) -> Double {
        let const = 1013.25 &#x2F;* Standard atmosphere, or average sea-level pressure in hPa *&#x2F;
        let coef = 1.0 &#x2F; 5.255
        return 44330.0 * (1.0 - pow((pressureKpa * 10) &#x2F; const, coef))
    }

As constant is used, returned absolute altitude is not precise but can be used for relative measuring instead of buggy CMAltitudeData.relativeAltitude

CMAltimeter reports wrong relativeAltitude values while an active HKWorkoutSession is paused on watchOS
 
 
Q