提问人:wiswasi 提问时间:10/6/2023 更新时间:10/7/2023 访问量:106
度/秒到轴角
Degrees/sec to axis-angle
问:
我有一张以度/秒(X、Y、Z)为单位的陀螺仪读数。我需要在 C 中将其转换为轴角格式(X、Y、Z、THETA)。 这是我想出的:
void gyroToAxisAngle(double gyro[3], double axis_angle[4]) {
double gyroRad[3];
// Convert gyro values from degrees per second to radians per second
gyroRad[0] = gyro[0] * M_PI / 180.0;
gyroRad[1] = gyro[1] * M_PI / 180.0;
gyroRad[2] = gyro[2] * M_PI / 180.0;
// Calculate the angular velocity magnitude
double gyroMagnitude = sqrt(gyroRad[0] * gyroRad[0] + gyroRad[1] * gyroRad[1] + gyroRad[2] * gyroRad[2]);
// Calculate the axis of rotation
axis_angle[0] = gyroRad[0] / gyroMagnitude;
axis_angle[1] = gyroRad[1] / gyroMagnitude;
axis_angle[2] = gyroRad[2] / gyroMagnitude;
// Calculate the rotation angle (theta)
axis_angle[3] = gyroMagnitude;
}
让我们以这些陀螺仪值为例,结果值为 , 。{-22.767, 145.174, -47.1}
XYZ: (-0.147539, 0.940781, -0.305225)
Theta: 2.693255
谁能确认我是否正确转换,或者是否有更准确的转换方式?谢谢!
答:
0赞
chux - Reinstate Monica
10/6/2023
#1
是否有更准确的转换方式?
除以 0.0 @ 激
当所有输入为零(甚至所有输入小于幅度)时,代码将除以 0.0。sqrt(DBL_TRUE_MIN)
在这种情况下,需要一些替代代码。
if (gyroMagnitude == 0.0) {
// TDB code needed to handle all tiny cases.
} else {
// The usual
}
溢出
尽管 OP 的值不太可能,但代码可能希望更好地处理溢出。在这种情况下,可以使用 TBD 替代代码或更广泛的类型。
再多看几点
是的,使用更宽的数学(当比 时更宽)和 。long double
double
FLT_EVAL_METHOD < 2
也许不是 OP 所寻求的几点改进,但它是:
// long double constant - degrees to radians
#defined D2R (3.1415926535897932384626433832795L / 180)
void gyroToAxisAngle(const double gyro[3], double axis_angle[4]) {
// Convert gyro values from degrees per second to radians per second
long double gr0 = gyro[0] * D2R;
long double gr1 = gyro[1] * D2R;
long double gr2 = gyro[2] * D2R;
// Calculate the angular velocity magnitude
long double gyroMagnitude = sqrtl(gr0*gr0 + gr1*gr1 + gr2*gr2);
// Calculate the axis of rotation
axis_angle[0] = (double) (gr0 / gyroMagnitude);
axis_angle[1] = (double) (gr1 / gyroMagnitude);
axis_angle[2] = (double) (gr2 / gyroMagnitude);
// Calculate the rotation angle (theta)
axis_angle[3] = (double) gyroMagnitude;
}
我估计 OP 的结果会好 1 或 2 ULP。
使用(或)打印,而不是用于评估准确性。"%.17g"
"%a"
"%f"
[编辑]
由于都是归一化的角度,因此失去了度/弧度单位,因此无需先转换为弧度。这种不必要的转换会失去一点准确性,并且是可以避免的工作。只需要度数到弧度的转换。axis_angle[0 to 2]
axis_angle[3]
#include <float.h>
#include <math.h>
// Rather than a * pi / 180, insure only 1 operation.
#define DEGS2RADS(a) ((a) * (3.1415926535897932384626433832795/180))
void gyroToAxisAngle(const double gyro[3], double axis_angle[4]) {
// Conversion to radians is not needed as code is forming a normalized vector.
// Conversion slightly increases accuracy.
// Calculate the angular velocity magnitude
double gyroMagnitude = sqrt(
gyro[0] * gyro[0] + gyro[1] * gyro[1] + gyro[2] * gyro[2]);
// See below code to handle extremes,
// or just handle the tiny value case with your own code
if (gyroMagnitude == 0.0) {
// TBD Code to handle tiny or the zero case.
return;
}
axis_angle[0] = gyro[0] / gyroMagnitude;
axis_angle[1] = gyro[1] / gyroMagnitude;
axis_angle[2] = gyro[2] / gyroMagnitude;
axis_angle[3] = DEGS2RADS(gyroMagnitude);
}
要处理极端情况:
// If all the gyroRad are small, scale them up, centered about exponent = 0
#define SCALE (-DBL_MIN_EXP*3/4)
if (gyroMagnitude < DBL_MIN) {
// Scaled up versions of gyroRad_scaled[]
double g_x[3];
g_x[0] = scalbn(gyro[0], SCALE);
g_x[1] = scalbn(gyro[1], SCALE);
g_x[2] = scalbn(gyro[2], SCALE);
gyroMagnitude = sqrt(g_x[0] * g_x[0] + g_x[1] * g_x[1] + g_x[2] * g_x[2]);
// All gryo[] are zeros.
if (gyroMagnitude == 0.0) {
// Make all same magnitude
double mag = 1.0 / sqrt(3.0);
axis_angle[0] = axis_angle[1] = axis_angle[2] = axis_angle[3] = 0.0;
return;
}
gyroMagnitude = scalbn(gyroMagnitude, -SCALE);
} else if (gyroMagnitude > DBL_MAX) {
// TBD Code
return;
}
评论
0赞
chux - Reinstate Monica
10/6/2023
注意:如果 OP 通常转换正确,则无法确认,
1赞
Ian Abbott
10/6/2023
gyro[]
包含角速度,而不是角度,因此范围缩小是不合适的。fmod
0赞
chux - Reinstate Monica
10/7/2023
@IanAbbott 同意范围缩小不适合角速度。答案已修改。
0赞
Ian Abbott
10/7/2023
您的特殊情况使向量过大。它应该是一个单位向量。我不认为方向太重要,但如果你想保留这些东西以获得 8 个方向的选择,用结果替换就可以了。if (gyroMagnitude == 0.0)
copysign
1.0
sqrt(3)/3
0赞
Ian Abbott
10/7/2023
同样,对于您的特殊情况,难道不应该使用符号 from 而不是相反的方式分配给 吗?axis_angle[x]
gyroRad[x]
上一个:计算先喝牛奶的 N 人准备谷物碗的方法数量(算法请求)
下一个:欧拉旋转角到轴角?
评论
sqrt(DBL_TRUE_MIN)