Datafield: Heading and direction to target. Strange CurrentHeading behavior.

I'm trying to develop a datafield where I have a pointer to a certain location, for this I try to determine my current heading adn the heading from current location to a target location.

I fetch my current heading in the compute(info) function:

function compute(info) {
heading_rad = info.currentHeading;

if( heading_rad < 0 ) { //convert to 0 to 2pi (0-360)
heading_rad = 2*Math.PI+heading_rad;
}
}


From what I understood this SHOULD get the heading based on gps if speed is high enough, but during running (12km/h) it was also influenced with how I held my watch. If I turned it 90 degrees (from havin my arm in front to my arm at my side) the heading returned differed greatly (but didn't seem to correspond to the 90 degrees?). But in general this seemed to fluctuate a lot!

Am I missing something here? (I read something about needing to call Activity.getInfo() to get the current info, but I assume this is done before compute() actually?

The heading between a start and target is calculated using:

function getHeadingRadNormal(lat1, lon1, lat2, lon2){
var dLong = lon2 - lon1;
var y = Math.sin(dLong) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLong);
var brng = Math.atan2(y, x); //-pi to po
if(brng<0){
brng = 2*Math.PI+brng; //0 to 360
}
return brng;
}


And that seems to work fine (this is constant value and seems to be correct), when displaying the indicator on the watch I simply subtract my current heading from the target point heading: brng-heading_rad but that is messed up by the weird currentHeading

Is it better just to use the last 2 latlon points? (Or a larger buffer, can imagine just the last 2 points also gives a large uncertainty).
  • I'm trying to develop a datafield where I have a pointer to a certain location, for this I try to determine my current heading adn the heading from current location to a target location.

    I fetch my current heading in the compute(info) function:

    function compute(info) {
    heading_rad = info.currentHeading;

    if( heading_rad < 0 ) { //convert to 0 to 2pi (0-360)
    heading_rad = 2*Math.PI+heading_rad;
    }
    }


    From what I understood this SHOULD get the heading based on gps if speed is high enough, but during running (12km/h) it was also influenced with how I held my watch. If I turned it 90 degrees (from havin my arm in front to my arm at my side) the heading returned differed greatly (but didn't seem to correspond to the 90 degrees?). But in general this seemed to fluctuate a lot!

    Am I missing something here? (I read something about needing to call Activity.getInfo() to get the current info, but I assume this is done before compute() actually?

    for this, the "info" you get passed in compute() is Activity.Info. No need to get it, as you already have it
    The heading between a start and target is calculated using:

    function getHeadingRadNormal(lat1, lon1, lat2, lon2){
    var dLong = lon2 - lon1;
    var y = Math.sin(dLong) * Math.cos(lat2);
    var x = Math.cos(lat1)*Math.sin(lat2) - Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLong);
    var brng = Math.atan2(y, x); //-pi to po
    if(brng<0){
    brng = 2*Math.PI+brng; //0 to 360
    }
    return brng;
    }


    And that seems to work fine (this is constant value and seems to be correct), when displaying the indicator on the watch I simply subtract my current heading from the target point heading: brng-heading_rad but that is messed up by the weird currentHeading

    Is it better just to use the last 2 latlon points? (Or a larger buffer, can imagine just the last 2 points also gives a large uncertainty).


    I do it based on lat/lon for the two points (and use that to also compute the "as the crow flies" distance). Heading can be interesting, but what I see is it's only really accurate when you are holding your arm so that the top of the watch is pointing in the direction you are going.

    On devices with a magnetic compass, it's never been completely clear to me when heading is based on that vs GPS (speed, etc). I take it you are on a watch with a HW compass, and not one that only uses GPS.

    In my Hike/Hike2 apps I use a few large arrays for lat/lon. By default I save lat/lon once a minute to draw a chart of the walk/hike, and a second where I have the waypoints, and user their lat/lon and the current lat/lon to get the distance and direction to each one. I cheat for heading though and just use the 8 compass points.
  • Thanks for the feedback...

    I know the info object from compute is an Activity.info object, and I assume it's always the most recent one (the reason for having the call getInfo() otherwise...)

    But yeahg, I do have a watch with hw compass... Guess just getting the heading from the positions themselves is more failsafe here. Strange as I also have a gps/compass widget which does get the proper heading, that one is retrieved from Position.info though, guess that differs enough to make that work but not this one ;)

    Ah well, we live and we learn!

    Btw, is it correct that in the SDK (emulator) the heading is still always showing 0? I read something in this thread that it would be fixed with the latest sdk, but not here (both present in 2.3.0beta as in 2.2.5). THis is (also) when playing back a fit file...
  • We had a reported issue about the heading displaying 0 in the sim that was investigated around the time of the 2.2.1 SDK release. The sim will initially display 0 until some heading data is present. I'm using the 2.3.0 beta SDK at the moment, and I receive heading data within our PositionSample app while simulating FIT data in the CIQ simulator. If you always see a heading of 0 in that sample (since I know it should work), then there may be a bug that requires more investigation.
  • We had a reported issue about the heading displaying 0 in the sim that was investigated around the time of the 2.2.1 SDK release. The sim will initially display 0 until some heading data is present. I'm using the 2.3.0 beta SDK at the moment, and I receive heading data within our PositionSample app while simulating FIT data in the CIQ simulator. If you always see a heading of 0 in that sample (since I know it should work), then there may be a bug that requires more investigation.


    Thanks for the reply, indeed it does work for the PositionSample but as you mentioned that is an app and it uses the Position.Info

    In my case it is a DataField which uses the Activity.Info, there I keep getting 0.000 even after letting it run for a few minutes (and this is when playing back a fit file and when simulation fit data). I would expect it also to show a proper heading value though.
  • I've seen differences when using simulated data vs playing back a .fit. If I recall, some .fits work and some don't. (well, they all work, but some always get "0" which is north) (Maybe due to being recorded with 1sec vs smart? I've never really looked into the "why")

    I reported a bug a while back where distance is wrong when playing back a .fit too:

    https://forums.garmin.com/showthread.php?371390-elapsedDistance-incorrect-when-playing-back-a-fit-in-the-sim

    More of a heads up than anything, and something else to watch for.
  • Ah, good to know! Thanks for the headsup... Just checked and speed IS displayed btw, but no heading.

    Also starting to realize how tough it can be to keep memory usage within bounds (or how easy it is to go over it). And then mainly with the datafields for older (connectiq 1) devices (below 16kb) ;)
  • There are a few tricks with 1.x DFs. Like don't use layouts if you can (there's a bit of a memory impact), and avoid things like custom fonts.

    You may want to look as doing things with resource overrides, including build file excludes. (don't even include the code that can't be used on 1.x devices, for example)