How to calculate elevation like in runkeeper application - iphone

I have application that track user movement. And I store all relevant data lat/lng/alt etc.
I am trying add elevation like on runkeeper just without graphic I need just to get elevation value.
In my .h file:
#property (nonatomic) double netElevationLoss;
#property (nonatomic) double netElevationGain;
#property (nonatomic) double netElevationChange;
In my .m file:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
double elevationChange = oldLocation.altitude - newLocation.altitude;
if (elevationChange < 0)
{
netElevationLoss += fabs(elevationChange);
}
else
{
netElevationGain += elevationChange;
}
netElevationChange = netElevationGain - netElevationLoss;
...
I don't know is this correct way to calculate it.
I have tested it and alt is for example 182.53 and netElevationChange is -182.53.
Maybe it's good but maybe I am missing something any idea what I have done wrong here?

According to the Wikipedia article you posted, "cumulative elevation gain" is basically the sum of all increases in elevation.
So for example, say you hike 100 feet up, then 100 feet down, then 200 feet up, then 250 feet down (say, a valley), and then 100 feet up, your gain would be 100 + 200 + 150 = 450 feet. The last 150 is due to hiking to an elevation of -50 feet at some point, then 100 feet up again.
Now, what this means to you is that you simply need to take into account positive deltas of altitude, like so:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
double elevationChange = oldLocation.altitude - newLocation.altitude;
// Only take into account positive changes
if (elevationChange > 0)
{
netElevationGain += elevationChange;
}
}
You could even simplify it further:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
netElevationGain += MAX(0, oldLocation.altitude - newLocation.altitude);
}
This would take into account valleys and even "ups and downs" during ascent and descent (which should be counted according to the article).
At the end, the netElevationGain property will contain your gain.

Related

How to make speed calculation accurate in iOS?

I use CLLocation with accuracy of kCLLocationAccuracyBestForNavigation. I am able to calculate the speed accurately. However, there is a 10sec delay in calculation...
For example, when I drive car at from 45mph to 55mph, the device shows 55mph around 10 secs later.
Is there a way we could make it a bit more precise?
Here is the code...
- (void)getSpeed
{
[self.locMgr startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations
{
double numericSpeed;
self.location = [locations lastObject];
numericSpeed = self.location.speed * 3.6 * 0.621371;
}

How to constantly check GPS Signal strength

I want to display GPS Signal Strength in the form of image like:
But I can't find any documentation about this or example.
I have tried this:
if (self.locationManager.location.horizontalAccuracy < 0)
{
...#"No"];
}
else if (self.locationManager.location.horizontalAccuracy > 163)
{
...#"Poor"];
}
else if (self.locationManager.location.horizontalAccuracy > 48)
{
...#"Average"];
}
else
{
...Full
}
But it seams that this code does nothing.
How can I monitor GPS signal strength, is it possible?
Where is this code located? Your code should be in the delegate callback:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
or iOS 6.0 and above:
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations

Small Location Change Detection

I'm need to detect small location change for the iphone , I tried the sample that's called Locate Me, but it doesn't recognize the small change in the location. Is there any way for doing this?
Thanks in Advance.
Best regards
John
How small is the change that you expected?
Maybe you should set the accuracy to it's maximum and calculate the displacement on the delegate method.
Configure the location manager to give you it's best.
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager setDistanceFilter:0.0];
And then on the delegate method:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Calculate the distance between the two locations
CGFloat distance = [newLocation distanceFromLocation:oldLocation];
if (distance >= MIN_DISPLACEMENT) {
// Do something
} else {
// Do something
}
}
To get more accurate data from the location manager, set the proper keys for UIRequiredDeviceCapabilities (location-services, gps) on the Info.plist.

Compass Calibration problem

How to get the Direction from Compass Calibration,
i used core location framework and don't know how to get north direction from the function:
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading;
if anybody knows help me to get the solution.
the method is the right. You can chosse between magnetic and true heading.
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
float compassHeading_True = newHeading.trueHeading;
float compassHeading_Magnetic = newHeading.magneticHeading;
}
If you want allow compass calibration, you have to implement this method:
- (BOOL)locationManagerShouldDisplayHeadingCalibration:(CLLocationManager *)manager{
return YES;}

CLLocation speed

I am developing GPS application.
Do you know about how to detect speed of mobile device ?
Actually, I need to detect the speed every 2 seconds.
I know didUpdateToLocation method is called when location changed.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
But I think this method is not suitable for my issue.
So, Do I need to check speed of [CLLocationManager location] in 2 seconds ?
Any suggestion ?
Thanks in advance.
How about the code below which works from the delegate method.
Alternatively, if you did want to poll, then keep your previous location and check the distance changed from the last poll and use the manual method (also shown below) to calculate the speed.
Speed is calculated/provided in m/s so multiply by 3.6 for kmph or 2.23693629 for mph.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
//simply get the speed provided by the phone from newLocation
double gpsSpeed = newLocation.speed;
// alternative manual method
if(oldLocation != nil)
{
CLLocationDistance distanceChange = [newLocation getDistanceFrom:oldLocation];
NSTimeInterval sinceLastUpdate = [newLocation.timestamp timeIntervalSinceDate:oldLocation.timestamp];
double calculatedSpeed = distanceChange / sinceLastUpdate;
}
}
You can only really use the delegate method you have suggested in your question.
Even if you access the [CLLocationManager location] every 2 seconds, you will only receive the coordinate you last received in the delegate method above.
Why the need to poll every two seconds? The iphone can update it's coordinates in less time on some cases.
HTH