Context: I'm creating a map-replanner for a robot in C, it should add obstacles within the environment to the map depending on which IR-sensors are getting high readings.
For this i need to check how the robot is positioned IRL vs in the internal map (pointing north). But for some reason, i sometimes get negative values in the conversion. Any ideas what i'm doing wrong?
There should never be any negative values. The allowed values should lie between 0-360. As of now, i get negative values sometimes.
#define PI 3.14159265358979323846264338327950
#define DEG(x) (x*57.2957795130823208767981548141)
Code:
float currentRot = now.th; //current rotation-reading in RAD from function.
if(currentRot > PI){ //normalize values
currentRot = currentRot - 2 * PI;
}
if(currentRot < -PI){
currentRot = currentRot + 2 * PI;
}
currentRot = fmod(currentRot,PI*2); //convert into RAD-modular
currentRot = DEG(currentRot); //convert to degrees
Any ideas of what i'm doing wrong?
π cannot be exactly represented as a float
, so any mod-ding with fmod(currentRot,PI*2);
or comparing if(currentRot > PI){
may fail to provide the expected results for edge cases.
Note that currentRot = currentRot + 2 * PI;
is a (foat) + (double)
and the conversion to float
. The edges of this conversion are problem to avoid slight negative results. Best to avoid mixing float
and double
math for this sensitive conversion.
Even with the good comment of @M Oehm, the inexactness PI
and mixing float/double
math can result in negative currentRot
.
Instead, convert radians to degrees first and then mod.
float RadianToDegree(float r);
float d = (float)(PI/180.0) * r;
d = fmodf(d, 360.0f);
if (d < 0.0f) d += 360.0f;
return d;
}
The result will be [0.0 - 360.0] inclusive.
Mod-ding by 360 can be expected to incur to no round-off error.
Use fmodf()
with float
and fmod()
with double
to avoid unnecessary conversions.
On a higher level note, the goal of "The allowed values should lie between 0-360" sacrifice precision. Consider a primary range of between -180 - +180.