2012-04-17 28 views
9

Tôi đang cố gắng sử dụng distanceFromLocation: phương pháp để tính tổng khoảng cách mà tôi đang đi với iPhone của mình trong tay. Cho đến nay, tôi đã tìm kiếm tất cả để giúp khắc phục kết quả khó hiểu, không chính xác và có vẻ tùy ý của tôi. Trong đoạn mã này, theLabel chỉ là một đối tượng nhãn hiện diện trong giao diện của ứng dụng của tôi, distanceMoved là biến mà tôi đang cố gắng lưu trữ tổng khoảng cách mà tôi đã đi vào, và locMan là một trình quản lý vị trí được khai báo trong tệp @interface của tôi .Rắc rối với phương pháp CLLocation distanceFromLocation: Kết quả không chính xác

- (void)viewDidLoad 
{ 
    locMan = [[CLLocationManager alloc] init]; 
    locMan.delegate = self; 
    [locMan startUpdatingLocation]; 
    isInitial = true; 
    distanceMoved = 0.0; 
    [super viewDidLoad]; 
} 

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    distanceMoved += [newLocation distanceFromLocation: oldLocation]; 
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 
} 

Bất kỳ trợ giúp nào để khắc phục những gì tôi đang làm sai ở đây sẽ được đánh giá cao. Cảm ơn bạn!

Trả lời

13
  1. Lọc ra cache (cũ) dữ liệu vị trí,
  2. Lọc ra kết quả vị trí không hợp lệ (chính xác < 0),
  3. Set yêu cầu độ chính xác thiết lập để kCLLocationAccuracyBest,
  4. Đặt một bộ lọc khoảng cách tối thiểu, tốt nhất ít nhất 10 mét để lọc ra tiếng ồn vị trí.
  5. EDIT: Không tính khoảng cách khi oldLocation là không.

Bạn có thể làm được nhiều việc hơn nhưng điều này sẽ hoạt động với điều kiện bạn có được độ chính xác đủ caoAccuracy (< 30m). Bạn có thể lọc ra kết quả chính xác thấp nhưng sau đó bạn phải theo dõi các oldLocation mình là một chút phức tạp hơn.

Thêm NSLog (xem bên dưới) để bạn có thể tìm hiểu điều gì đang xảy ra. Nếu bạn vẫn không nhận được kết quả tốt, hãy đăng đầu ra của NSLog để chúng ta có thể thấy những gì đang diễn ra và giúp đỡ nhiều hơn.

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{ 
    NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 

    if (age > 120) return; // ignore old (cached) updates 

    if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates 

    // EDIT: need a valid oldLocation to be able to compute distance 
    if (oldLocation == nil || oldLocation.horizontalAccuracy < 0) return; 

    CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation]; 

    NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm", 
     oldLocation.coordinate.latitude, 
     oldLocation.coordinate.longitude, 
     newLocation.coordinate.latitude, 
     newLocation.coordinate.longitude, 
     distance, 
     newLocation.horizontalAccuracy); 

    distanceMoved += distance; 
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 
} 

- (void)viewDidLoad 
{ 
    locMan = [[CLLocationManager alloc] init]; 
    locMan.delegate = self; 
    locMan.desiredAccuracy = kCLLocationAccuracyBest; 
    locMan.distanceFilter = 10; 

    [locMan startUpdatingLocation]; 
    isInitial = true; 
    distanceMoved = 0.0; 
    [super viewDidLoad]; 
} 

EDIT cho iOS6 nếu bạn muốn làm điều tương tự sử dụng didUpdateLocations: (kể từ khi các phương pháp trên hiện đang bị phản đối) là giải pháp đơn giản nhất là chỉ cần lưu mỗi vị trí trong một tài sản để trên bản cập nhật tiếp theo bạn có vị trí trước đó.Khai báo một tài sản trong lớp để giữ oldLocation:

@property (nonatomic, retain) CLLocation* oldLocation; 

Sau đó, trong phương pháp đại biểu giúp bạn tiết kiệm mỗi newLocation để sử dụng làm oldLocation cho lần tiếp theo phương pháp đại biểu được gọi là:

-(void)locationManager:(CLLocationManager *)manager didUpdateToLocations:(NSArray *)locations 
{ 
    CLLocation* newLocation = [locations lastObject]; 

    NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow]; 

    if (age > 120) return; // ignore old (cached) updates 

    if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates 

    // EDIT: need a valid oldLocation to be able to compute distance 
    if (self.oldLocation == nil || self.oldLocation.horizontalAccuracy < 0) { 
     self.oldLocation = newLocation; 
     return; 
    } 

    CLLocationDistance distance = [newLocation distanceFromLocation: self.oldLocation]; 

    NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm", 
     self.oldLocation.coordinate.latitude, 
     self.oldLocation.coordinate.longitude, 
     newLocation.coordinate.latitude, 
     newLocation.coordinate.longitude, 
     distance, 
     newLocation.horizontalAccuracy); 

    distanceMoved += distance; 
    theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 

    self.oldLocation = newLocation; // save newLocation for next time 
} 
+0

