I'm trying to detect Automotive
ActivtyType, however the problem is if "I go on a drive and then stop the car and stay in the car" and simply check the coreMotion logs: I would continue to get numerous mixed callbacks of either
high Confidence: Automotive: True, Stationary: True
or
high confidence: Automotive: True, Stationary: False
or
low confidence: Automotive: True, Stationary: True
I do not get an only Stationary: True, it always comes with automotive being True as well
There's not much of a pattern to how they come, or at least I haven't been able to find a pattern.
Q: Has anyone found a reliable way of detecting when the car is truly automotive?
I've tried counting the number of callbacks I get and then doing some calculation but that doesn't seem reliable.
FWIW the moment the user gets out of the car then I get either a walking or stationary (with no automotive...which is good) callback and use those callbacks to set a flag to true...so after that if I get any automotive
callback...then I know it’s a real automotive...
My code:
func beginMotionTracking(){
let motionLog = OSLog(subsystem: "Spike", category: "Motion")
shouldUseTimer = false
motionActivityManager = CMMotionActivityManager()
var totalWalking = 0
var totalAutomotive = 0
var totalStationary = 0
var totalFalseAutomotive = 0
motionActivityManager?.startActivityUpdates(to: OperationQueue.main){
[weak self] activity in
os_log("Motion is Tracking | desiredAccuracy is %{public}f | RemainingTime : %{public}f ",log: motionLog, type: .default, (self?.locationManager.desiredAccuracy)! , UIApplication.shared.remainingTime())
if activity?.walking == true && (activity?.confidence == .medium || activity?.confidence == .high) && activity?.automotive == false && activity?.stationary == false && activity?.unknown == false {
totalWalking += 1
os_log("medium and high conf: walking %{public}d time", log: motionLog, type: .error, totalWalking)
}else if activity?.stationary == true && (activity?.confidence == .medium || activity?.confidence == .high) && activity?.automotive == false && activity?.walking == false && activity?.unknown == false {
totalStationary += 1
os_log("medium and high conf: stationary %{public}d time", log: motionLog, type: .error, totalStationary)
// false automotive
}else if activity?.automotive == true && activity?.stationary == true && (activity?.confidence == .high) && activity?.walking == false && activity?.unknown == false {
totalFalseAutomotive += 1
os_log("high conf: FALSE Automotive %{public}d time", log: motionLog, type: .error, totalFalseAutomotive)
if totalFalseAutomotive > 2{
totalFalseAutomotive = 0
totalAutomotive = 0
totalStationary = 0
totalWalking = 0
os_log("Too many FALSE automotives, REST all counts back to 0", log: motionLog, type: .fault)
}
}
else if activity?.automotive == true && (activity?.confidence == .high) && activity?.walking == false && activity?.stationary == false && activity?.unknown == false {
totalAutomotive += 1
os_log("high conf: Automotive %{public}d time", log: motionLog, type: .error, totalAutomotive)
if ((totalWalking > 3 && totalAutomotive > 2) || (totalStationary > 3 && totalAutomotive > 2) || (totalAutomotive > 7)){
self?.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
os_log("Motion is Automotive and is about to be stopped: desired AccuracyChanged to HundredMeters | RemainingTime : %{public}f ", log: motionLog, type: .fault, UIApplication.shared.remainingTime())
self?.shouldUseTimer = true
self?.motionActivityManager?.stopActivityUpdates()
}
}
}
}
I'm going through all this hassle, because I'm trying to degrade my core-location Accuracy whenever the user isn't driving for more than 3 minutes and then later using core-motion to detect automotive
Motion and use that to put back location Accuracy to hundredMeter.
This is what works for my similar use case, where I want to aggressively restrict interaction when .automotive has become set, but where I'm ok allowing an easy restoration of interaction if it becomes stationary. In logging the messages, it seems to hold onto the .automotive until another mode is detected (e.g. walking)
Since I commute on a bus with WiFi in heavy traffic, I saw repeated messages of:
They toggle as such over and over (and I never saw any medium confidence activities) and only when stationary for a sufficient time (10-12s) does the confidence to go high with stationary true, automotive true so I key off that.
Here's the code that I got to work: