|
16 | 16 | from spatialmath.base.argcheck import getvector |
17 | 17 | from spatialmath.base.types import * |
18 | 18 |
|
19 | | -try: # pragma: no cover |
20 | | - # print('Using SymPy') |
21 | | - import sympy |
22 | | - |
23 | | - _symbolics = True |
24 | | - |
25 | | -except ImportError: # pragma: no cover |
26 | | - _symbolics = False |
| 19 | +from spatialmath.base import symbolic as sym |
27 | 20 |
|
28 | 21 | _eps = np.finfo(np.float64).eps |
29 | 22 |
|
@@ -55,8 +48,8 @@ def norm(v: ArrayLikePure) -> float: |
55 | 48 | for x in v: |
56 | 49 | sum += x * x |
57 | 50 |
|
58 | | - if _symbolics and isinstance(sum, sympy.Expr): |
59 | | - return sympy.sqrt(sum) |
| 51 | + if sym.issymbol(sum): |
| 52 | + return sym.sqrt(sum) |
60 | 53 | else: |
61 | 54 | return math.sqrt(sum) |
62 | 55 |
|
@@ -567,13 +560,10 @@ def wrap_mpi2_pi2(theta: ArrayLike) -> Union[float, NDArray]: |
567 | 560 |
|
568 | 561 | """ |
569 | 562 | theta = getvector(theta) |
570 | | - n = theta / np.pi * 2 |
571 | | - if isinstance(n, np.ndarray): |
572 | | - n = n.astype(int) |
573 | | - else: |
574 | | - n = np.fix(n).astype(int) |
575 | | - |
576 | | - y = np.where(np.bitwise_and(n, 1) == 0, theta - n * np.pi, n * np.pi - theta) |
| 563 | + theta = np.fmod(theta, 2 * np.pi) |
| 564 | + theta = np.where(theta > np.pi, theta - 2 * np.pi, theta) |
| 565 | + theta = np.where(theta < -np.pi, theta + 2 * np.pi, theta) |
| 566 | + y = np.where(np.abs(theta) <= np.pi / 2, theta, np.copysign(np.pi, theta) - theta) |
577 | 567 | if isinstance(y, np.ndarray) and len(y) == 1: |
578 | 568 | return float(y[0]) |
579 | 569 | else: |
@@ -832,7 +822,14 @@ def project(v1: ArrayLike3, v2: ArrayLike3) -> ArrayLike3: |
832 | 822 | :return: vector projection of v1 onto v2 (parrallel to v2) |
833 | 823 | :rtype: ndarray(n) |
834 | 824 | """ |
835 | | - return np.dot(v1, v2) * v2 |
| 825 | + v1 = getvector(v1) |
| 826 | + v2 = getvector(v2) |
| 827 | + scale = np.max(np.abs(v2)) |
| 828 | + if scale == 0: |
| 829 | + return np.zeros_like(v2) |
| 830 | + # Normalize the scale before dot products to avoid over/underflow. |
| 831 | + v2 = v2 / scale |
| 832 | + return (np.dot(v1, v2) / np.dot(v2, v2)) * v2 |
836 | 833 |
|
837 | 834 |
|
838 | 835 | def orthogonalize(v1: ArrayLike3, v2: ArrayLike3, normalize: bool = True) -> ArrayLike3: |
|
0 commit comments