Tôi chỉ sử dụng mã chính xác này, nhưng tôi đã thay đổi bộ lọc khoảng cách thành 1. Đối với một số lý do, khoảng cách của tôi đã bắt đầu ở -1. Đây là kết quả của tôi sau khi đi bộ khoảng 2m về phía trước: 2012-04-17 17: 58: 05.341 Vị tríManagerTest2 [422: 707] 0.000000/0.000000 đến 39.856110/-74.940113 cho -1m, độ chính xác +/- 10m 2012-04 -17 17: 58: 10.248 Vị tríManagerTest2 [422: 707] 39.856110/-74.940113 đến 39.856165/-74.940107 trong 6m, độ chính xác +/- 50m 2012-04-17 17: 58: 11.248 LocationManagerTest2 [422: 707] 39.856165/- 74.940107 đến 39.856223/-74.940010 cho 10m, độ chính xác +/- 50m Khoảng cáchMoved xuất hiện khoảng 15m - cách quá nhiều – bnasty

+0

Tôi đã thử sử dụng mã này vài lần trước đây, và tôi nhận được một số kết quả dường như chính xác và một số đã xa – bnasty

+0

khoảng cách -1 là nơi oldLocation của bạn là 0, có thể có nghĩa là thông số oldLocation là không. Bạn sẽ cần phải thêm một kiểm tra cho rằng quá (xem chỉnh sửa của tôi ở trên). Bạn không thể mong đợi độ chính xác cao khi báo cáo horizontalAccuracy là 50m !!! Điều đó có nghĩa là GPS không có tín hiệu đủ tốt, điều đó có nghĩa là vị trí được báo cáo có thể giảm đi 50 mét theo bất kỳ hướng nào. – progrmr

0

Bạn không đặt độ chính xác của trình quản lý vị trí của mình. Đi qua tài liệu táo, nó là một cái gì đó giống như độ chính xác = bestfornavigation. hay gì đó. Điều đó sẽ tiêu hao pin như địa ngục nhưng có nghĩa là cho loại mục đích này.

chỉnh sửa: chỉ cần nhớ tôi đã có nó trong tầm tay.

// Create the Location Manager 
locationManager = [[CLLocationManager alloc] init]; 

// Configure the Location Manager 
locationManager.delegate = self; 
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation; 
+0

tôi đã cố gắng thiết lập tất cả các hằng số khác nhau cho độ chính xác mong muốn, nhưng vẫn không có may mắn. Bây giờ, ứng dụng của tôi sẽ bắt đầu với distanceMoved tại -1.00000 vì một số lý do thay vì 0.000000. Có thể vấn đề có thể nằm trong khuôn khổ Vị trí cốt lõi của tôi hoặc bản thân iPhone của tôi không? – bnasty

+0

NSlog vị trí cũ và mới để xem chúng thay đổi như thế nào. sau đó nói với tôi vì vậy tôi có thể có một ý tưởng về những gì đang xảy ra. Tôi đã làm việc rất nhiều với người quản lý vị trí và tôi nhớ rằng nếu bạn không định cấu hình chính xác nó sẽ làm những thứ kỳ lạ – Pochi

+0

Các tọa độ kinh độ và vĩ độ có vẻ chính xác, mỗi khi vị trí được cập nhật, vị trí mới từ lần cuối cùng được lưu trữ như vị trí cũ. Đối với một số lý do, khoảng cách giữa hai địa điểm đang được tính toán như một số cực cao. – bnasty

0
CLLocationDistance distance = [secondLocation distanceFromLocation:firstLocation]; // distance is expressed in meters 

CLLocationDistance kilometers = distance/1000.0; 
// or you can also use this.. 
CLLocationDistance meters = distance; 

NSString *distanceString = [[NSString alloc] initWithFormat: @"%f", kilometers]; 

flot totaldistancecovered = [distanceString floatValue]; 

//Now,you can use this float value for addition... 
// distanceMoved should be float type variable which is declare in .h file... 

distanceMoved = distanceMoved + totaldistancecovered ; 
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved]; 

Hy vọng điều này sẽ giúp bạn ..

+0

'CLLocationDistance' chỉ đơn giản là một typedef cho' double', do đó không có lý do để chuyển đổi nó thành một chuỗi và sau đó trở lại một lần nữa để làm toán. – pr1001

0

Điều đầu tiên bạn nên làm là xả cập nhật đầu tiên bằng cách kiểm tra các dấu thời gian của bản cập nhật đầu tiên bạn nhận được từ người quản lý vị trí, nó thường lưu trữ vị trí đã biết cuối cùng. Thứ hai nhớ độ chính xác, các giá trị ban đầu mà bạn sẽ nhận được luôn ở trong phạm vi rộng.

Các vấn đề liên quan