Toybox.Activity.Info.offCourseDistance is always null when Off Course Warnings is off

According to the API documentation, the attribute offCourseDistance in class Toybox.Activity.Info contains the distance to the nearest point on the current course in meters. I have tested the value of this attribute with a simple data field with the following code in the compute method of the View class:

function compute(info) {
if (info != null and info has :offCourseDistance) {
if (info.offCourseDistance == null) {
return "null";
} else {
return info.offCourseDistance;
}
} else {
return "-";
}


Next, I have uploaded a course on my Garmin Edge 1030, and started riding it. The Off Course Warnings setting on the Edge is off.

While I am not riding off course, the simple data field shows null (which indicates that info.offCoursedistance is null).

When I am riding deliberately off course, the simple data field still shows null. At the same time the native data field Dist. to Next, however, shows the distance between my current location and the nearest point on the course. (This behavior of this native data field is not documented, but from experience I have learned that this is the case.) Therefore, the Edge has detected that I am indeed off course.

When I repeat this test with the Off Course Warnings setting switched on, info.offCoursedistance is still null when I am not riding off course, but some value is showing in my simple data field when I ride off course. This value, however, is sometimes null, and sometimes a numeric value, but never a value that is equal to the value in the native data field Dist. to Next.

This is not at all what I expected. I would expect info.offCoursedistance to have the following value:
  • null when I am not riding a course
  • 0 when I am riding a course, and I am not off course
  • The same value shown in native data field Dist. to Next when I am riding a course and I am off course

I would expect these values to be independent from the Off Course Warnings setting. Specifically, if Off Course Warnings is off, info.offCoursedistance should still have a value when I am riding off course. Switching on Off Course Warnings has undesired side effects (buzzes, pop-ups). And what is more, there is no way in Connect IQ to check the value of the Off Course Warnings setting.

Some additional information:
  • Garmin Edge 1030, firmware version 3.90
  • Code sample created with Eclipse IDE for Java Developers Version: Oxygen.3a Release (4.7.3a) and Connect IQ SDK 3.0.7
  • Yes it would just be nice for apps to be able to automatically match how Garmin does it. Especially if it's something that Garmin changes with firmware updates. The fact that you mentioned a user setting tells me it's less than optimal, because most users don't like to tweak things they don't have to.

    It's similar to how every dev has to implement their own %Grade formula since that's unavailable as a native field. Apparently some people take an altitude delta over a fixed distance, others use a fixed number of samples. Of course the exact distance or sample size varies. Maybe there's a user option for that. With Garmin %Grade field, you just get a number (whether you like it or not).
  • I agree. Ideally I want my app or data field to have the same look and feel and behavior as the native apps and data fields. I want my data field to display the same off course behavior as my Edge 1030. I do not want to do reverse engineering to obtain the value of the threshold that the Edge 1030 uses to decide whether it is off course, in order to be able to implement the same behavior in my app or data field. These thresholds may vary between devices, and even between firmware versions of devices. This makes it almost impossible to develop an app or data field with a 'native' look and feel and behavior for a range of different Garmin devices.
  • mweijs well, you will find that many things in CIQ are difficult to implement "just like native", without doing a lot of reverse-engineering, taking a lot of care to note device-specific behaviour and/or writing a lot of device-specific code. Sometimes I am not sure whether this is an intentional design decision, but it is what it is.
  • Even when I was on course, info.offCourseDistance was showing values ranging from 0.5 to 95, sometimes increasing, sometimes decreasing. The values seemed random to me, I could not make any sense of them. However, they were never 0, even though the map showed that I was right on course.


    My testing was on foot. If offCourseDistcance (OCD) showed say 30m, if I walked perpendicular to the course it would decrease nearing 0 than eventually start ascending when I crossed and started to move away in the other direction. This is exactly what I would expect.

    And when I had gone deliberately off course, info.offCourseDistance also showed non-null values greater than 0. Again, I could not make much sense of the values being shown. The values did not seem to represent, as far as I could see, the distance from my current location to the nearest point on the course path in a straight line.


    In your situation, are you also traveling parallel to the course? or are you traveling perpendicular to test it? My testing was perpendicular and I saw reasonable values. Perhaps it having parallel movement is causing the issue?


  • As Jim pointed out, GPS is inaccurate. So any field that represents the literal off course distance will probably always be non-zero, like Jim said. However, as Jim also pointed out, you probably don't get an alert unless your off course distance goes over some threshold.

    Yes, that's how it works (for the device to issue the warning).

    So maybe what needs to happen is there should be another field called isOffCourse, which represents whether the Garmin off-course alert algorithm thinks you are off-course.

    Yes, there's something missing.

    Making the off-course distance zero when it's below the threshold would provide that information. Small numbers aren't meaningful anyway (due to GPS variability).

    TL;DR, if the device doesn't think you're off course when you're only 5 metres off course, does the device need to show "5" in that field?

    No, it doesn't need to do that. Not showing the 5 is what the device does normally (outside of IQ).


    Keep in mind that the tracks are often aligned with the centerline of the roadway and cyclists are usually riding at the side of the road.

    The off-course warning needs a threshold because of that.
  • Making the off-course distance zero when it's below the threshold would provide that information. Small numbers aren't meaningful anyway (due to GPS variability).


    That was my follow-up suggestion in the same post you quoted, although I suggested null instead of 0.

    I have a feeling that Garmin wouldn't like changing the behaviour of offCourseDistance so that it suddenly becomes null or zero when the "real value" goes below a certain threshold, because that could:
    - break existing code
    - be confusing if you didn't read the docs
    - break some other use case

    As an analogy, when you are walking too slowly (pace greater than 59:59 per km/mi), the pace data field shows "--:--". However, the CIQ speed variable doesn't have a value of 0, it just has a small-ish value.

    IOW, I think the idea is that the numbers available through the SDK tend to represent reality (after some filtering) more closely than the activity data fields.

    I think the best compromise would be to provide an isOffCourse boolean variable (true/false) and let the developer decide what to do with that information. Of course, that lessens the chance that an older device will ever get that change....
  • In your situation, are you also traveling parallel to the course? or are you traveling perpendicular to test it? My testing was perpendicular and I saw reasonable values. Perhaps it having parallel movement is causing the issue?


    In this morning's test, when I deliberately went off course, I was moving perpendicular to the course.
  • That was my follow-up suggestion in the same post you quoted, although I suggested null instead of 0.


    Null means "no data" or "can't be determined".

    It shouldn't be use to represent having information.

  • Null means "no data" or "can't be determined".

    It shouldn't be use to represent having information.



    Null can also mean "not applicable". I do agree with you in principle, though.

    By the same token, "0" should not be used to represent "5" or "30", or whatever values lie below your threshold for being off course. What if someone wanted to calculate the average off course distance, for example? Hiding the true value of offCourseDistance by making it either null or 0 does them no favours.

    Similarly, even if the pace field is showing "--:--" when I'm moving real slow, I expect the internal speed variable to be greater than 0. Even if the speed field is rounded down to 0.0 when I'm moving at a snail's pace, I expect the internal speed variable to be non-zero as long as there's movement detected.

    Which is why I will return to my original suggestion of having a separate boolean variable isOffCourse. That way you get the additional information you wanted without losing any current information.

    I'm pretty sure it will never happen tho.

    Anyway, I don't really have any investment in this discussion, I just wanted to give my (next-to-worthless) opinion. I hope it gets resolved to everyone's satisfaction.
  • Null can also mean "not applicable". I do agree with you in principle, though..

    That's just another type of no data.

    By the same token, "0" should not be used to represent "5" or "30", or whatever values lie below your threshold for being off course. What if someone wanted to calculate the average off course distance, for example? Hiding the true value of offCourseDistance by making it either null or 0 does them no favours.

    With small differences, it's junk data. You are just taking averages of GPS variability. Why would anybody want to do this? It's not useful.

    As this feature works, one is only off-course when the difference exceeds the theshold.

    Not being exactly on the track isn't off course.

    If the current track point is obtainable, one could compute this junk oneself.

    Which is why I will return to my original suggestion of having a separate boolean variable isOffCourse. That way you get the additional information you wanted without losing any current informainformatio

    I'm pretty sure it will never happen tho.

    A Boolean flag makes sense. But that it will likely never happen means it's not really an option.

    Knowing that one is off course is much more useful than keeping track of junky small differences when on course.