adriangibbons / php-fit-file-analysis

A PHP class for analysing FIT files created by Garmin GPS devices
MIT License
126 stars 49 forks source link

Problem with some latitude fields? #51

Closed Fjeldfross closed 5 years ago

Fjeldfross commented 5 years ago

The first entries for position_lat and position_long in one of my FIT files are [1539031114] => -40.64575 and [1539031114] => 175.29212. Yes, I'm in New Zealand!

However, I have lap[start_position_lat] => 220.64569, lap[start_position_long] => 175.29196, lap[end_position_lat] => 220.86769, and lap[end_position_long] => 175.06788, and session[start_position_lat] => 220.64569, session[start_position_long] => 175.29196.

It looks as though the conversion for these lap[] and session[] fields isn't working correctly for negative latitudes. I need to subtract the lat values from 180 to get the correct -ve value. The conversion obviously works OK for the position_lat values.

Can anybody point to me to where this needs to be fixed (in function readDataRecords()) please??

Of course it may be my device, Lezyne Mega XL, but I also see the same problem with FIT files from a friend's device from a completely different manufacturer.

Thanks.

Fjeldfross

adriangibbons commented 5 years ago

Hey Bru :)

I'm in Australia and hadn't noticed any issues with my files from Garmin devices. Have a look at the Mountain-Biking demo - would be keen to know whether the lap info is out?

Please could you also see if when using Raw units (i.e. no conversion applied) the first lat/lon matches up with the start_position_lat and lon?

$pFFA = new adriangibbons\phpFITFileAnalysis('my_fit_file.fit', ['units' => 'raw']);

By default, the data is converted from semicircles, which you can read about here, to degrees. The formula for conversion is:

degrees = semicircles * ( 180 / 2^31 )

The same formula is applied whether the data is an array or not. Typically information in record fields is an array; and single values in lap and session fields. https://github.com/adriangibbons/php-fit-file-analysis/blob/99ab97bdc1bb2d45c129b6db849dcc16c03c617e/src/phpFITFileAnalysis.php#L1917 https://github.com/adriangibbons/php-fit-file-analysis/blob/99ab97bdc1bb2d45c129b6db849dcc16c03c617e/src/phpFITFileAnalysis.php#L1970 So laps/sessions are probably being being processed by line 1925 or 1978, depending if you are using statute or metric units. (Yes, I should probably put it in a function, but inline duplicated code seems to work much quicker in PHP where the same algorithm is followed many times over!)

If you want a quick and easy fix, you could add something along the lines of:

// subtract the lat values from 180 to get the correct -ve value
// replace lines 1925 and 1978 with all of the below
if ($field === 'start_position_lat') {  // probably end_position_lat too?
    $this->data_mesgs[$message][$field] = 180.0 - round($this->data_mesgs[$message][$field] * (180.0 / pow(2, 31)), 5);
} else {
    $this->data_mesgs[$message][$field] = round($this->data_mesgs[$message][$field] * (180.0 / pow(2, 31)), 5);
}

Hope this helps, please let me know the results of using raw units! đź‘Ť

Fjeldfross commented 5 years ago

Hello Adrian,

Thanks for your reply. I’ve dumped the mountain-bike.fit file using my FITDump program and also modified it to do a raw units dump as you suggest. This is what I get:

mountain-biking.fit Dumped using $pFFA = new adriangibbons\phpFITFileAnalysis($fileSpec);

[lap] => Array
    (
        [timestamp] => 1371880151
        [start_time] => 1371867999
        [start_position_lat] => 211.96493
        [start_position_long] => 116.10833
        [end_position_lat] => 211.96485
        [end_position_long] => 116.10694
        ...
    )

[session] => Array
    (
        [timestamp] => 1371880151
        [start_time] => 1371867999
        [start_position_lat] => 211.96493
        [start_position_long] => 116.10833
        [total_elapsed_time] => 6770.675
        [total_timer_time] => 6770.675
        [total_distance] => 20.53
        [nec_lat] => 211.95438
        [nec_long] => 116.14887
        [swc_lat] => 211.98905
        [swc_long] => 116.09891
        ...
   )

mountain-biking.fit RAW dump Dumped using $pFFA = new adriangibbons\phpFITFileAnalysis($fileSpec, ['units' => 'raw']);

