Question

I'm translating some c++ code in relation to PMP for attitude controls and part of the code uses FLT_EPSILON.

The code does the following:

while (angle > ((float)M_PI+FLT_EPSILON))

M_PI is simple but I'm not sure what to with FLT_EPSILON. A google has told me:

This is the difference between 1 and the smallest floating point number of type float that is greater than 1. It's supposed to be no greater than 1E-5.

However other sources state values like 1.192092896e-07F.

I'm not 100% clear on why it's being used. I suspect it's to do with the granuality of float. So if someone could clarify what it is attempting to do in c++ and if this is a concern for javascript then that would be very helpful.

I'm not sure how javascript goes about handling internally stuff like these values so help would be appreciated.

As an FYI, the code I'm translating is as follows (sourced from QGroundControl, it's open source):

float limitAngleToPMPIf(float angle) {
    if (angle > -20*M_PI && angle < 20 * M_PI) {
        while (angle > ((float)M_PI + FLT_EPSILON)) {
            angle -= 2.0f * (float)M_PI;
        }

        while (angle <= -((float)M_PI + FLT_EPSILON)) {
            angle += 2.0f * (float)M_PI;
        }
    } else {
        // Approximate
        angle = fmodf(angle, (float)M_PI);
    }

    return angle;
}

--- edit ---

Just realised that fmodf isn't defined. Apparently it's a lib function and does the following:

The fmod() function computes the floating-point remainder of dividing x by y. The return value is x - n * y, where n is the quotient of x / y, rounded toward zero to an integer.

Was it helpful?

Solution

This code is attempting to keep angle within an interval around zero.

However, managing angles in this way is troublesome and requires considerable care. If it is not accompanied by documentation explaining what is being done, why, and the various errors and specifications that are involved, then it was done improperly.

It is impossible for this sort of angle reduction to keep accumulated changes accurately over a long sequence of changes, because M_PI is only an approximation to π. Therefore, this sort of reduction is generally only useful for aesthetic or interface effect. E.g., as some angle changes, reducing it can keep it from growing to a point where there may be large jumps in calculation results due to floating-point quantization or other calculation errors that would be annoying to a viewer. Thus, keeping the angle within an interval around zero makes the display look good, even though it diverges from what real physics would do over the long term.

The choice of FLT_EPSILON appears to be arbitrary. FLT_EPSILON is important for its representation of the fineness of the float format. However, at the magnitude of M_PI, the ULP (finest change) of a float is actually 2*FLT_EPSILON. Additionally, JavaScript performs the addition with double-precision arithmetic, and FLT_EPSILON is of no particular significance in this double format. I suspect the author simply chose FLT_EPSILON because it was a convenient “small” number. I expect the code would work just as well as if angle > M_PI had been written, without the embellishment, and (float) M_PI were changed to M_PI everywhere it appears. (The addition of FLT_EPSILON may have been intended to add some hysteresis to the system, so that it did not frequently toggle between values near π and values near –π. However, the criterion I suggest, angle > M_PI, also includes some of the same effect, albeit a smaller amount. That might not be apparent to somebody inexperienced with floating-point arithmetic.)

Also, it looks like angle = fmodf(angle, (float) M_PI); may be a bug, since this is reducing modulo M_PI rather than 2*M_PI, so it will add 180º to some angles, producing a completely incorrect result.

It is possible that replacing the entire function body with return fmod(angle, 2*M_PI); would work satisfactorily.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top