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.
-
Undocumented
Declaration
Swift
public let pedometer = CMPedometer()
-
The LocomotionManager’s current
RecordingState
.Declaration
Swift
public private(set) var recordingState: RecordingState
-
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’sdesiredAccuracy
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
andkCLLocationAccuracyHundredMeters
. 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 tomaximumDesiredLocationAccuracy
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 ofActivityTypeClassifier
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
andLocomotionSample.zAcceleration
will be set with the results.Note
If you are making use ofActivityTypeClassifier
, 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 ofActivityTypeClassifier
, 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 inrawLocation
. For fully smoothed and denoised motion properties you should uselocomotionSample
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 currentLocomotionSample
.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 aLocomotionSample
instance fromlocomotionSample
and usemovingState
anddate
on that sample.Declaration
Swift
public var movingState: MovingState
-
Start monitoring device location and motion.
NSNotification.Name.didUpdateLocations
notifications will be sent through the systemNotificationCenter
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 callrequestAlwaysAuthorization()
, otherwiserequestWhenInUseAuthorization()
will be called. Default value isfalse
.
Declaration
Swift
public func requestLocationPermission(background: Bool = false)
- background: If
-
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
orauthorizedAlways
.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()
andstopCoreLocation()
methods.Warning
The CLLocationManager’sdesiredAccuracy
anddistanceFilter
properties are managed internally. Changes to them will be overriden, and may interfere with LocomotionManager’smovingState
detection. Thedelegate
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 =
-
Undocumented
Declaration
Swift
public func locationManager(_ manager: CLLocationManager, didRangeBeacons beacons: [CLBeacon], in region: CLBeaconRegion)
-
Undocumented
Declaration
Swift
public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus)
-
Undocumented
Declaration
Swift
public func locationManager(_ manager: CLLocationManager, didVisit visit: CLVisit)
-
Undocumented
Declaration
Swift
public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])