So I'm very very very very new to programming, but I've fumbled my way through this far: I'm creating an Iphone App,
My goal is to create an automatic stopwatch; something that starts itself at a pre-set location and stops itself at a pre-set location ( both of which are set by the user). If the pre-set gps location and the actual gps location are equal, a timer will start/stop. I've done this by setting a location as a variable at the push of a button.
here's the problem: The two values are never equal. The pre-set start and finish locations contain many more decimals than the "actual" location ( the values themselves, not just the printed values) and if they are never equal, the timer will not start.
any help is appreciated!!!!
You could simply calculate the distance between the two coordinates and start/stop the timer when the distance drops below a certain threshold (e.g. 50m) to the start or end location.
CLLocation provides a convient method for doing so:
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
For example:
double lat = 51.7;
double lng = 7.0;
CLLocation *locationStart = [[CLLocation alloc] initWithLatitude:lat longitude:lng];
CLLocation *currentLocation = ...; // received from location services
if ([locationStart distanceFromLocation:currentLocation] < 50) {
// start timer
}
You may also consider using the horizontalAccuracy property of the current location instead of the arbitrary 50m. Beware however that the accuracy can be as bad as several kilometers. Something like MIN(horizontalAccuracy, 50) may work well.
Related
I'm creating a location-based reminder, EKReminder.
For the coordinates I'm using CLGeocoder to convert an address into a CLLocation.
When it comes to the reminder itself, I think that there are two factors involved that determine the 'area' (radius/circle) in which the reminder will fire.
1) the Horizontal accuracy of the CLLocation.
The docs describe the horizontalAccuracy property as "The radius of uncertainty for the location, measured in meters. (read-only)".
There's more good information about this in a previous question:
What do horizontalAccuracy and verticalAccuracy of a CLLocation refer to?
As suggested in that answer, the horizontalAccuracy is 100m.
2) the radius property on the EKStructuredLocation. The discussion notes for this property read "To use the default radius, set this property to 0."
If I create a location-based reminder in the stock, Reminders app from Apple, it comes out with radius = 0 and horizontalAccuracy = 0. So it's using the default 'reminder radius' (don't know what that is) with a value of 0 for the uncertainty in the horizontal location...
I want to avoid having two margins in my reminder. I think there are two options to achieve this:
a) use the default radius for the EKStructuredLocation by setting it to 0 and change the result coming back from the CLGeocoder to have a horizontalAccuracy of 0m.
b) keep the horizontalAccuracy (100m, or different, depending on circumstance) from the CLGeocoder - but not use the default radius for the EKStructuredLocation and set it to something small, like 1m.
Thoughts? Am I understanding these APIs correctly?
Will I get a 'double margin' if I use the returned horizontalAccuracy and the default value for radius?
Does the horizontalAccuracy for the CLLocation object introduce a radius from the coordinate, or is it purely giving information about the uncertainty of the location?
Cheers
As pointed out by progmr, horizontalAccuracy is purely an estimate of the uncertainty in the location.
To back this up, I did a couple of real-world tests where:
I created a location-based reminder in the Reminders app, which has radius = 0 but also reports horizontalAccuracy = 0.
I created a reminder using the same location in my own code, setting radius = 0, but the return from CLGeocoder reporting horizontalAccuracy = 100
With each test, the reminders fired at exactly the same position. horizontalAccuracy is purely for information.
I've developed an iPhone application to parse data from an XML file. This data contains a set of longitudes and latitudes for different places.
How do I detect nearest of them according to my current location on the map and how do I set set a range to show places in this range?
CLLocation *myLocation = [[CLLocation alloc] initWithLatitude:myLatitude longitude:myLongitude];
CLLocation *myXmlLocation = [[CLLocation alloc] initWithLatitude:xmlLatitude longitude:xmlLongitude];
CLLocationDistance distance = [myLocation distanceFromLocation: myXmlLocation];
This is in meters, so you must do any converting from there. They are also linear, so these aren't driving direction lengths by any means. Good luck.
some trig, but really not too difficult.
this page has an example script, not in your language, but it contains explainations and the equations you need.
http://www.movable-type.co.uk/scripts/latlong.html
and also, please don't write run-on sentences, it took me a while to read your question.
#Vinnie said is absolutely right but these values is air distance.
Also this method is deprecated in iOS 3.2
- (CLLocationDistance)getDistanceFrom:(const CLLocation *)location Parameters
You can't find the distance based on roads with the Apple SDK. Try to use google APIs for finding distance between two points on earth on roads.
In my iPhone application I allow the user to choose a destination on the map, then when he starts driving toward the destination I want to give him information like: how long until he reaches the destination and what its current distance from the destination. I'm using CloudMade maps SDK for iPhone and i know there is an API method to get a path between two point that returns also the time and distance between them. Is it OK to call this method every time i get a new location from the CLLocationManager to get the updated time and distance? I assume this method query the CloudMade servers so i don't know if calling it a lot of time is the best way to do this..
For distance
/*
* distanceFromLocation:
*
* Discussion:
* Returns the lateral distance between two locations.
*/
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location __OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_3_2);
For getting the time needed, you could calculate it yourself. CLLocation has a speed parameter. Use the distance and the speed to calculate time.
Swift version would be:
var startLocation:CLLocation!
var lastLocation: CLLocation!
let distance = startLocation.distanceFromLocation(lastLocation)
I am writing an app, that uses GPS. I can get successfully the latitude, longitude and other properties, but altitude seems to always return "0.00" i have the following code to test it in the most simplest way and still get 0.00. Code below:
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// Stop updating location if renewed in less than 60 seconds
if ([self timeBetweenLocationandNow] < 60)
{
[locationManager stopUpdatingLocation];
NSLog(#"GPS Stopped");
}
NSLog(#"Altitude:%.2f m",newLocation.altitude);
}
Any ideas on what could be wrong ? also on an init method i have the following:
- (id)init
{
self = [super init];
if (self != nil)
{
// Create location manager Object
locationManager = [[CLLocationManager alloc] init];
// Set the delegate to this object
[locationManager setDelegate:self];
// Set distance filter and accuracy
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager startUpdatingLocation];
}
return self;
}
Will appreciate any insight. thank you
I'm no expert but this is how I understand it: The iPhone is quite different from other gps systems because of the multiple ways in which it goes about figuring out your location. The iPhone figures out the location in three ways: local wifi signals, cell towers, and/or gps chip. Using a gps satellite to find a position can be extremely slow and reception can be pretty much non-existent in populated cities. Therefore, iPhone generally looks to the first 2 options first.
Wifi positioning data comes from people driving around on the streets logging hotspots which obviously isn't going to give much of a hint of an altitude. I'm not sure if cell tower triangulation gives any altitude data but my guess is no. These two methods are extremely fast compared to gps but will yield an altitude of 0 as you have seen. If you are in a place where there is a decent gps satellite reception the iPhone may give you the altitude, but even then, it might not even find it till it has received the satellite signal a few times and called the location delegate multiple times, and even then altitude data for gps can be notoriously inaccurate.
Long story short, it's a bad idea to count on accurate altitude data from the iPhone.
i found the problem. As Deepmist suggested the delegate has to be called several times. I was stopping the GPS after the first fix. Which was giving me accurate data for coordinates but altitude remained # 0.00 until like 3 or so delegate calls. Now i get the altitude data, what is a good way to check for this ? so i can stop the location manager after i get the data ? i can check that altitude is a non-zero value, but was wondering if there are other properties that should be used instead to make sure that you have the highest accuracy possible making all of your location data valid (i.e non-zero on some properties). thank you
I´m playing a bit with the iPhone SDK and I want to show the current speed in my application. There are so many apps that can do that really precise, especially for low speeds like running or biking. The best I've seen is RunKeeper.
But, in my application, the speed is absolutely inaccurate. In low speeds it is always null, and only at higher speeds it shows some values but they are rarely updated and not really useful.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
if (newLocation.timestamp > oldLocation.timestamp &&
newLocation.verticalAccuracy > 0.0f && // GPS is active
newLocation.horizontalAccuracy < 500.0f && // GPS is active
//newLocation.horizontalAccuracy < kCLLocationAccuracyHundredMeters && // good quality GPS signal
//newLocation.speed > 1.0f && // enough movment for accurate speed and course measurement
oldLocation != nil) // oldLocation is nil on the first reading
{
double speed = (newLocation.speed * 3.6);
[self updateDisplayWithSpeed:speed];
//double direction = newLocation.course;
}
}
Does anyone have working code for that? Or can you tell me what´s wrong with mine?
I would try the following.
Remember that you should set the distanceFilter and desiredAccuracy as needed by your scenario: walking is not the same as traveling by car etc. Moreover, when you request high accuracy from the GPS, you must always discard the very first location provided by the GPS and use the second one as the starting location. Quoting the Apple documentation:
You should assign a value to this property that is appropriate for your usage scenario. In other words, if you need only the current location within a few kilometers, you should not specify kCLLocationAccuracyBest for the accuracy. Determining a location with greater accuracy requires more time and more power.
When requesting high accuracy location data, the initial event delivered by the location service may not have the accuracy you requested. The location service delivers the initial event as quickly as possible. It then continues to determine the location with the accuracy you requested and delivers additional events, as necessary, when that data is available.
Here is my suggestion.
First, update the location using the GPS using an interval of at least one second. Below this interval the speed value is useless because it is measured in meters per second and owing to the previous discussion, you are not likely to get a valid update in less than a second with high accuracy.
Second, only use meaningful values for the location coordinates: you should discard values with negative horizontalAccuracy. This is what I am referring to when speaking of good locations.
Third, you can compute the distance by yourself: compute the distance between the last good location and the previous good location using getDistanceFrom() and then divide by the number of seconds elapsed between the location update. This will give you the distance in meters per second. I will try to do this and compare the result with the Apple provided speed.
Please try following in your code :
speedLabel.text = [NSString stringWithFormat:#"SPEED(Km/Hr): %f", [location speed]*3.6];
latitudeLabel.text = [NSString stringWithFormat:#"LATITUDE: %f", location.coordinate.latitude];
longitudeLabel.text = [NSString stringWithFormat:#"LONGITUDE: %f", location.coordinate.longitude];
CLLocationDistance meters = [location distanceFromLocation:orginalLoc];
distanceLabel.text = [NSString stringWithFormat:#"DISTANCE(M): %f", meters];