Navigate back to the homepage

Mobility Metrics: Calculating Walking Speed

Arvind Ravi
March 7th, 2021 · 2 min read

Introduction

We live in a world of data. It is believed that over 2.5 quintillion bytes are generated every day - how big is that? I’m not sure, just a ridiculously large amount.

But what’s also quite interesting is that - our bodies are functioning biological systems that generate tons of data every day. Any functionining system needs to be monitored, taken care of to be able to use it effectively. Our health care systems do pretty much that. We’ve developer a wide variety of sensors that are able to read information from our body, these give us bio-markers or data that are of concern in the field of medicine to make certain interpretations.

We still have a wide variety of hardware components and software systems that can give us accurate information - but what we also do have is something close to it in our pockets - iOS now enables us to read a subset of mobility information from our bodies that could be use in a variety of ways.

Mobility Metrics in iOS

With iOS 14 — Apple has introduced Mobility Metrics which allow us to gather mobility information that prove quite useful such as walking speed, step-length, double support time, six-minute walk distance, etc.

We’ll quickly take a look at how to gather one of the metrics thats quite interesting to look at — Walking Speed.

Mobility Metrics is baked into HealthKit and can be accessed by simply constructing and executing a HKSampleQuery with a HKHealthStore.

Querying Walking Speed

There are three steps to gather this information from our device:

  1. Consent

    Any health related information that we get access to on a user’s device requires consent.

    This means that the first step in this process would be to request authorization from the user before getting access to their samples.

  2. Construct a HKSampleQuery

    A HKSampleQuery requires 3 pieces of information to be constructed:

    • A Sample Type (in our case this is walkingSpeed)
    • A Predicate (which indicates the period of type we’re requesting the sample from). Optional.
    • Sort Descriptor (inorder to get a sorted list of samples). Also, optional.
  3. Execute Query with a HKHealthStore

Now that we broadly understand how this is done, let’s take a look at this code to do this:

Setup

Setup a HealthKit store.

1private let store: HKHealthStore = HKHealthStore()

Request Authorisation

1private let typesToRead: Set = [
2 HKObjectType.quantityType(forIdentifier: .walkingSpeed)!
3]
4
5public func requestAuthorization() {
6 store.requestAuthorization(toShare: nil, read: typesToRead) { (success, error) in
7 if !success, let error = error {
8 print("Authorization Failed: \(error.localizedDescription)")
9 }
10 }
11}

Here, we’ve simply defined a Set of types that we’re interested in, just walkingSpeed in our case, and use it to call requestAuthorization on our health store.

This call triggers the native alert asking for permissions from the user. Also to note is to include the corresponding Info.plist that’s required to indicate to the user how their information is used.

Query for Walking Speed

Once we’ve got the authorisation from the user, we can proceed with building our query and executing it with the store —

1public func walkingSpeedSamples(_ completion: @escaping WalkingSpeedSamplesResult) {
2 // 1
3 let start = Calendar.current.date(byAdding: .day, value: -30, to: .init())
4 let end = Calendar.current.date(byAdding: .day, value: 60, to: .init())
5
6 // 2
7 let datePredicate = HKQuery.predicateForSamples(withStart: start, end: end, options: [])
8
9 // 3
10 let walkSpeedType = HKSampleType.quantityType(forIdentifier: .walkingSpeed)!
11 let sortByStartDate = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)
12
13 // 4
14 let query = HKSampleQuery(sampleType: walkSpeedType,
15 predicate: datePredicate,
16 limit: HKObjectQueryNoLimit,
17 sortDescriptors: [sortByStartDate]) { (_, samples, error) in
18 completion(.success(samples))
19 }
20
21
22 // 5
23 store.execute(query)
24}
  1. We start by defining the start and end dates for the period of samples we’re interested in.
  2. We use the defined ranges to build a predicate that indicates this range, with HealthKit we’re able to use HKQuery.prdicateForSamples() method to build an NSPredicate
  3. We then define our sample type which in our case could be buiild with the HKSampleType.quantityType(forIdentifier:) method that takes an enum of the metric we’re interested in.
  4. We can now build a HKSampleQuery, with all of the information we have, and additionally pass a closure which gets called when the query is executed.
  5. Execute the query using store.execute()

Inspecting the Samples

The samples we get back using this process look something like —

1[1.61 m/s 037C636A-23C2-4A55-B2C0-F3A6514291A0 "Arvind’s iPhone" (14.3),
2"iPhone13,3" (14.3) "iPhone" (2021-02-06 6:22:05 pm +0000 - 2021-02-06 6:22:31 pm +0000),
31.49 m/s CD229350-FC24-4BEA-89B3-1B4R229F1A5E "Arvind’s iPhone" (14.3),
4"iPhone13,3" (14.3) "iPhone" (2021-02-06 6:22:47 pm +0000 - 2021-02-06 6:23:07 pm +0000),
50.94 m/s 9EFA6631-A73C-4574-9EDB-5111B4F123FB4 "Arvind’s iPhone" (14.3),]

This set of samples that are returned are of type HKSample and are really good inputs for visualising them with charts, graphs etc. ResearchKit provides us with a number of these views that could be used for this purpose.

Hope this was useful - I’ve put this together into a Swift Package incase you’re interested — MobilityKit.

More articles from Swiftla

Thinking in SwiftUI

Learn how to think in SwiftUI.

October 14th, 2020 · 2 min read

Building an API Client with Combine

Learn how to build a simple API Client using a URLSession Publisher with Combine.

October 6th, 2020 · 2 min read
© 2020–2021 Swiftla
Link to $https://twitter.com/arvindravi_Link to $https://github.com/arvindraviLink to $https://www.linkedin.com/in/arvindravizxc/