LocomotionManager

@objc public class LocomotionManager: NSObject

The central class for interacting with LocoKit location and motion recording. All actions should be performed on the LocomotionManager.highlander singleton.

Overview

LocomotionManager monitors raw device location and motion data and applies filtering and smoothing algorithms to produce a stream of high level LocomotionSample objects, a composite representation of the device and user’s location and activity state at each point in time.

Locomotion samples include filtered and smoothed locations, the user’s moving or stationary state, current activity type (eg walking, running, cycling, etc), step hertz (ie walking, running, or cycling cadence), and more.

Energy Efficiency

LocomotionManager dynamically adjusts various device monitoring parameters, balancing current conditions and desired results to achieve the desired accuracy in the most energy efficient manner.

Starting and Stopping Recording

To start recording location and motion data call startRecording(), and call stopRecording() to stop.

Update Notifications

LocomotionManager will send locomotionSampleUpdated notifications via the system default NotificationCenter when each new location arrives.

Raw, Filtered, and Smoothed Data

LocoKit provides three levels of location data: Raw CLLocations, filtered CLLocations, and high level location and activity state LocomotionSamples. See the documentation for rawLocation, filteredLocation, and LocomotionSample for details on each.

Moving State

When each raw location arrives LocomotionManager updates its determination of whether the user is moving or stationary, based on changes between current and previous locations over time. The most up to date determination is available either from the movingState property on the LocomotionManager, or on the latest locomotionSample. See the movingState documentation for further details.

  • The LocomotionManager singleton instance, through which all actions should be performed.

    Declaration

    Swift

    @objc public static let highlander = LocomotionManager()
  • The maximum desired location accuracy in metres. Set this value to your highest required accuracy.

    For most uses the default value will achieve best results. Lower values will encourage the device to more quickly attain peak possible accuracy, at the expense of battery life. Higher values will extend battery life, at the cost of slower attainment of peak accuracy, or in some cases settling on accuracy levels below the best attainable by the hardware and sensors.

    Note

    If dynamicallyAdjustDesiredAccuracy is true, LocomotionManager will periodically adjust the internal CLLocationManager’s desiredAccuracy to best match the current best possible accuracy based on local conditions, to avoid wasteful energy use and improve battery life.

    Warning

    Setting a value above 100 metres will greatly reduce the movingState accuracy, and is thus not recommended.

    GPS, Wifi, And Cell Tower Triangulation Thresholds

    • iOS will usually attempt to exceed the requested accuracy, and may exceed it by a wide margin. For example if clear GPS line of sight is available, peak accuracy of 5 metres will be achieved even when only requesting 50 metres or even 100 metres. However the higher the desired accuracy, the less effort iOS will put into achieving peak possible accuracy.

    • Under some conditions, setting a value of 65 metres or above may allow the device to use wifi triangulation alone, without engaging GPS, thus reducing energy consumption. Wifi triangulation is typically more energy efficient than GPS.

    Declaration

    Swift

    @objc public var maximumDesiredLocationAccuracy: CLLocationAccuracy = 30
  • Whether LocomotionManager should dynamically adjust the internal CLLocationManager’s desiredAccuracy to best match local conditions. It is recommended to leave this enabled, to avoid wasteful GPS energy use inside buildings.

    If set to true, periodic adjustments are made within the range of maximumDesiredLocationAccuracy and kCLLocationAccuracyHundredMeters. Various heuristics are used to determine the current best possible accuracy, to avoid requesting a value beyond what can be currently achieved, thus avoiding wasteful energy consumption.

    If set to false, desiredAccuracy will be set to maximumDesiredLocationAccuracy and not modified.

    Declaration

    Swift

    @objc public var dynamicallyAdjustDesiredAccuracy: Bool = true
  • Assign a delegate to this property if you would like to have the internal location manager’s CLLocationManagerDelegate events forwarded to you after they have been processed internally.

    Declaration

    Swift

    @objc public var locationManagerDelegate: CLLocationManagerDelegate?
  • Whether or not to record pedometer events. If this option is enabled, LocomotionSample.stepHz will be set with the results.

    Note

    If you are making use of ActivityTypeClassifier it is recommended to leave this option enabled, in order to increase classifier results accuracy. This is particularly important for the accurate detection of walking, running, and cycling.

    Declaration

    Swift

    @objc public var recordPedometerEvents: Bool = true
  • Whether or not to record accelerometer events. If this option is enabled, LocomotionSample.xyAcceleration and LocomotionSample.zAcceleration will be set with the results.

    Note

    If you are making use of ActivityTypeClassifier, enabling this option will increase classifier results accuracy.

    Declaration

    Swift

    @objc public var recordAccelerometerEvents: Bool = true
  • Whether or not to record Core Motion activity type events. If this option is enabled, LocomotionSample.coreMotionActivityType will be set with the results.

    Note

    If you are making use of ActivityTypeClassifier, enabling this option will increase classifier results accuracy.

    Declaration

    Swift

    @objc public var recordCoreMotionActivityTypeEvents: Bool = true
  • Whether LocomotionManager should enter a low power sleep mode while stationary, in order to reduce energy consumption and extend battery life during long recording sessions.

    Declaration

    Swift

    @objc public var useLowPowerSleepModeWhileStationary: Bool = true
  • Whether or not LocomotionManager should wake from sleep mode and resume recording when no location data is available.

    Under some conditions, a device might stop returning any recent or new CLLocations, for extended periods of time. This may be due to a lack of available triangulation sources, for example the user is inside a building (thus GPS is unavailable) and the building has no wifi (thus wifi triangulation is unavailable). The device may also decide to delay location updates for energy saving reasons.

    Whilst in sleep mode, it is typically best to ignore this lack of location data, and instead remain in sleep mode, in order to avoid unnecessary energy consumption.

    However there are cases where it may not be safe to assume that a lack of location data implies that the user is still stationary. The most common exception case being underground train trips. In these edge cases you may want to instead treat the lack of location data as significant, and resume recording.

    Warning

    This setting should be left unchanged unless you have confident reason to do otherwise. Changing this setting to true may unnecessarily increase energy consumption.

    Declaration

    Swift

    @objc public var ignoreNoLocationDataDuringWakeups: Bool = true
  • How long the LocomotionManager should wait before entering sleep mode, once the user is stationary.

    Setting a shorter duration will reduce energy consumption and improve battery life, but also increase the risk of undesirable gaps in the recording data. For example a car travelling in heavy traffic may perform many brief stops, lasting less than a few minutes. If the LocomotionManager enters sleep mode during one of these stops, it will not notice the user has resumed moving until the next wakeup cycle (see sleepCycleDuration).

    Declaration

    Swift

    @objc public var sleepAfterStationaryDuration: TimeInterval = 180
  • The duration to wait before performing brief wakeup checks whilst in sleep mode.

    Wakeups allow the LocomotionManager to periodically check whether the user is still stationary, or whether they have resumed moving. If the user has resumed moving, LocomotionManager will exit sleep mode and resume recording.

    Note

    During each wakeup, LocomotionManager will briefly make use of GPS level location accuracy, which has an unavoidable energy cost. Setting a longer sleep cycle duration will reduce the number and frequency of wakeups, thus reducing energy consumption and improving battery life.

    Declaration

    Swift

    @objc public var sleepCycleDuration: TimeInterval = 60
  • The most recently received unmodified CLLocation.

    Declaration

    Swift

    public var rawLocation: CLLocation?
  • The most recent Kalman filtered CLLocation, based on the most recently received rawLocation.

    If you require strictly real time locations, these filtered locations offer a reasonable intermediate state between the raw data and the fully smoothed LocomotionSamples, with coordinates as near as possible to now.

    Note

    Both the location coordinate and location altitude are Kalman filtered, however all other CLLocation properties (course, speed, etc) are identical to the values in rawLocation. For fully smoothed and denoised motion properties you should use locomotionSample instead.

    Declaration

    Swift

    public var filteredLocation: CLLocation?
  • Returns a new LocomotionSample representing the most recent filtered and smoothed locomotion state, with combined location, motion, and activity properties.

    Note

    This method will create a new sample instance on each call. As such, you should retain and reuse the resulting sample until a new sample is needed.

    Declaration

    Swift

    public func locomotionSample() -> LocomotionSample
  • The MovingState of the current LocomotionSample.

    Note

    This value is as near to real time as possible, but typically represents the user’s state between 6 and 60 seconds in the past, with the age depending on the quality of available location data over that period of time. The higher the accuracy of current location data, the closer to now the reported moving state will be. If you need to know an exact timestamp to match the moving state, you should instead take a LocomotionSample instance from locomotionSample and use movingState and date on that sample.

    Declaration

    Swift

    public var movingState: MovingState
  • Start monitoring device location and motion.

    NSNotification.Name.didUpdateLocations notifications will be sent through the system NotificationCenter as each location arrives.

    Amongst other internal tasks, this will call startUpdatingLocation() on the internal location manager.

    Declaration

    Swift

    public func startRecording()
  • Stop monitoring device location.

    Amongst other internal tasks, this will call stopUpdatingLocation() on the internal location manager.

    Declaration

    Swift

    public func stopRecording()
  • Reset the internal state of the location Kalman filters. When the next raw location arrives, filteredLocation will be identical to the raw location.

    Declaration

    Swift

    public func resetLocationFilter()
  • This method is temporarily public because the only way to request Core Motion permission is to just go ahead and start using Core Motion. I will make this method private soon, and provide a more tidy way to trigger a Core Motion permission request modal.

    Declaration

    Swift

    public func startCoreMotion()
  • A convenience wrapper for CLLocationManager.locationServicesEnabled()

    Declaration

    Swift

    public var locationServicesAreOn: Bool
  • A convenience wrapper for the CLLocationManager authorisation request methods.

    You can also interact directly with the internal locationManager to perform these tasks.

    • background: If true, will call requestAlwaysAuthorization(), otherwise requestWhenInUseAuthorization() will be called. Default value is false.

    Declaration

    Swift

    public func requestLocationPermission(background: Bool = false)
  • The device authorisation state for monitoring Core Motion data.

    Declaration

    Swift

    public var haveCoreMotionPermission: Bool
  • A convenience wrapper for CLLocationManager.authorizationStatus().

    Returns true if status is either authorizedWhenInUse or authorizedAlways.

    Declaration

    Swift

    public var haveLocationPermission: Bool
  • A convenience wrapper for CLLocationManager.authorizationStatus().

    Returns true if status is authorizedAlways.

    Declaration

    Swift

    public var haveBackgroundLocationPermission: Bool
  • The internal CLLocationManager manager.

    Direct interaction with this should be avoided. Starting and stopping location monitoring should instead be done through LocomotionManager’s startCoreLocation() and stopCoreLocation() methods.

    Warning

    The CLLocationManager’s desiredAccuracy and distanceFilter properties are managed internally. Changes to them will be overriden, and may interfere with LocomotionManager’s movingState detection. The delegate should also not be changed, as this will disable LocomotionManager, and potentially result in the untimely deaths of small cute animals in Madagascar.

    Declaration

    Swift

    @objc public private(set) lazy var locationManager: CLLocationManager =