Electronic – STM32 NaN value for floating point operations on global variables

armcfloating pointgccstm32

I am trying to implement a simple Odometry computation loop. Which is being run in a while loop. Following is the code:

double dx=0,dy=0,dw=0;
double v,w;

void computeOdom(){

    uint32_t ticknow=ticksms;  //global timer variable (gives current ticks in milliseconds)

    v=0.0;
    w=0.0;

    double dt = (ticknow - tickprev)/1000.0; //time elapsed since last odom update
    double res = (double)ENCODER_RESOLUTION; //Encoder Resolution ticks per revolution
    double leftvel = (double) ((((Left.position)/res) * 2 * M_PI))/dt; // Angular velocity of left wheel (rad/s)

    Left.position=0;
    double rightvel=(((double)Right.position)/ENCODER_RESOLUTION)* 2 * M_PI/dt; //Angular velocity of right wheel (rad/s)

    Right.position=0;

    double r_L= 0.260/2;
    double r_R= 0.260/2;

    v += (r_L/2.0) * leftvel; //Linear velocity of the robot
    v += (r_R/2.0) * rightvel;
    w += (r_R/0.610) * rightvel; //Angular velocity of the robot
    w -= (r_L/0.610) * leftvel;
    double tempx=0.0,tempy=0.0,tempz=0.0;

    if(!(w==0.0f)){
        dx += (double)(dt * v * arm_cos_f32(dw + dt*(w/2.0))); //The line where dx becomes NaN
        dy += (double)(dt * v * arm_sin_f32(dw + dt*(w/2.0))); //The line where dy becomes NaN
        dw += (dt * w);
    }
    else{
        dx += (double)(dt * v * arm_cos_f32(dw));
        dy += (double)(dt * v * arm_sin_f32(dw));
    }

    tickprev = ticknow;

    printf("prev_x: %f\n\r",dx);
}

I have debugged the code with GDB. I have checked for any exceptions that are being raised but everything looks fine. And if I change the code to this:

dx = (double)(dt * v * arm_cos_f32(dw + dt*(w/2.0))); 
dy = (double)(dt * v * arm_sin_f32(dw + dt*(w/2.0)));

The NaN goes away. I have tried using temporary local variables. I have checked the cos and sin functions by executing them on local variables and they work as intended. No issues there. Only when I want to increment the global variables, the issue arises. dx, dy and dw are persistent global variables which keep track of the position.

This is the version of arm-gcc I am using.

arm-none-eabi-gcc 5.4.1 20160609 (release) [ARM/embedded-5-branch
revision 237715]

I am using STM32F429 discovery board with Arm-gcc toolchain and FPU has been enabled. Disabling the FPU has no effect whatsoever.

Any pointers or suggestions?

Best Answer

@MarkoBursic Thank you for pointing those out man. You know, actually i made so many changes in that tiny piece of code since yesterday that i started losing track of the idioticity :). Anyhow i have somehow managed to solve the problem. Bear with me for a while. using gdb i stepped through the code once again, checking each variable before and after every line of execution. leftvel was initially a nan(0x400000) when dt was zero since during the first iteration tickprev and ticknow were the same (0). Since leftvel and rightvel are local variables the nan values didnt stick through. And this nan value was getting multiplied to my global variables which are persistent. So i added this line :

if(isnan(leftvel) || isnan(rightvel))
    return;

Just before multiplying it with dx,dy and dw. Thank you for your suggestions @MarcoBursic @BenceKaulics