Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Crazy speed GPS MyCLController CoreLocation

KrisKris Posts: 61Registered Users
edited June 2009 in iPhone SDK Development
Hi!

I want to create an app that gives me the distance traveled and the speed - current speed and maximum speed during that distance.

The distance is calculated very nice and accurate. But the speed... here is the problem... Before I ask a question, this is my source code:

MyCLController.h
@protocol MyCLControllerDelegate 
@required
- (void)locationUpdate:(CLLocation *)location;
- (void)locationError:(NSError *)error;
- (void)locationChange:(CLLocation *)newLocation:(CLLocation *)oldLocation;
@end

@interface MyCLController : NSObject <CLLocationManagerDelegate>  {
    CLLocationManager *locationManager;
    id delegate;
	int updateCount;
}

@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, assign) id  delegate;

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation;

- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error;

@end

MyCLController.m
#import "MyCLController.h"

@implementation MyCLController

@synthesize locationManager;
@synthesize delegate;

- (id) init {
    self = [super init];
    if (self != nil) {
        self.locationManager = [[[CLLocationManager alloc] init] autorelease];
        self.locationManager.delegate = self; // send loc updates to myself
    }
    return self;
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
	if (updateCount < 2) {
		[self.delegate locationUpdate:newLocation];
		updateCount++;
	}
	else {
		[self.delegate locationChange:newLocation :oldLocation];
	}
}

- (void)locationManager:(CLLocationManager *)manager
	   didFailWithError:(NSError *)error
{
    [self.delegate locationError:error];
}

- (void)dealloc {
    [self.locationManager release];
    [super dealloc];
}

@end

CoreLocation framework is importand in Prefix.pch
And of course my class that displays data has the <MyCLControllerDelegate> protocol and three methods:
- (void)locationUpdate:(CLLocation *)location;
- (void)locationChange:(CLLocation *)newLocation:(CLLocation *)oldLocation;
- (void)locationError:(NSError *)error;

Later:
locationController = [[MyCLController alloc] init];
	locationController.delegate = self;
	locationController.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
	locationController.locationManager.distanceFilter = kCLDistanceFilterNone;
	[locationController.locationManager startUpdatingLocation];

and what is most important:
- (void)locationChange:(CLLocation *)newLocation:(CLLocation *)oldLocation {//
	NSTimeInterval difference = [[newLocation timestamp] timeIntervalSinceDate:[oldLocation timestamp]];

	double temp_distance = [newLocation getDistanceFrom:oldLocation];
	
	distance += temp_distance;
	distanceLbl.text = [NSString stringWithFormat:@"%.2f",distance];
	
	
	currentSpeed = (temp_distance/difference) * (18.0/5.0);
	if (currentSpeed > maxSpeed) {
		maxSpeed = currentSpeed;
		maxSpeedLbl.text = [NSString stringWithFormat:@"%.2f",maxSpeed];
	}
	currentSpeedLbl.text = [NSString stringWithFormat:@"%.2f",currentSpeed];
}


-(void)locationUpdate:(CLLocation *)location {
	NSLog(@"locationUpdate");
}

- (void)locationError:(NSError *)error {
	NSLog(@"locationError");
}

As you see above everything does locationChange method. MyCLController ignores first two locations - they are passed to locationUpdate method which doesn't do anything at all.

The distance traveled is right: 3000 meters. In most cases the speed displayed is also right (in km/h [18.0/5.0]), but sometimes I get an extreme speed for example 350 km/h which is impossible in that particular moment and it stays in maxSpeed and is displayed on the screen causing confusion.

How do you deal with that trouble? I cannot do any if statment (if (currentSpeed > 100) ...) because I don't know where user will play with my application - while jogging, driving, on the airplane or spaceship...
CoreLocation is not my best part, I've just started using it and try to understand.

BTW Can anybody confirm that it is better to calculate the speed as I do, not using the CLLocation.speed property? I've read it somewhere on dev forums.

