fix(assembly): use short-arc angle in validateNewPlacements (#338)
All checks were successful
Build and Test / build (pull_request) Successful in 30m5s
All checks were successful
Build and Test / build (pull_request) Successful in 30m5s
Rotation::evaluateVector() computes angle = 2*acos(w) which gives values in [0, 2*pi]. When the relative quaternion has w < 0 (opposite hemisphere), the angle exceeds pi even though q and -q represent the same rotation. This caused the validator to report ~350 degree 'flips' and reject valid solver output. Fix: map the angle to [0, pi] before comparing against the 91-degree threshold. This is the short-arc equivalent — the minimum rotation angle between two orientations regardless of quaternion sign convention.
This commit is contained in:
@@ -659,19 +659,26 @@ bool AssemblyObject::validateNewPlacements()
|
||||
// Get the relative rotation: how much did the part rotate?
|
||||
Base::Rotation relativeRot = newRot * oldRot.inverse();
|
||||
|
||||
// Get the angle of this rotation
|
||||
// Ensure we measure the short-arc angle. Rotation stores
|
||||
// angle = 2*acos(w) which gives [0, 2*pi]. When the
|
||||
// quaternion w component is negative (opposite hemisphere),
|
||||
// the angle exceeds pi even though q and -q represent the
|
||||
// same rotation. Map to [0, pi] for a correct comparison.
|
||||
Base::Vector3d axis;
|
||||
double angle;
|
||||
relativeRot.getRawValue(axis, angle);
|
||||
if (angle > M_PI) {
|
||||
angle = 2.0 * M_PI - angle;
|
||||
}
|
||||
|
||||
// If the part rotated more than 90 degrees, consider it a flip
|
||||
// Use 91 degrees to allow for small numerical errors
|
||||
constexpr double maxAngle = 91.0 * M_PI / 180.0;
|
||||
if (std::abs(angle) > maxAngle) {
|
||||
if (angle > maxAngle) {
|
||||
Base::Console().warning(
|
||||
"Assembly : Ignoring bad solve, part (%s) flipped orientation (%.1f degrees).\n",
|
||||
obj->getFullLabel(),
|
||||
std::abs(angle) * 180.0 / M_PI
|
||||
angle * 180.0 / M_PI
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user