Accuracy has absolutely tanked since the latest update

I don’t know if this helps, but I discovered this morning that if I re-classify a chunk of transportation as stationary, the app suddenly presents me with all these “brief stops” that I wasn’t able to see before, which then allows me to tag the stop that I was looking for. I can then re-classify the other segments as transportation again. Not sure why these stops aren’t just showing up in the “split segment” interface.

I don’t know if this helps, but I discovered this morning that if I re-classify a chunk of transportation as stationary, the app suddenly presents me with all these “brief stops” that I wasn’t able to see before

The timeline view has two distinct kinds of Timeline Items: Visits and Paths. A Visit is a stationary period that you can assign a Place to, while a Path is a trip between Visits, which you can assign an Activity Type to.

Within a Visit there might still be moving type segments within - visible on the Individual Segments view, and in a Path there might still be stationary segments. This is because a single segment isn’t promoted to the main timeline view as a Timeline Item unless it meets certain minimum thresholds. Those being at least 2 minutes duration for a stationary segment to become a Visit, and for a Path the thresholds are minimum 60 seconds duration and minimum 30 metres distance.

Segments that don’t meet those thresholds instead get merged in to an adjacent Timeline Item. So for example if you are walking, then stop at a pedestrian crossing for 10 seconds, then continue walking, that 10 seconds stationary won’t meet the minimum minutes threshold, so will be merged into the walking Timeline Items on either side.

However that stationary segment will still be visible in the Individual Segments view, and you can tap on it and assign a Place to it, which will then promote it to being a full Timeline Item visible on the timeline view. This is because assigning a Place manually makes the segment meet the “keeper” threshold, regardless of duration.

You can also extract Visits out of Paths from the Individual Segments view by changing the type of a 2+ minute segment to stationary. For example if a long segment has been misclassified as car or cycling when really you were stationary for that period, changing it to stationary will convert it to a Visit and promote it to the timeline view.

How did you get on with installing Arc Mini and getting to those debug views? You really shouldn’t be seeing anything classifies as “transport”, because when Arc says “transport” really it means “I don’t have enough data to confidently classify this as any specific type”. That means that there’s probably something wrong with the data models, which we’ll need to find the cause of. In normal use, seeing “transport” should be very rare, except perhaps for when travelling to new areas you’ve never been to before.

Speaking of that, I’ve just now encountered a weird behavior that may be related to that.

I’m currently on a train on the Yamanote line, which is above ground with good gps signal, and the recording quality is drastically different whether Arc is running or closed (by swiping up from the recent apps). When Arc is recording, the geolocation is very coarse, probably using just the WiFi/ble beacon data, and gets updated around once every 30 seconds. However, if only Arc Mini is running, I can easily get 1 sample per second with 15m accuracy.

Maybe iOS limits the accuracy of the location if it’s been constantly requested to save battery or something? And it would make sense that the limit is per-app (or per-CLLocationManager, that would explain the map dot being correct, it’s not using the location often in the background), so that apps that need accurate location only few times per day shouldn’t be throttled because of the ones that need it constantly. Arc mini records when the main Arc app isn’t recording, so it also gets a softer treatment by iOS. Maybe there’s a way to split the recording approximately 50/50 (except for the cases where one of the apps gets killed of course)?

P.s. just to clarify, the last paragraph is pure speculation in my part based on the factual data from the second paragraph. I don’t really know how iOS works on the inside :upside_down_face:

Ah the good ol Yamanote! Can’t wait to get back there next January.

Haha, you and me both. Apple are very deliberate about keeping us in the dark about those things.

Anyway I think the essence of your hunches are likely correct, at least in some way. My suspicion is similar in that apps get graded/marked based on energy and resource use over time, and are then subsequently favoured or disfavoured in terms of access to those resources. So if Arc App is doing most of the recording, using more resources than Mini on average, it’ll draw more of iOS’s ire and potentially be granted less accurate data.

