Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continous angles in C++ (eq unwrap function in matlab)

Tags:

c++

angle

I guess it is not that hard, but I have been stuck on that one for a while.

I have a joint that can rotate both direction. A sensor gives me the angle of the joint in the range -pi and +pi.

I would like to convert it in the range -infinity and +infinity. Meaning that if for example the joint rotate clockwise forever, the angle would start at 0 and then increase to infinity. In matlab, the unwrap function does that very well:

newAngle = unwrap([previousAngle newAngle]);
previousAngle = newAngle;

Note: it is assumed the angle does not make big jump, nothing superior to PI for sure.

Note: I really looked hard before asking ...

Thanks !

like image 590
Vince Avatar asked Mar 26 '13 10:03

Vince


People also ask

How do you unwrap an angle in Matlab?

Q = unwrap( P ) unwraps the radian phase angles in a vector P . Whenever the jump between consecutive angles is greater than or equal to π radians, unwrap shifts the angles by adding multiples of ±2π until the jump is less than π. If P is a matrix, unwrap operates columnwise.

What is unwrap phase?

Phase unwrap or unwrap is a process often used to reconstruct a signal's original phase. Unwrap algorithms add appropriate multiples of 2π to each phase input to restore original phase values, as illustrated in the diagram. For more information on the unwrap algorithm used by this block, see Unwrap Method.

How do you create a phase angle in Matlab?

Description. theta = angle( z ) returns the phase angle in the interval [-π,π] for each element of a complex array z . The angles in theta are such that z = abs(z). *exp(i*theta) .


3 Answers

// wrap to [-pi,pi]
inline double angle_norm(double x)
{
    x = fmod(x + M_PI, M_2PI);
    if (x < 0)
        x += M_2PI;
    return x - M_PI;
}

double phase_unwrap(double prev, double now)
{
    return prev + angle_norm(now - prev);
}

This works.

like image 70
MujjinGun Avatar answered Oct 19 '22 16:10

MujjinGun


After some work, came up with this. Seems to be working fine.

//Normalize to [-180,180):
inline double constrainAngle(double x){
    x = fmod(x + M_PI,M_2PI);
    if (x < 0)
        x += M_2PI;
    return x - M_PI;
}
// convert to [-360,360]
inline double angleConv(double angle){
    return fmod(constrainAngle(angle),M_2PI);
}
inline double angleDiff(double a,double b){
    double dif = fmod(b - a + M_PI,M_2PI);
    if (dif < 0)
        dif += M_2PI;
    return dif - M_PI;
}
inline double unwrap(double previousAngle,double newAngle){
    return previousAngle - angleDiff(newAngle,angleConv(previousAngle));
}

I used code from this post: Dealing with Angle Wrap in c++ code

like image 4
Vince Avatar answered Oct 19 '22 15:10

Vince


The following function does the job, assuming the absolute difference between the input angles is less than 2*pi:

float unwrap(float previous_angle, float new_angle) {
    float d = new_angle - previous_angle;
    d = d > M_PI ? d - 2 * M_PI : (d < -M_PI ? d + 2 * M_PI : d);
    return previous_angle + d;
}

If you need to unwrap an array, you can use this routine:

void unwrap_array(float *in, float *out, int len) {
    out[0] = in[0];
    for (int i = 1; i < len; i++) {
        float d = in[i] - in[i-1];
        d = d > M_PI ? d - 2 * M_PI : (d < -M_PI ? d + 2 * M_PI : d);
        out[i] = out[i-1] + d;
    }
}
like image 4
roeeb Avatar answered Oct 19 '22 16:10

roeeb