Decoding the CLLocationAccuracy const's - ios

the following are listed in CLLocation.h but from my experience they are deceiving names- possibly originally thought up to serve two purposes, 1. to test the accuracy of the location returned, but also 2. to set how hard the location manager works, specifically what is enabled (gps (how many sat channels), how hard the wifi works, triangulation etc.
extern const CLLocationAccuracy kCLLocationAccuracyBestForNavigation; // (raw value: -2)
extern const CLLocationAccuracy kCLLocationAccuracyBest; // (raw value: -1)
extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters; // (raw value: 10)
extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters; // (raw value: 100)
extern const CLLocationAccuracy kCLLocationAccuracyKilometer; // (raw value: 1000)
extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers; // (raw value: 3000)
I would love to take a look at CLLocation.m, but as that is not likely to happen any time soon- does anyone have any field testing showing what they think is going on with these different modes.
ie, kCLLocationAccuracyBest = 10 satellite (channels/trunks?), 100% power to wifi etc..
I'm kind of guessing at straws here- I think this is the type of information apple should have provided-
what I really want to know is, what is actually happening with kCLLocationAccuracyThreeKilometers in relation to battery draw- is the gps on? 1 sat trunk? wifi enabled? wifi on a timer? who knows? I know I'd like to

I agree with Olie that hiding the details of the algorithm is intended to protect the app developer from worrying about how location is determined. That said, I believe it's still reasonable to ask the question: "what are the power implications of my accuracy selection?".
I have a little bit of information that might guide your decision on which to use, but I don't know the true details of Apple's implementation.
First, assume that as the reading becomes more accurate, the system will need to use more power-hungry radios. For example, the GPS will be required for the most detailed readings, inside 100 Meters, and it uses the most power.
Here is an educated guess at the mechanism used to determine the accuracy. List is ordered with (1) being the highest battery drain.
GPS - kCLLocationAccuracyBestForNavigation;
GPS - kCLLocationAccuracyBest;
GPS - kCLLocationAccuracyNearestTenMeters;
WiFi (or GPS in rural area) - kCLLocationAccuracyHundredMeters;
Cell Tower - kCLLocationAccuracyKilometer;
Cell Tower - kCLLocationAccuracyThreeKilometers;
When choosing, it is recommended by Apple that you select the most coarse-grained accuracy that your application can afford.
Hope that helps, a.little.

In the business district of a major city, wifi and cell tower triangulation are both very good. Residential suburbs they're not so good. In rural areas they barely work if they work at all.
GPS doesn't work very well indoors, and can take a very long time to get any fix at all without cell tower assistance (possibly 20 minutes!!). It takes that long for the satelites to broadcast enough information to determine your location, and there can be packet loss (clouds, buildings, trees, mountains, etc). It's worth noting that a proper high end GPS will have an antenna the size of a basket ball, no handheld GPS can get a perfect signal.
Even outdoors with perfect signal, GPS is inaccurate when you change direction rapidly (such as on the highway or a windy road). The BestForNavigation setting uses the accelerometer and gyroscope to offset this.
Currently, the iOS platform uses:
GPS: very accurate, but high power draw, slow and not always available. some hardware doesn't have a GPS.
WiFi: lots of power draw, and only works in the city. Can also be flat out wrong (eg place you in the wrong city)
Cell Tower: almost no power draw at all, and works well in the city. Not so great in rural areas. Doesn't exist on some hardware.
Accelerometer: slight improvements to other location fixes, but huge power draw.
Gyroscope: slight improvements to other location fixes, but huge power draw. iPhone 4 only.
You give it an accuracy in meters that you need (the constants are just nice names for meters), and it will use a combination of the above, to get you that level of accuracy with the fastest possible fix and lowest possible power draw. The technique it uses will change, from one user to another, and will change depending on where in the world the user is standing at the time.

The whole point of using extern rather than exposing what is actually happening is so that the under-gerwerkkins can change and your code doesn't have to worry about it to pick up the improvements.
That said, CLLocationAccuracy is typedef-ed to double, so I think it's fair to guess that kCLLocationAccuracyNearestTenMeters = 10.0, kCLLocationAccuracyHundredMeters = 100.0, etc. Best is likely either 0, 1 or kCLLocationAccuracyNearestTenMeters, and BestForNavigation is probably one they tossed it to help folks like TomTom, etc.
If you REALLY want to know, you can print out the values -- they're just doubles.
I do not believe that the number of satellites or power to wifi is altered based on your desired accuracy. The way I understand the algorithms, there is an approximation calculation that, the more times through the loop, the more accurate it gets. Hence, less-accurate just bails earlier.
But, again, the more important point is: it doesn't matter. Apple specifically doesn't describe what goes on behind the scenes because that's not part of the design. The design is: if you use kCLLocationAccuracyKilometer, you'll get an answer that's within a kilometer, etc. And Apple is now free to change how they arrive at that without you caring. This sort of isolation is a basic tenet of object oriented programming.
EDIT:
CORRECTION -- I'm just now watching the WWDC session on location (Session 115) and, at about 22:00 or so, he talks about how, when using BestForNavigation, this adds in some gyroscope correction (when available.) However, he warns that, while this is power & CPU intensive, and should be only used when necessary, as with turn-by-turn navigation.
I'm not sure how much more I can talk about this publically but, if you're a registered developer, you can get the sessions from iTunes-U.
(This is WWDC-2010, btw.)

Related

Minimizing speed variability with kCLLocationBestForNavigation when sailing

I am working on a GPS Apple Watch app for use when sailing which requires high accuracy for a start line scenario. I suspect the additional gyro/accelerometer inputs are actually hurting, not helping GPS accuracy. For example, CLLocation.speed variability seems very high compared to other instruments. (i.e 4.4 knots, 2.2 knots, 6.8 knots, 4.6 knots ... , when other sailing GPS instruments read 4.5 ,4.3 ,4.6 ,4.5, ...)
I understand that having the iPhone nearby will make the watch offload GPS processing to the iPhone. This definitely helps accuracy, but does not seem to help variability. When I am testing off the water (walking or riding a bike), the variability is much lower than sailing. I get similar results running my code on iPhone app and on watch (with iPhone nearby).
func startReceivingLocationChanges(locationManager: CLLocationManager) -> Bool {
// Do not start services that aren't available.
if !CLLocationManager.locationServicesEnabled() {
// Location services is not available.
return false
}
// Configure and start the service.
locationManager.desiredAccuracy = kCLLocationBestForNavigation // kCLLocationBestForNavigation seems to have accuracy issues when sailing, try kCLLocationBest???
locationManager.distanceFilter = kCLDistanceFilterNone // In meters.
locationManager.delegate = self
locationManager.startUpdatingLocation()
return true
}
I am considering trying kCLLocationAccuracyBest to turn OFF the Gyro/accel in hopes that this may help. I am assuming speed and course are simple calculations based on lat/long changes, but perhaps not? I can do these calculations myself if needed. Also interested in possibly using some 3rd party filtering code to "smooth" the curves. Curious what others have tried. (I suspect this might also be an issue for swimmers, and/or mountain biking tracking scenarios where movement is not "smooth" or easily filtered out.)

Timing Advance in GSM

I have a bunch of questions concerning Timing Advance in GSM :
When is it defined ?
Is it the phone or the BTS who's in charge of defining it's value ?
is it dynamic, does it depends on certain situations ?
Let's say that I figured out a way to get the exact value of the Timing Advance (GSM Layer 1 Transmission level) from the phone's modem :
In order to verify my solution, I'm supposed to put my phone over and over in a situation where he have to use/change the Timing Advance while I log its value...
How can I do that ?
Thanks
In the GSM cellular mobile phone standard, timing advance value corresponds to the length of time a signal takes to reach the base station from a mobile phone. GSM uses TDMA technology in the radio interface to share a single frequency between several users, assigning sequential timeslots to the individual users sharing a frequency. Each user transmits periodically for less than one-eighth of the time within one of the eight timeslots. Since the users are at various distances from the base station and radio waves travel at the finite speed of light, the precise arrival-time within the slot can be used by the base station to determine the distance to the mobile phone. The time at which the phone is allowed to transmit a burst of traffic within a timeslot must be adjusted accordingly to prevent collisions with adjacent users. Timing Advance (TA) is the variable controlling this adjustment.
Technical Specifications 3GPP TS 05.10[1] and TS 45.010[2] describe the TA value adjustment procedures. The TA value is normally between 0 and 63, with each step representing an advance of one bit period (approximately 3.69 microseconds). With radio waves travelling at about 300,000,000 metres per second (that is 300 metres per microsecond), one TA step then represents a change in round-trip distance (twice the propagation range) of about 1,100 metres. This means that the TA value changes for each 550-metre change in the range between a mobile and the base station. This limit of 63 × 550 metres is the maximum 35 kilometres that a device can be from a base station and is the upper bound on cell placement distance.
A continually adjusted TA value avoids interference to and from other users in adjacent timeslots, thereby minimizing data loss and maintaining Mobile QoS (call quality-of-service).
Timing Advance is significant for privacy and communications security, as its combination with other variables can allow GSM localization to find the device's position and tracking the mobile phone user. TA is also used to adjust transmission power in Space-division multiple access systems.
This limited the original range of a GSM cell site to 35km as mandated by the duration of the standard timeslots defined in the GSM specification. The maximum distance is given by the maximum time that the signal from the mobile/BTS needs to reach the receiver of the mobile/BTS on time to be successfully heard. At the air interface the delay between the transmission of the downlink (BTS) and the uplink (mobile) has an offset of 3 timeslots. Until now the mobile station has used a timing advance to compensate for the propagation delay as the distance to the BTS changes. The timing advance values are coded by 6 bits, which gives the theoretical maximum BTS/mobile separation as 35km.
By implementing the Extended Range feature, the BTS is able to receive the uplink signal in two adjacent timeslots instead of one. When the mobile station reaches its maximum timing advance, i.e. maximum range, the BTS expands its hearing window with an internal timing advance that gives the necessary time for the mobile to be heard by the BTS even from the extended distance. This extra advance is the duration of a single timeslot, a 156 bit period. This gives roughly 120 km range for a cell.[3] and is implemented in sparsely populated areas and to reach islands for example.
Hope this Answer the question:)
It's defined everytime the BTS needs to set the define the phone's transmission power, which happens quite often.
It's the core system (BTS in GSM) who totally in charge of defining it's value.
It's very dynamic, and change a lot. Globally, the GSM core system is constantly trying to find the exact distance between the BTS and the MS, so it constantly make a kind of "ping" to calculate it. The result of such operations is generally not that accurate since there are a lot of obstacles between the mobile and the BTS (it's not a direct link in an open space).
Such operations happens a lot, so use your smartphone. Simply.