It’s also possible that Apple are internally hardcoding different settings in iOS for Arc App. Arc App has been around for quite a few years now, and the Core Location / Location Services team will be well aware of it. It’s not uncommon for well known apps to get app-specific hardcoded tweaks built in at OS level, for things like maintaining compatibility with popular old unmaintained apps that would otherwise start to crash, or in this case perhaps different location data accuracy thresholds intended to more specifically manage Arc’s energy use.

Though that feels slightly conspiracy theory, and I’m more inclined to think it’s the former - Arc simply doing more of the work, and thus being punished for that.

One thing to keep in mind though, as I’ve learnt painfully over the years, is that any real world testing you do can easily turn out to have been a fluke, when you retest again the next day or a week later, or daily over several weeks or months (as I used to aggressively do in Arc’s early years).

Whenever you think you’ve spotted a pattern, more testing ends up showing it as just another unexplained random event.

Which is why over the years I’ve taken to talking about iOS’s black box / undocumented behaviours in quite emotive terms - iOS having moods, playing favourites, etc. It’s incredibly difficult to pin down reliably deterministic behaviours!

I’ve occasionally pondered the same idea. It’s also something I’d like to do with the scheduled background daily housekeeping tasks. Both Arc App and Arc Mini file requests for the same list of tasks (with Arc App filing a handful more, for data processing/presentation features that don’t exist in Mini). Then it’s up to iOS to decide which app’s requests to honour first / quickly / at all. It might be beneficial for Mini to be the only one that requests to do some of those tasks, or requests them earlier/more frequently than Arc App does.

But ultimately that load balancing is supposed to be iOS’s responsibility. Trying to game the system might be counter productive in the end.

Though for the actual responsibility of being the active recorder at any point in time… yeah, that seems like it potentially could be more worthwhile. It’s something I do want to come back to at some stage, to see if it could help.

1 Like

I’ve actually been able to reproduce it today as well! Same line, same place, same behavior.

I’ve done 2 iterations, in one I kept only Arc Mini running, in the other I opened Arc at the start of the turn and closed in the middle, and you can clearly see that segment :melting_face:

I guess my next test will be deleting Arc, letting Arc Mini do all the recording for a week or so, and then doing this test again (and hopefully the results will flip). Hopefully I’ll be able to classify and back up the new data when I re-install Arc, right? Just making sure that I don’t loose a week of data with those tests XD

1 Like

When doing these tests, if you’re swiping one of the apps closed, make sure to bring the other app into the foreground straight after. The “active recorder” switching can take a couple of minutes to notice that the other app has disappeared, so when one of the apps dies there’s often a little 2 minute data gap until the other app realises. But bringing the app into the foreground triggers it to immediately take over as active recorder. So you can preempt that “is the other app really dead? should I take over?” delay.

Just make sure you’ve always got at least one of the apps installed! It’s safe to delete one of them, because the “App Group Container” won’t be deleted unless both apps are deleted. But yeah, deleting both will trigger container deletion - bad times.

Curious to see more testing results! This is something I should spend more time on testing myself, but right now I’m in Bali, where there’s no buildings higher than 5-6 storeys. Even an app that’s having its location data accuracy aggressively throttled will still probably get really clean data here. Need a big city to test in!

Oh actually that makes me realise that you can probably just do the testing by bringing one app or the other into the foreground, given that foregrounding immediately triggers active recorder takeover.

Although… if iOS is throttling location data accuracy for all apps based on one app it doesn’t like being alive and recording, maybe you do need to swipe one of the apps closed to get proper test results. I guess really depends what iOS is actually doing. Which is… what we don’t know, and the point of these tests :joy:

1 Like

Yup, that’s exactly what I was doing. I was pretty sure that something like that was indeed happening in the background, so I switched to Arc Mini as quickly as possible after quitting Arc.

