C ++中的连续角度(matlab中的eq unwrap函数)

时间:2013-03-26 10:13:20

标签: c++ angle

我想这并不难,但我已经坚持了一段时间了。

我有一个可以旋转两个方向的关节。传感器给出了-pi和+ pi范围内关节的角度。

我想在-infinity和+ infinity范围内转换它。意味着如果关节永远顺时针旋转,角度将从0开始,然后增加到无穷大。 在matlab中,unwrap函数非常好用:

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

注意:假设角度没有大跳跃,肯定没有优于PI。

注意:在问之前我真的很努力......

谢谢!

3 个答案:

答案 0 :(得分:3)

经过一番工作,想出了这个。似乎工作正常。

//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));
}

我使用了这篇文章中的代码: Dealing with Angle Wrap in c++ code

答案 1 :(得分:3)

假设输入角度之间的绝对差值小于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;
}

如果需要打开数组,可以使用此例程:

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;
    }
}

答案 2 :(得分:2)

// 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);
}

这很有效。