Repository: sympy/sympy

Issue:
Quaternion.angle method might have a wrong definition
For an axis defined by the unit vector: $$\pmb e = e_x \pmb i + e_y \pmb j + e_z \pmb k$$ and an angle $\theta$, the rotation quaternion is given by:
```math
q = \cos(\theta / 2) + \sin(\theta / 2) \pmb e
```
Which is exactly what is implemented in `Quaternion.from_axis_angle`. 
To retrieve the angle then, defining $q_r = \cos(\theta / 2)$ and $\pmb{q}_v = \sin(\theta / 2) \pmb e$ the real and imaginary parts of $q$, respectively:
```math
\theta/2 = \operatorname{atan_2}\left( |\pmb{q}_v|, q_r\right)
```
And:
```math
\theta = 2 \operatorname{atan_2}\left( |\pmb{q}_v|, q_r\right)
``` 

This multiplying factor of two is missing from the implementation of `Quaternion.angle`, as running this:
```
axis = [1, 0, 0]
theta = pi / 2
Quaternion.from_axis_angle(axis, theta).angle()
```
Returns $\pi / 4$

Discussion:

Patch:
diff --git a/sympy/algebras/quaternion.py b/sympy/algebras/quaternion.py
index 3e9170333d..a924d82ee4 100644
--- a/sympy/algebras/quaternion.py
+++ b/sympy/algebras/quaternion.py
@@ -1406,11 +1406,11 @@ def angle(self):
         Explanation
         ===========
 
-        Given a quaternion $q = a + bi + cj + dk$ where a, b, c and d
+        Given a quaternion $q = a + bi + cj + dk$ where $a$, $b$, $c$ and $d$
         are real numbers, returns the angle of the quaternion given by
 
         .. math::
-            angle := atan2(\sqrt{b^2 + c^2 + d^2}, {a})
+            \theta := 2 \operatorname{atan_2}\left(\sqrt{b^2 + c^2 + d^2}, {a}\right)
 
         Examples
         ========
@@ -1418,11 +1418,11 @@ def angle(self):
         >>> from sympy.algebras.quaternion import Quaternion
         >>> q = Quaternion(1, 4, 4, 4)
         >>> q.angle()
-        atan(4*sqrt(3))
+        2*atan(4*sqrt(3))
 
         """
 
-        return atan2(self.vector_part().norm(), self.scalar_part())
+        return 2 * atan2(self.vector_part().norm(), self.scalar_part())
 
 
     def arc_coplanar(self, other):


Test patch:
diff --git a/sympy/algebras/tests/test_quaternion.py b/sympy/algebras/tests/test_quaternion.py
index ced474c930..edf65ec18e 100644
--- a/sympy/algebras/tests/test_quaternion.py
+++ b/sympy/algebras/tests/test_quaternion.py
@@ -198,8 +198,8 @@ def test_quaternion_functions():
     assert Quaternion(0, 2, 10, 3).is_pure() is True
     assert Quaternion(w, 2, 10, 3).is_pure() is None
 
-    assert q1.angle() == atan(sqrt(29))
-    assert q.angle() == atan2(sqrt(x**2 + y**2 + z**2), w)
+    assert q1.angle() == 2*atan(sqrt(29))
+    assert q.angle() == 2*atan2(sqrt(x**2 + y**2 + z**2), w)
 
     assert Quaternion.arc_coplanar(q1, Quaternion(2, 4, 6, 8)) is True
     assert Quaternion.arc_coplanar(q1, Quaternion(1, -2, -3, -4)) is True