Yeah, I’ve been kinda obsessed with Arc for the last month or so (ever since I switched to an iPhone), even though I’ve been using it on my backup phone for years now, and since I had absolutely 0 experience in iOS apps (or any app development at all, my specialty is coding for microcontrollers in C, which has almost no transferrable experience aside from maaaaybe the very basics) I wanted to learn what the limits are and how they can be extended even further :eyes:
So I’ll be happy to do a bunch more tests in my spare time and report back! :blush:

Yup, tried that as well a few times, the behavior was the same, but I decided to keep closing Arc to make the number of possible ways of it doing something unexpected as low as possible. What if it suddenly switches the recording back to Arc while I’m thinking that Arc Mini is the one recording? Actually, is that even possible, or is the foreground app always the one recording?

1 Like

It’s a funny thing with Arc versus its competitors - because Arc’s main goal has been to be the most accurate and detailed timeline recorder, that kind of overflows into the user experience a lot of the time too. Especially for people who already have a lot of interest / experience in data handling and processing.

It certainly wasn’t my intention! But I think because most other apps just aim for a high level overview, users accept those apps for what they achieve, which is much less detail than Arc. But because Arc is aiming to get as much detail and accuracy as possible given the current hardware’s abilities, that flows over into the user experience, where we (myself included) end up sometimes obsessing over getting more and more out of it. “There’s got to be a way to get even more accuracy here” :joy:

That’s actually been kind of counterproductive for the app as a business, unfortunately. People are getting much more accuracy and detail, but there’s some psychology going on that makes them less satisfied with that extra detail than they are with the lesser detail / lesser accuracy of predecessor apps or some competitors.

Though I guess also it’s partly just that Arc attracts users who are inherently going to want the best possible results - it’s the timeline recorder for data nerds :joy:

That kind of experience would be invaluable in the lower levels of Arc/LocoKit! Where things like single instructions or loop iterations really matter.

Arc is kind of a challenging one to take on as an individual, because it goes right from the lower level details of energy optimisation and raw data processing, right up to the high level UX details of how the user perceives and interacts with it all. I tend to find myself bouncing between the extremes sometimes, spending a month or so in the guts of things, then the next month trying to improve the UX so that users can actually appreciate the improvements made at the bottom of the stack. (It’s the stuff in the middle that tends to be the most boring work).

We’re of the same mind then. I don’t know for sure whether having the standby app still alive in the background would make a difference, but for the sake of this kind of testing it’ll simplify things to eliminate it completely from the equation.

Good question. And… unless I’m forgetting some LocoKit logic, it shouldn’t be possible. The foreground app should always command active recorder status. If the other app did manage to take over (perhaps due to the IPC / AppGroup messaging failing), then the foreground app would very shortly after say “nope, get lost. this job is mine” and take over again.

The foreground / active recorder app gets to make those decisions on cycles of 2-30 seconds, while the background / standby app is on 2 minute standby cycles. (If I’m remembering all the numbers right. It’s somewhere around those anyway.)

1 Like

By the way, is the recording handoff possible only between Arc and Arc Mini, or can any LocoKit app participate in that? From a quick look at Arc Mini’s source code I think all the needed things are in Arc Mini/Models/Database/ArcStore.swift and Arc Mini/Managers/RecordingManager.swift, but I’m not sure yet…

I have an idea of making a third app for testing that just tries to be the recorder for about 40-50% of the time and see how it’ll impact the accuracy, but not sure if that’s even possible.

And in general, if I were to use LocoKit in my app, would I be able to use the models already trained in Arc (if it’s installed) and have my app help with Arc recording? This sounds to me like a very cool idea, but it also sounds as something that’s very difficult to actually pull off, so I thought I’d ask.

On the other hand, while I can’t speak for everyone, I’m more than happy to pay more than usual for that kind of accuracy :smiley:

Speaking of which, I was wondering, what plan option is better for you if a user buys? (if that’s not a trade secret or something :sweat_smile:) The monthly seems better because in the long term it’s going to be more profitable, but the one-time plan allows for better budgeting and upfront investment, I think… Basically what I’m asking is which one should I use if I can afford both and want to support the development a bit more :grin:

Unfortunately the app would need to be part of the AppGroup, which is only possible if it’s deployed with my developer account. The key file for the IPC is `AppGroup.swift. From memory, part of it is direct IPC and part is messaging through a shared UserDefaults in the AppGroup container.

Yeah, just poking through the code, I see AppGroup.send() method doing both - setting the message in the shared UserDefaults, then also sending an immediate message via CFNotificationCenter. Ugh, I tapped send by mistake. I’ll continue this reply in a new reply.

1 Like

So the CFNotificationCenter part escapes the AppGroup, because that’s system-wide messaging. But the AppGroup’s UserDefaults is sandboxed to the AppGroup. So another app listening for the system-wide messages wouldn’t be able to pick up the necessary extra details.

Or could it… I wonder actually if the active recorder handover doesn’t require the extra details in the UserDefaults - that’s sugar on top. Although… it wouldn’t be much use anyway, because an app outside of the AppGroup wouldn’t have access to the shared database, so it couldn’t be contributing to the same timeline data. That’s a bit of a blocker!

1 Like

With a LocoKit API key you could get the GD models from the server. But it wouldn’t have access to the CD models in the AppGroup. It’d have to build its own. So it wouldn’t be able to contribute directly back to the most important models Arc is using (ie the CD models).

Just by the numbers, I make the most money if someone sticks with a monthly subscription. But I’m really uncomfortable with that, because most people tend to continue using Arc for years, and a monthly subscription over several years adds up to amounts that I’m really not comfortable with charging!

Monthly subscriptions are fine for things we use for maybe a few months, but for things we’re going to continue using for years they’re really not a good deal. (Services that don’t offer yearly rates rub me the wrong way.)

I’m happiest when people buy a Lifetime purchase. Because that’s the best deal for them, by far. That way I don’t have to feel guilty about someone getting ripped off over the longer term. And it also shows me that that person really does plan to keep using the app for several years, which is nice to see :smile:

1 Like

Ah, I see! I reckoned something like that would be the case… But this means that I should be able to at least make an app that just measures how much time Arc spends recording and how much Arc Mini does, right?

In any case, thanks a ton for the explanation, what to me was unpredictable magic is now way easier to understand!

Ooh that’s an interesting thought. I wonder if that much detail could be determined from the CFNotificationCenter messages. Hmm. The CFNotificationCenter ones are just message name alone, because you can’t [easily] encode Swift data types into those messages.

Ugh, it looks like you’d possibly only see messages like group.ArcApp.tookOverRecording, but without the name of the app that sent the message. Unless CFNotificationCenter messages contain sender process details… Which I’m not seeing any definitive confirmation of in the API yet. Though I’m only skimming it.

The key code will be the CFNotificationCenterAddObserver() at the bottom of AppGroup.swift. It does look like it might actually be possible to encode some more details in those messages. Which would actually be super handy, because those messages should be “immediate”, where as the shared UserDefaults ones are only noticed when AppGroup.swift manually polls it (presumably once it receives the CFNotificationCenter message).

Though I’ve actually got a hunch the CFNotificationCenter stuff isn’t working at the moment. Not that I’ve confirmed that it’s stopped working, it would just explain why active recorder handover sometimes appears to be slower than it should be.

If you do want to throw together a quick app to test any of this stuff, I recommend building from LocoKit Demo App. That’s a SwiftUI rebuild of the very old (and probably now broken) demo app in the LocoKit repo.

Though you can always build on top of the Arc Mini code. But for lower level / pure LocoKit layer testing I prefer to work with the demo app. Less higher level fluff in the way, and simpler code to hack debug UI bits into as needed.

1 Like

Oh I’m probably barking up the wrong tree there, now that I think about it. The slow handover I sometimes notice is when the active recorder dies/gets killed. And in that case the active recorder is dead, so it can’t be sending any CFNotificationCenter messages. The standby app really does just have to wait until it next polls the shared UserDefaults and notices that the other guy who’s supposed to be active recorder hasn’t updated state recently enough. Sigh.

1 Like