Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions spatialmath/base/vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -683,14 +683,28 @@ def angle_std(theta: ArrayLike) -> float:
r"""
Standard deviation of angular values

:param theta: angular values
:param theta: angular values, in radians
:type theta: array_like
:return: circular standard deviation
:return: circular standard deviation, in radians
:rtype: float

The circular standard deviation is

.. math::

\sigma_{\theta} = \sqrt{-2 \log \| \left[ \frac{\sum \sin \theta_i}{N}, \frac{\sum \sin \theta_i}{N} \right] \|} \in [0, \infty)
\sigma_{\theta} = \sqrt{-2 \log R} \in [0, \infty), \quad
R = \left\| \left[ \frac{\sum \cos \theta_i}{N}, \frac{\sum \sin \theta_i}{N} \right] \right\|

where :math:`R` is the length of the mean of the unit vectors at angles
:math:`\theta_i`. :math:`R = 1` if all the angles are equal, giving a
standard deviation of zero, and :math:`R \to 0` as the angles spread evenly
around the circle, when the standard deviation grows without bound.

This is the same quantity as ``scipy.stats.circstd`` with its default
arguments.

.. note:: If :math:`R` is exactly zero the result is ``inf``, with a NumPy
divide-by-zero warning.

:seealso: :func:`angle_mean`
"""
Expand All @@ -705,16 +719,23 @@ def angle_mean(theta: ArrayLike) -> float:
r"""
Mean of angular values

:param theta: angular values
:type v: array_like
:return: circular mean
:param theta: angular values, in radians
:type theta: array_like
:return: circular mean, in radians
:rtype: float

The circular mean is given by
The circular mean is the angle of the mean of the unit vectors at angles
:math:`\theta_i`

.. math::

\bar{\theta} = \tan^{-1} \frac{\sum \sin \theta_i}{\sum \cos \theta_i} \in [-\pi, \pi)]
\bar{\theta} = \tan^{-1} \frac{\sum \sin \theta_i}{\sum \cos \theta_i} \in [-\pi, \pi]

computed with the two-argument arctangent so that the quadrant is correct.

.. note:: If the unit vectors cancel, for example the angles :math:`0` and
:math:`\pi`, the mean direction is undefined and the result is decided by
rounding error.

:seealso: :func:`angle_std`
"""
Expand All @@ -727,8 +748,8 @@ def angle_wrap(theta: ArrayLike, mode: str = "-pi:pi") -> Union[float, NDArray]:
"""
Generalized angle-wrapping

:param v: angles to wrap
:type v: array_like
:param theta: angles to wrap
:type theta: array_like
:param mode: wrapping mode, one of: ``"0:2pi"``, ``"0:pi"``, ``"-pi/2:pi/2"`` or ``"-pi:pi"`` [default]
:type mode: str, optional
:return: wrapped angles
Expand Down
Loading