[lap] => Array
    (
        [timestamp] => 1371880151
        [start_time] => 1371867999
        [start_position_lat] => -381356420
        [start_position_long] => 1385226349
        [end_position_lat] => -381355555
        [end_position_long] => 1385209747
        ...
    )

[session] => Array
    (
        [timestamp] => 1371880151
        [start_time] => 1371867999
        [start_position_lat] => -381356420
        [start_position_long] => 1385226349
        [total_elapsed_time] => 6770.675
        [total_timer_time] => 6770.675
        [total_distance] => 20525.4
        [total_cycles] => -1
        [nec_lat] => -381230560
        [nec_long] => 1385709972
        [swc_lat] => -381644180
        [swc_long] => 1385113968
        ...
   )

I guess you’re a bit east of Perth!

So, judging from the RAW dump it looks as though the latitudes are probably correct as they are negative. That implies that it’s the conversion that’s going wrong then. So I’ll go and dig into the code and see what I can come up with.

All the best,

Adrian


Dr. Adrian Lumsden 114 Rahui Road Otaki Kapiti Coast 5512 New Zealand

Mobile: +64 (22) 567 2403 Tel: NZ: +64 (4) 974 7683 \ UK: +44 (1870) 475001 = All of these reach me in New Zealand US: +1 (215) 279 8935 /


From: Adrian Gibbons [mailto:notifications@github.com] Sent: Tuesday, 11 December 2018 02:01 To: adriangibbons/php-fit-file-analysis Cc: Adrian Lumsden; Author Subject: Re: [adriangibbons/php-fit-file-analysis] Problem with some latitude fields? (#51)

Hey Bru :)

I'm in Australia and hadn't noticed any issues with my files from Garmin devices. Have a look at the Mountain-Biking demo - would be keen to know whether the lap info is out?

Please could you also see if when using Raw units (i.e. no conversion applied) the first lat/lon matches up with the start_position_lat and lon?

$pFFA = new adriangibbons\phpFITFileAnalysis('my_fit_file.fit', ['units' => 'raw']);

By default, the data is converted from semicircles, which you can read about here https://docs.microsoft.com/en-us/previous-versions/windows/embedded/cc510650(v=msdn.10) , to degrees. The formula for conversion is:

degrees = semicircles * ( 180 / 2^31 )

The same formula is applied whether the data is an array or not. Typically information in record fields is an array; and single values in lap and session fields. https://github.com/adriangibbons/php-fit-file-analysis/blob/99ab97bdc1bb2d45c129b6db849dcc16c03c617e/src/phpFITFileAnalysis.php#L1917 https://github.com/adriangibbons/php-fit-file-analysis/blob/99ab97bdc1bb2d45c129b6db849dcc16c03c617e/src/phpFITFileAnalysis.php#L1970 So laps/sessions are probably being being processed by line 1925 or 1978, depending if you are using statute or metric units. (Yes, I should probably put it in a function, but inline duplicated code seems to work much quicker in PHP where the same algorithm is followed many times over!)

If you want a quick and easy fix, you could add something along the lines of:

// subtract the lat values from 180 to get the correct -ve value

// replace lines 1925 and 1978 with all of the below

if ($field === 'start_position_lat') { // probably end_position_lat too?

$this->data_mesgs[$message][$field] = 180.0 - round($this->data_mesgs[$message][$field] * (180.0 / pow(2, 31)), 5);

} else {

$this->data_mesgs[$message][$field] = round($this->data_mesgs[$message][$field] * (180.0 / pow(2, 31)), 5);

}

Hope this helps, please let me know the results of using raw units! đź‘Ť

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/adriangibbons/php-fit-file-analysis/issues/51#issuecomment-445807001 , or mute the thread https://github.com/notifications/unsubscribe-auth/ABkIBBjvhbr9ZivrMWhTAYs-2ajj9kRRks5u3lsBgaJpZM4ZH4CC . https://github.com/notifications/beacon/ABkIBIXEWuemNFsJfKHGlMMMsQ7XCZAvks5u3lsBgaJpZM4ZH4CC.gif

Fjeldfross commented 5 years ago

I've done some exploring and have discovered a problem that doesn't seem to be anything to do with the php-fit-file-analysis code. In fact I haven't touched the php-fit-file-analysis code at all.