I've checked the documantation and maybe I should check the horizontalAccuracy property and ignore the currentSpeed if horizontalAccuracy is to big. I could check it all by myself but I would have to test my application in the car each time I made a major change with it, so can anybody help me?

Thanks in advance
Kris
Post edited by Kris on

Replies

  • KrisKris Posts: 61Registered Users
    edited May 2009
  • jtarajtara Posts: 406Registered Users
    edited May 2009
    In theory, the speed and direction values read from the GPS should be more accurate than the position values. As long as you are moving. And that is the problem with using it - it fails utterly if you are not moving. (May just be because of distance filtering - when you are sitting still, you don't get a "final update" unless you've moved x from your previous location.

    You probably should be filtering-out values with high values for horizontal accuracy. (I wish they wouldn't call it that - it's horizontal INaccuracy!) Be careful if you do that to keep track of the last location on your own, rather than using the one supplied in the callback. (i.e. you will be filtering out some locations, so you have to compute distance/speed from the last GOOD location).
  • KrisKris Posts: 61Registered Users
    edited May 2009
    jtara wrote: »
    I haven't found the speed value to be reliable.

    The funny thing is that, in theory, the speed and direction values read from the GPS should be more accurate than the position values. As long as you are moving.

    Why don't you just calculate the speed yourself, since you are finding location to be accurate?

    as you see I get the speed by dividing the distance between to locations and the difference of their timestamps, everything in locationChange method.
    I don't use the CLLocation speed property.

    Today I will be jogging so I will change my application, so it will log longtitudes and latitudes, timestamps, speeds (using my method and cllocation property) and the horizontalAccuracy into textView and I will study the result. If I figure anything out, I will post it here.

    Maybe anybody know the solution? If since 3.0 developers can make turn by turn navigation I guess, knowing the right speed will be very important :).
  • jtarajtara Posts: 406Registered Users
    edited May 2009
    Yes, sorry, I changed my response after I saw that you were already calculating the speed yourself.

    What is the distance filter you are using? This can still be a problem, as you won't necessarily get an update when you are standing still, and so you will see an erroneous speed.

    As well, you aren't doing any filtering-out of inaccurate readings.

    You may want to consider writing your data to the log or even to a file. I have a debug option to write all my data to a GPX file, which I can upload to my computer later. (You don't need to write any software to do the upload. You can get the log or the file using Organizer.)

    With the GPX file, you can view your path on Google Earth, and really see what is going on with your data.
  • KrisKris Posts: 61Registered Users
    edited May 2009
    Hmmm...

    I don't know how rest of the users will use my app, but I use it for jogging, not fliying, driving, but jogging.

    Do you have any idea what CLLocations with what value of horizontall accuracy should I be ignoring?

    if (newLocation.horizontalAccuracy > 10) {
    //sth
    }

    is ten metres good? of course I'm talking about GPS in 3G, not any location services by wifi or cell towers in 2g/touch 1g.

    Best regards
  • dragidragi Posts: 19Registered Users
    edited June 2009
    Hi,

    I have the same Problem....I´m trying to get accurat speeds since weeks and it will not function very well. Is here anyone who can provide a code sample were the speed is just as accurat as in the App RunKeeper? For higher speeds, it´s easy, but for Jogging and cycling I can´t get good and accurat speeds. It´s exasperating :'(

    thx

    dragi
  • bteasleybteasley Posts: 12Registered Users
    edited June 2009
    A little tangential information here. Note that some mainstream commercial mapping programs (Tom Tom) have offered "pedestrian" and "vehicle" use modes. While there are other reasons for this, in part it is due to the type of issue(s) you are describing.

    If you "know" that the user is walking versus driving, then you can use that information to filter out bad/erroneous readings.

    Location readings (via GPS) are not 100% accurate. An error of 10 feet throws off calculations by a wide margin when somebody is a pedestrian. If you are in a car, 10 feet is not much compared to the distance traveled.
Sign In or Register to comment.