根据四元数确定调整方向所需的 angular 速度
Determining angular velocity required to adjust orientation based on Quaternions
问题:
我有一个 object 的 3D space 存在于给定方向。我需要将 object 重新定位到新的方向。我目前将方向表示为四元数,尽管这不是绝对必要的。
我基本上需要确定将 body 定向到所需方向所需的 angular 速度。
我目前正在使用的内容如下所示:
伪代码:
// 4x4 Matrix containing rotation and translation
Matrix4 currentTransform = GetTransform();
// Grab the 3x3 matrix containing orientation only
Matrix3 currentOrientMtx = currentTransform.Get3x3();
// Build a quat based on the rotation matrix
Quaternion currentOrientation(currentOrientMtx);
currentOrientation.Normalize();
// Build a new matrix describing our desired orientation
Vector3f zAxis = desiredForward;
Vector3f yAxis = desiredUp;
Vector3f xAxis = yAxis.Cross(zAxis);
Matrix3 desiredOrientMtx(xAxis, yAxis, zAxis);
// Build a quat from our desired roation matrix
Quaternion desiredOrientation(desiredOrientMtx);
desiredOrientation.Normalize();
// Slerp from our current orientation to the new orientation based on our turn rate and time delta
Quaternion slerpedQuat = currentOrientation.Slerp(desiredOrientation, turnRate * deltaTime);
// Determine the axis and angle of rotation
Vector3f rotationAxis = slerpedQuat.GetAxis();
float rotationAngle = slerpedQuat.GetAngle();
// Determine angular displacement and angular velocity
Vector3f angularDisplacement = rotationAxis * rotationAngle;
Vector3f angularVelocity = angularDisplacement / deltaTime;
SetAngularVelocity(angularVelocity);
这基本上只会让我的 object 旋转到被遗忘的地步。我已经验证了我通过轴构建的 desiredOrientMtx 确实是正确的最终旋转变换。我觉得我在这里遗漏了一些愚蠢的东西。
想法?
要计算 angular 速度,您的 turnRate
已经提供了大小 (rads/sec),因此您真正需要的只是旋转轴。这是 GetAxis( B * Inverse(A) )
给出的。相同数量的 GetAngle
将给出两者之间行进的总角度。有关详细说明,请参阅 'Difference' between two quaternions。
SetAngularVelocity( Normalize( GetAxis( B * Inverse(A)) ) * turnRate )
您需要在某个时刻(当您到达目标方向时)将 angular 速度设置为 0。一种方法是使用 quaternion distance。另一种更简单的方法是检查所花费的时间。最后,您可以检查两个 quats 之间的角度(如上所述)并检查它是否接近 0。
float totalAngle = GetAngle( Normalize( endingPose * Inverse( startingPose ) ) );
if( fabs( totalAngle ) > 0.0001 ) // some epsilon
{
// your setting angular velocity code here
SetAngularVelocity(angularVelocity);
}
else
{
SetAngularVelocity( Vector3f(0) );
// Maybe, if you want high accuracy, call SetTransform here too
}
但是,说真的,我不明白您为什么不充分利用 Slerp
。不用依赖物理积分器(这可能不精确)和知道你何时到达目的地(这有点尴尬),你可以逐帧移动对象,因为你知道运动。
Quaternion startingPose;
Quaternion endingPose;
// As discussed earlier...
Quaternion totalAngle = Quaternion.AngleBetween( startingPose, endingPose );
// t is set to 0 whenever you start a new motion
t += deltaT;
float howFarIn = (turnRate * t) / totalAngle;
SetCurrentTransform( startingPose.Slerp( endingPose, howFarIn ) );
有关这方面的一些讨论,请参阅 Smooth rotation with quaternions。
问题:
我有一个 object 的 3D space 存在于给定方向。我需要将 object 重新定位到新的方向。我目前将方向表示为四元数,尽管这不是绝对必要的。
我基本上需要确定将 body 定向到所需方向所需的 angular 速度。
我目前正在使用的内容如下所示:
伪代码:
// 4x4 Matrix containing rotation and translation
Matrix4 currentTransform = GetTransform();
// Grab the 3x3 matrix containing orientation only
Matrix3 currentOrientMtx = currentTransform.Get3x3();
// Build a quat based on the rotation matrix
Quaternion currentOrientation(currentOrientMtx);
currentOrientation.Normalize();
// Build a new matrix describing our desired orientation
Vector3f zAxis = desiredForward;
Vector3f yAxis = desiredUp;
Vector3f xAxis = yAxis.Cross(zAxis);
Matrix3 desiredOrientMtx(xAxis, yAxis, zAxis);
// Build a quat from our desired roation matrix
Quaternion desiredOrientation(desiredOrientMtx);
desiredOrientation.Normalize();
// Slerp from our current orientation to the new orientation based on our turn rate and time delta
Quaternion slerpedQuat = currentOrientation.Slerp(desiredOrientation, turnRate * deltaTime);
// Determine the axis and angle of rotation
Vector3f rotationAxis = slerpedQuat.GetAxis();
float rotationAngle = slerpedQuat.GetAngle();
// Determine angular displacement and angular velocity
Vector3f angularDisplacement = rotationAxis * rotationAngle;
Vector3f angularVelocity = angularDisplacement / deltaTime;
SetAngularVelocity(angularVelocity);
这基本上只会让我的 object 旋转到被遗忘的地步。我已经验证了我通过轴构建的 desiredOrientMtx 确实是正确的最终旋转变换。我觉得我在这里遗漏了一些愚蠢的东西。
想法?
要计算 angular 速度,您的 turnRate
已经提供了大小 (rads/sec),因此您真正需要的只是旋转轴。这是 GetAxis( B * Inverse(A) )
给出的。相同数量的 GetAngle
将给出两者之间行进的总角度。有关详细说明,请参阅 'Difference' between two quaternions。
SetAngularVelocity( Normalize( GetAxis( B * Inverse(A)) ) * turnRate )
您需要在某个时刻(当您到达目标方向时)将 angular 速度设置为 0。一种方法是使用 quaternion distance。另一种更简单的方法是检查所花费的时间。最后,您可以检查两个 quats 之间的角度(如上所述)并检查它是否接近 0。
float totalAngle = GetAngle( Normalize( endingPose * Inverse( startingPose ) ) );
if( fabs( totalAngle ) > 0.0001 ) // some epsilon
{
// your setting angular velocity code here
SetAngularVelocity(angularVelocity);
}
else
{
SetAngularVelocity( Vector3f(0) );
// Maybe, if you want high accuracy, call SetTransform here too
}
但是,说真的,我不明白您为什么不充分利用 Slerp
。不用依赖物理积分器(这可能不精确)和知道你何时到达目的地(这有点尴尬),你可以逐帧移动对象,因为你知道运动。
Quaternion startingPose;
Quaternion endingPose;
// As discussed earlier...
Quaternion totalAngle = Quaternion.AngleBetween( startingPose, endingPose );
// t is set to 0 whenever you start a new motion
t += deltaT;
float howFarIn = (turnRate * t) / totalAngle;
SetCurrentTransform( startingPose.Slerp( endingPose, howFarIn ) );
有关这方面的一些讨论,请参阅 Smooth rotation with quaternions。