The original test that I did that was giving me strange latitude values was done with an executable image that I had build using RapidEXE (http://deneskellner.com/sw/rapidexe).

I modified my code to optionally support the 'units'=>'raw' and made the test above using an .exe as before.

Doing more testing I find that if I run the PHP file from the command line I get:

>> php Fitdump.php /lap test.fit
[lap] Array
(
    [timestamp] => 1535774092
    [start_time] => 1535762315
    [start_position_lat] => -40.76535
    [start_position_long] => 175.16942
    [end_position_lat] => -40.65072
    [end_position_long] => 175.25716

i.e. correct negative latitudes for NZ.

If I create an executable using RapidEXE I get:

>> FitDump /lap test.fit
[lap] Array
(
    [timestamp] => 1535774092
    [start_time] => 1535762315
    [start_position_lat] => 220.76535
    [start_position_long] => 175.16942
    [end_position_lat] => 220.65072
    [end_position_long] => 175.25716

i.e. incorrect values for latitude. That's really weird given that all of the latitude values in [position_lat] are negative and correct.

The same phpFITFileAnalysis.php file is used in both cases.

Any thoughts?

Fjeldfross

adriangibbons commented 5 years ago

Sounds like the problem lies with RapidEXE, which looks like quite an interesting utility - I may have a use for something like that in future!

My first thoughts are that perhaps it is something to do with the way it is handling floats. From the article I shared:

degrees = semicircles * ( 180 / 2^31 )

What do you get if you output the following, using both with RapidEXE and without?

$my_const = 180.0 / pow(2, 31);
var_dump($my_const);

$start_position_lat_semicircles = -381356420;
var_dump($start_position_lat_semicircles);

$start_position_lat_degrees = $start_position_lat_semicircles * $my_const;
var_dump($start_position_lat_degrees);
DenesKellner commented 5 years ago

Hi, I'm the author of RapidEXE and I'd like to help. Can you make a minimal php file to me that still produces this weird phenomenon? Also, which PHP version are you using with the compiler?

adriangibbons commented 5 years ago

Hi @DenesKellner - will need @Fjeldfross to supply. Adrian

Fjeldfross commented 5 years ago

Hello DĂ©nes, I did send you a message when I first came across this problem. I can't track the message down now. Anyway... I'd be happy to send you a copy of my code. It's not very large but you'd also need the code from this repo too. I could also send you a FIT file to play with. At the moment that's the best that I can do. I've been running flat out on other things and haven't had time to do even the test that Adrian suggested above. Would that help? I'm currently using PHP Version 5.6.23.

Fjeldfross.

DenesKellner commented 5 years ago

Hi Fjeldfross,

please do send all necessary files to me, I'm gonna take a look at it! Meanwhile, you might want to try it out using PHP 7.2 which is RapidEXE's default engine; I'm not expecting any difference but one can never know.

developer at deneskellner dot com is the way.

Fjeldfross commented 5 years ago

@adriangibbons

What do you get if you output the following, using both with RapidEXE and without?

$my_const = 180.0 / pow(2, 31); var_dump($my_const);

$start_position_lat_semicircles = -381356420; var_dump($start_position_lat_semicircles);

$start_position_lat_degrees = $start_position_lat_semicircles * $my_const;

So running your test with PHP Version 5.6.23:

FIT File Utilities>php AG_Test\AG_Test.php
float(8.3819031715393E-8)
int(-381356420)
float(-31.964925862849)

FIT File Utilities>AG_Test\AG_Test.exe
float(8.3819031715393E-8)
int(-381356420)
float(-31.964925862849)

I can't see a difference between the two.

All the best, Fjeldfross

Fjeldfross commented 5 years ago

@DenesKellner

I'll gather together the files and e-mail them to you. It'll probably be a couple of days.

Thank you.

All the best, Fjeldfross

Fjeldfross commented 5 years ago

@DenesKellner

I'v just e-mailed a package of files to you for you to explore. I hope that helps. I'm interested in what you find.

All the best, Fjeldfross

Fjeldfross commented 5 years ago

Oops. I didn't mean to close the issue. sorry.

DenesKellner commented 5 years ago

So, it turns out that by the time I had a chance to open the code samples, the issue has already been resolved; it was about PHP versions. I'm glad I didn't screw up any floating point numbers today :)

Also thanks for the improvement tips, @Fjeldfross !