(VIRB) heading is static if speed = 0 in gps_metadata/160 even if camera is turning

EDIT: see test values/comparisons in my reply below.

I don't know if this is expected behaviour or a bug.

Here's partial output from gps_metadata/160 messages from a VIRB Ultra 30. "[XXXXX]" is just a coordinate counter, SPE = speed, HDG = heading for each gps_metadata message - this is just the raw data directly from the FIT file.

[46335] 5030s 775ms HDG: 20321, SPE: 468
[46336] 5030s 875ms HDG: 21102, SPE: 455
[46337] 5030s 975ms HDG: 21102, SPE: 0
[46338] 5031s  75ms HDG: 21102, SPE: 0
[46339] 5031s 175ms HDG: 21102, SPE: 0
[46340] 5031s 275ms HDG: 21102, SPE: 0
[46341] 5031s 375ms HDG: 21102, SPE: 0
[46342] 5031s 475ms HDG: 21102, SPE: 0
[46343] 5031s 575ms HDG: 21102, SPE: 0
[46344] 5031s 675ms HDG: 21102, SPE: 0
[46345] 5031s 775ms HDG: 21102, SPE: 0
[46346] 5031s 875ms HDG: 21102, SPE: 0
[46347] 5031s 975ms HDG: 21102, SPE: 0
[46348] 5032s  75ms HDG: 21102, SPE: 0
[46349] 5032s 175ms HDG: 21102, SPE: 0
[46350] 5032s 275ms HDG: 21102, SPE: 0
[46351] 5032s 375ms HDG: 21102, SPE: 0
[46352] 5032s 475ms HDG: 21102, SPE: 0
[46353] 5032s 575ms HDG: 21102, SPE: 0
[46354] 5032s 675ms HDG: 21102, SPE: 0
[46355] 5032s 775ms HDG: 21102, SPE: 0
[46356] 5032s 875ms HDG: 21102, SPE: 0
[46357] 5032s 975ms HDG: 21102, SPE: 0
[46358] 5033s  75ms HDG: 21102, SPE: 0
[46359] 5033s 175ms HDG: 21102, SPE: 0
[46360] 5033s 275ms HDG: 21102, SPE: 0
[46361] 5033s 375ms HDG: 21102, SPE: 0
[46362] 5033s 475ms HDG: 21102, SPE: 0
[46363] 5033s 575ms HDG: 21102, SPE: 0
[46364] 5033s 675ms HDG: 21102, SPE: 0
[46365] 5033s 775ms HDG: 21102, SPE: 0
[46366] 5033s 875ms HDG: 21102, SPE: 0
[46367] 5033s 975ms HDG: 21102, SPE: 0
[46368] 5034s  75ms HDG: 21102, SPE: 0
[46369] 5034s 175ms HDG: 32004, SPE: 427
[46370] 5034s 275ms HDG: 32414, SPE: 435
[46371] 5034s 375ms HDG: 32690, SPE: 442
[46372] 5034s 475ms HDG: 32784, SPE: 441

Whenever speed is 0, heading stops updating for gps_metadata. Looking at the corresponding video recording, the camera/wearer is immobile for these sections, but is very much turning around. What sensor logs heading in gps_metadata messages for VIRB Ultra 30?

Calibrated values for magnetometer_data/208 for the same time span seem to update continuously regardless of speed as expected (presuming I managed to get the calibration right...). I tried a quick atan2(y, x) for the first values in each calibrated array, which returns continuous values (if it can be checked that way, that is).

Does any one have any clues?

