The Same Quaternion But .angleTo Self Is Not Zero

When I use the Quaternion.rotateTowards() to animate camera, like this:

    function moving(dt) {
      timer += dt
      q1.rotateTowards(q2, dt * turnRate * speed), 0, 1).applyQuaternion(q1)
      const currentAngle = q1.angleTo(q2)

      if (q1.angleTo(q2) === 0) {
        scope._movingCamera = null

But the q1.angleTo(q2) === 0 is always false.
The result of q1.angleTo(q2) is a very very small number, so I think it because of the number’s precision.

I write an unit test about this.

	QUnit.test('angleTo', (assert) => {
		const q = new Quaternion();
		q._x = -0.3011968357996212
		q._y = -0.20601814257707293
		q._z = -0.06682031825320903
		q._w = 0.9286398850479817

		assert.ok( q.angleTo( q ) === 0, 'Passed!' )

It is an issue with precision. The calculation of angleTo does 2*acos(x*x + y*y + z*z + w*w).

For the specific values of the quaternion, JavaScript gives:

so, (x*x+...+w*w) is 0.999…9, although it should be 1.

Generally, to safeguard against similar problems, avoid using == with floating point numbers that are results of calculations. Instead, check whether the numbers are close enough.


It was discussed at GitHub to add an additional epsilon parameter to certain math methods (e.g. equals()) but the main issue is agreeing on an appropriate default value. A typical candidate is Number.EPSILON however it does not work in all use cases since it might be too small. A higher value is also hard to pinpoint since you don’t want to pick a too large one. Epsilon values are mainly app specific so try to solve the issue like shown below:

if (q1.angleTo(q2) < Number.EPSILON ) {

If Number.EPSILON doesn’t work, pick whatever epsilon works for you.


Thank you for your prompt reply.
Yeah, finally, I use q1.equals(q2) to fix it. I just want to know whether q1 equals to q2.