约束俯仰、偏航和卷 [英] Constrain pitch, yaw, & roll
问题描述
我有一个表示为四元数的旋转,并试图限制俯仰、偏航和滚动轴.我试着这样做:
I've a rotation represented as a quaternion and am trying to constrain the pitch, yaw, & roll axes. I tried doing so thusly:
public struct Orientation
{
public Vector3 up, forward;
public Orientation(Vector3 up, Vector3 forward)
{
this.up = up;
this.forward = forward;
}
}
public static Orientation[] orientations = new Orientation[3]
{
new Orientation(Vector3.right, Vector3.up),
new Orientation(Vector3.up, Vector3.forward),
new Orientation(Vector3.forward, Vector3.right)
};
public enum Axis
{
Pitch,
Yaw,
Roll
};
private Vector3 ConstrainAxis(Vector3 vector, Axis axis, float from, float to)
{
Orientation orientation = orientations[(int)axis];
float theta = (to - from) * 0.5F;
Vector3 cons = Quaternion.AngleAxis(from + theta, orientation.up) * orientation.forward;
Vector3 proj = Vector3.ProjectOnPlane(vector, orientation.up);
return ConstrainVector(cons.normalized, proj.normalized, theta);
}
private Vector3 ConstrainVector(Vector3 from, Vector3 to, float angle)
{
float theta = Mathf.Abs(angle / Vector3.Angle(from, to));
if(theta < 1.0F)
{
return Vector3.Slerp(from, to, theta);
}
return to;
}
结果证明这不过是一种限制欧拉角表示的各个分量的过于复杂的方法,这两者都受到奇怪的抖动问题的影响(与万向节锁定有关?).
Which turned out to be nothing more than an over-complicated way of constraining the individual components of an euler angle representation, of which both are subject to a strange jittering issue (gimbal lock related?).
约束这些轴的最佳方法是什么?
What is the best approach to constraining these axes?
推荐答案
对于关节约束,通常的做法是使用swing twin";参数化.将当前旋转表示为摆动扭曲"对于四元数,有很好的分解http://www.alinenormoyle.com/weblog/?p=726
For joint constraints it is common practice to use "swing twist" parametrization. To represent current rotation as "swing twist" for quaternions, theare are good decomposition http://www.alinenormoyle.com/weblog/?p=726
swing"的约束和扭曲"可以用四元数来完成.
And constraint for "swing" and "twist" can be done with quaternions.
如果我们想将swing限制在+-30度,伪代码如下
if we want to constrain swing to +-30 degrees , pseudocode looks like
Quaternion swing;
const double maxMagnitude = sin(0.5 * toRad(30));
const double maxMagnitudeW = sqrt(1.0 - maxMagnitude * maxMagnitude);
if (swing.vec().normSqr() > maxMagnitude * maxMagnitude)
{
swing.vec() = swing.vec().normalized() * maxMagnitude;
swing.w() = maxMagnitudeW;
}
这篇关于约束俯仰、偏航和卷的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!