I need headings and hoped for the easy way out via the heading field in gps_metadata, but I may have to use magnetometer readings instead, which seems quite involved. I can easily get the calibrated values for each sensor, but presumably I would have to further translate calibrated magnetometer data using gyroscope values to make sure the magnetometer reading is parallel to the ground.

  • Did a little testing, for VIRB gps_metadata/160 messages, comparing "heading" (field 5) to the "velocity" (field 7), which is a vector [x, y, z] as opposed to the scalar "enhanced_speed" (field 4).

    Whenever enhanced_speed hits 0, heading/field 5 is static. But doing a rough angle from velocity x, y values seems closer to reality. A bit surprising that velocity still show a [low] displacement value when enhanced_speed is 0? Anyway, here are examples from the same FIT-file  (code after "->" can be pasted into the Julia repl, practical as an advanced terminal calculator!), with enhanced_speed = 0 then > 0.

    ENHANCED SPEED = 0
    
    // id:   4 enhanced_speed        : UINT32([0])
    // id:   5 heading               : UINT16([20443]) STATIC
    // id:   7 velocity              : SINT16([-5, -12, -2])
                               -> rad2deg(atan(-5/-12)) = 22.6198
    
    // id:   4 enhanced_speed        : UINT32([0])
    // id:   5 heading               : UINT16([20443]) STATIC
    // id:   7 velocity              : SINT16([-4, -12, -2])
                               -> rad2deg(atan(-4/-12)) = 18.4349
    
    // id:   4 enhanced_speed        : UINT32([0])
    // id:   5 heading               : UINT16([20443]) STATIC
    // id:   7 velocity              : SINT16([-4, -11, -2])
                               -> rad2deg(atan(-4/-11)) = 19.9831
    
    ENHANCED SPEED > 0
    
    // id:   4 enhanced_speed        : UINT32([523]) 
    // id:   5 heading               : UINT16([20606]) 
    // id:   7 velocity              : SINT16([-22, -46, -2])
                                -> rad2deg(atan(-22/-46)) = 25.5560
    
    // id:   4 enhanced_speed        : UINT32([487]) 
    // id:   5 heading               : UINT16([19301]) 
    // id:   7 velocity              : SINT16([-10, -47, -2])
                               -> rad2deg(atan(-10/-47)) = 12.0115
    
    // id:   4 enhanced_speed        : UINT32([413]) 
    // id:   5 heading               : UINT16([28277]) 
    // id:   7 velocity              : SINT16([-40, 9, -1])
                               -> rad2deg(atan(-40/9)) = -77.3196
    

    I'm a bit confused. Velocity seems to be the better indicator of actual heading here. Is there something I'm missing as to how the speed/velocity/heading values are derived and which sensor may be involved?

    Also trying the magnetometer readings at the moment, but I'm not quite there yet (have calibrated values, but need to test I've actually implemented the calibration correctly, right now it doesn't add up). 

  • The virb is a fascinating device with all the available sensor data.

    Only thing I can contribute to this is that I recently learned that GPS devices sometimes use the gps signal doppler-effect to calculate speed instead of relying on time between two lat/lon points, this is because it doesn't need a full lock onto satellite signals, just listens to the drift like a fire-truck siren racing by and seemingly changing tones even though it's the same.

    If a device isn't moving, and it is maybe using doppler-effect, maybe it can't also calculate heading/bearing?

    But if it is accelerator based, well then yeah maybe it's a bug.

  • Yes, it really does make me wonder where heading in gps_metadata is derived from. If the gyro or magnetometer are involved there shouldn't be an issue. I have continuous readings from those, and the magnetometer readings are not static around the same timespans.

    The doppler thing is pretty dope, by the way (had to to look it up).

  • It's disappointing that no other device saves the magnetic compass to the 1-second records though.

    Maybe bouncing on the wrist is too much for a watch or footpod to know which way it's oriented vs magnetic north but you'd think it's technically possible with some serious R&D, someone will do it eventually.

    It occurs to me that using Stryd's "air power" field and the lat/long between the last two points it is possible to calculate wind speed though. Not sure how wildly off the accuracy would be but maybe within a couple of mph

  • VIRB doesn't save heading to Record/20 either, only to gps_metadata (don't know how heading is derived, though). Other than the raw sensor values I'm currently trying to work with.