Contiki OS CC2538: Reducing current / power consumption

I am trying to drive down the current consumption of the contiki os running on the CC2538 development kit.
I would like to operate the device from a CR2032 with a run life of 2 years. To achieve this I would need an average current less than 100uA.
However when I run the following at 3V, I get the following results:
contiki/examples/hello-world = 0.4mA - 2mA
contiki/examples/er-rest-example/er-example-client = 27mA
contiki/examples/er-rest-example/er-example-server = 27mA
thingsquare websocket example = 4mA
I have also designed my own target platform based on the cc2538 and get similar results.
I have read the guide at https://github.com/contiki-os/contiki/blob/648d3576a081b84edd33da05a3a973e209835723/platform/cc2538dk/README.md
and have ensured that in the contiki-conf.h file:
- LPM_CONF_ENABLE 1
- LPM_CONF_MAX_PM 2
Can anyone give me some pointers as to how I can get the current down. It would be most appreciated.
Regards,
Shane
How did you measure the current?
You have to be aware that using a basic ampere meter to measure the current consumption of contiki-os wouldn't give you relevant results. The system is turning on/off the radio at a relative high rate (8Hz by default) in order to perform the CCA. This might not be very easy to catch for an ampere meter.
To have an idea of the current consumption when the device is in deep sleep (and then make calculation to determine the averaged current consumption), I'd rather put the device in the PM state before the program reach the infinite while loop. I used the following code to do that:
lpm_enter();
REG(SYS_CTRL_PMCTL) = SYS_CTRL_PMCTL_PM2;
do { asm("wfi"::); } while(0);
leds_on(LEDS_RED); // should not reach here
while(1){
...
On the CC2538, the CCA check consumes about 10-15mA and last approximately 2ms. When the radio transmit a packet, it consume 25mA. Have a look at this post: Contiki UDP packet transmission duration with CC2538.
Furthermore, to save a little more current, turn off the serial com:
#define CC2538_CONF_QUIET 1
Are you using the SmartRF board? If you want to make proper current measurement with this board, you have to remove every jumpers: P486, P487, P411 and P408. Keep only the jumpers of BTN_SEL and the RESET signals.

CoreLocation find distance travelled and use as variable iOS

I am making an alarm that shuts off only after the phone has been moved a certain distance(to force the user out of bed). I need to be able to find the distance travelled after the alarm has gone off, then take this distance and use it in a method to shut the alarm sound off if the minimum distance has been travelled. Any ideas?
I'm using the following to update the location. Any thoughts on how to incorporate this into disabling the alarm?
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if(!newLocation) {
NSLog(#"No movement");
}
if ((oldLocation.coordinate.latitude != newLocation.coordinate.latitude) &&
(oldLocation.coordinate.longitude != newLocation.coordinate.longitude))
{
CLLocation *loc1 = [[CLLocation alloc] initWithLatitude:oldLocation.coordinate.latitude longitude:oldLocation.coordinate.longitude];
CLLocation *loc2 = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
CLLocationDistance distance = [loc2 distanceFromLocation:loc1];
if (distance>=4) {
NSLog(#"Very good!");
}
}
NSLog(#"Location:%#", newLocation);
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
A couple of thoughts:
You're not considering horizontalAccuracy. First if this is negative for either coordinate, then you just can't do any comparison. And even if they're both non-negative, you probably want to back out the horizontal accuracies if you really want to determine if the user moved a certain distances.
Look at not only the latitude and longitude, but the horizontalAccuracy, too.
You're not considering that when you turn on location services, there are frequently a whole series of coordinates that come in, and the coordinates may bounce around as the horizontal accuracy gets better and better. You want to make sure you don't consider this slow triangulation as the movement necessary to qualify as having gotten out of bed.
Make sure you do your experimentation on a real device, in real world scenarios. Using the simulator is definitely not a good test. Nor is using a device plugged into your computer (because you you want to see your GPS in real world scenario, where someone has moved around before going to bed).
I'd suggest starting with a simple app that logs location events in a database (or other format) and perhaps show the log in a tableview, so you don't always have to go back to your computer to review the results. Fire up that app, walk around, and then look at the location events you get. That will help you get your arms around the patterns you see as people use their actual devices.
Note that if this app is destined for the app store, you'll want to engage lots of different people in different environments and different devices and different scenarios (poor GPS locations, with wifi, no wifi, etc.). Even when you do your own real-world GPS experience with a physical device, you must appreciate that everyone else's may experience different GPS results.
I must confess to some reservations whether the iPhone GPS is accurate enough for this sort of app as a generalized solution, and you'll probably want to warn the user to make sure to plug in their iPhone before they go to sleep so the GPS doesn't drain the battery. You might also want to play tricks like turning on location services after the user has demonstrated that they're up and about. You might also not even want to turn on location services until a few minutes before the alarm, thereby assuring that the GPS is as accurate as it can be when the alarm goes off, but not draining their battery as they sleep if they don't happen to have it plugged in and charging.
Update:
Probably easier than calculating distances yourself, use the location services distance filter (i.e. only generate events when the location changes by x meters). For example:
- (void)startLocationManager
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 5.0; // detect when I move 5 meters
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
}
When I do that, standing completely still, as soon as I turn on location services, I get a whole bunch of events before I even start moving. You can see the GPS warming up, and getting more and more accurate:
latitude longitude horizontalAccuracy
---------------- ------------------ ------------------
39.9482837548282 (82.4963494095571) 65
39.9482817585030 (82.4964543834170) 10
39.9482392622539 (82.4964914314290) 5
39.9481753502422 (82.4964918505242) 5
39.9481269028419 (82.4964797805836) 5
I wait for that to quite down (it took 15-20 seconds in my case), and then I started walking in a straight line, looking at the distance from the last location I got above.
latitude longitude horizontalAccuracy distance
---------------- ------------------ ------------------ --------
39.9481722908476 (82.4964962091138) 5 5.3
39.9482206544289 (82.4965029146363) 5 10.4
39.9482627315828 (82.4965282279839) 5 15.4
39.9483157471204 (82.4965248752227) 5 21.2
I must confess that while I didn't measure it, these distances didn't feel quite right, but possibly within the 5 meter tolerance I set up with my distanceFilter.
Anyway, as all of this evidences, the right process is probably going to be
turn on location services, setting the distanceFilter appropriate for your app;
wait for the location to settle down;
make sure the horizontalAccuracy is even plausible for this process to work at all; and
wait for the new location notification based upon the GPS determining that the distanceFilter has been exceeded.
This never will be perfect (e.g. I had to walk a good 6-10 meters before my "5 meter" distanceFilter kicked in, probably a combination of the GPS lagging a few seconds and the horizontalAccuracy), but it might be "good enough for government work."
(By the way, I've changed my coordinates in the above log, so don't look for me in this Ohio cornfield, but it gives you and idea of the sort of pattern you may see.)

Blackberry cache reverse geocode address info with proximity

Most people are limited to about 5 or 6 locations on a daily basis (work, home, school, store, etc). I want to speed up address display by caching a few of these most visited locations. I've been able to get the address info using both google maps GPS and JSON and Locator.reverseGeocode. What would be the best way to cache this information and to check proximity quickly? I found this GPS distance calculation example and have it working. Is there a faster way to check for proximity?
Please see similar question first: Optimization of a distance calculation function
There are several things we can change in distance calculations to improve performance:
Measure device speed and decrease or increase period of proximity test accordingly
Trigonometric calculations takes most of performence, but it may done much faster. First make bold distance calculations using lookup table method, then if distance is less than proximity limit + uncertainty limit, use CORDIC method for more precise calculation.
Use constants for Math.PI/180.0 and 180.0/Math.PI
several links that may be helpful:
Very useful explanations of CORDIC, especially doc from Parallax for dummies
Fast transcendent / trigonometric functions for Java
Cordic.java at Trac by Thomas B. Preusser
Cordic.java at seng440 proj
Sin/Cos look-up table source at processing.org by toxi

Resources