Skip to content

Commit c59f30e

Browse files
authored
Merge branch 'master' into feat/use_new_colored_api
2 parents b5ce917 + 09b0c43 commit c59f30e

10 files changed

Lines changed: 53 additions & 14 deletions

File tree

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Global Owners
2-
* @petercorke @jbarry-bdai
2+
* @petercorke @jbarry-bdai @taughz

.github/workflows/master.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
33
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
44

5-
name: build
5+
name: CI
66

77
on:
88
push:

.github/workflows/sphinx.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ jobs:
2929
cd ../
3030
- name: Commit documentation changes
3131
run: |
32-
git clone https://github.com/petercorke/spatialmath-python.git --branch gh-pages --single-branch gh-pages
32+
git clone https://github.com/${{ github.repository }}.git --branch gh-pages --single-branch gh-pages
3333
cp -r docs/build/html/* gh-pages/
3434
cd gh-pages
3535
git config --local user.email "action@github.com"

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "spatialmath-python"
3-
version = "1.1.16"
3+
version = "1.1.17"
44
authors = [
55
{ name="Peter Corke", email="rvc@petercorke.com" },
66
]

spatialmath/base/graphics.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,10 +1512,11 @@ def _axes_dimensions(ax: plt.Axes) -> int:
15121512
else:
15131513
# handle the case of Animate objects pretending to be Axes
15141514
classname = ax.__class__.__name__
1515-
if classname == "Animate":
1516-
ret = 3
1517-
elif classname == "Animate2":
1518-
ret = 2
1515+
base_classes = ax.__class__.__bases__
1516+
if classname in ("Axes3DSubplot", "Animate") or any(base_class.__name__ in ("Axes3DSubplot", "Animate") for base_class in base_classes):
1517+
return 3
1518+
elif classname in ("AxesSubplot", "Animate2"):
1519+
return 2
15191520
# print("_axes_dimensions ", ax, ret)
15201521
return ret
15211522

spatialmath/twist.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ def pitch(self):
944944
>>> S.pitch
945945
946946
"""
947-
return np.dot(self.w, self.v)
947+
return np.dot(self.w, self.v) / np.dot(self.w, self.w)
948948

949949
def line(self):
950950
"""

tests/base/test_transforms3d_plot.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,12 @@ def test_plot(self):
7474
plt.close("all")
7575

7676
@pytest.mark.skipif(
77-
os.environ.get("CI") == "true"
77+
plt.get_backend().lower() == "agg"
78+
or os.environ.get("CI") == "true"
7879
or (sys.platform.startswith("darwin") and sys.version_info < (3, 11)),
79-
reason="no display in CI / tkinter bug on mac",
80+
reason="animation wait=True busy-loop never terminates under the "
81+
"non-interactive Agg backend (no event loop to deregister the "
82+
"timer callback); needs a real display",
8083
)
8184
def test_animate(self):
8285
tranimate(transl(1, 2, 3), repeat=False, wait=True)

tests/conftest.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import os
2+
3+
# Force a non-interactive Matplotlib backend for the whole test session,
4+
# before any test module or package code gets a chance to import
5+
# matplotlib.pyplot. Several modules (geom2d, geom3d, spline, animate)
6+
# import pyplot at module load time, so this has to happen here, in
7+
# conftest.py, which pytest guarantees to load before collecting tests.
8+
#
9+
# CI already sets MPLBACKEND=Agg via the workflow env, so this mainly
10+
# fixes local runs, which otherwise use the platform's interactive
11+
# backend and pop up real windows / can hang on plt.pause(). setdefault
12+
# (not a hard override) leaves an escape hatch: run with
13+
# MPLBACKEND=MacOSX pytest ... to actually see a plot when you want to.
14+
os.environ.setdefault("MPLBACKEND", "Agg")

tests/test_spline.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ def test_evaluation(self):
2828
nt.assert_almost_equal(spline(0).A, self.control_poses[0].A)
2929
nt.assert_almost_equal(spline(1).A, self.control_poses[-1].A)
3030

31-
@pytest.mark.skipif(os.environ.get("CI") == "true", reason="no display in CI")
31+
@pytest.mark.skipif(
32+
plt.get_backend().lower() == "agg" or os.environ.get("CI") == "true",
33+
reason="animate=True busy-waits on a timer callback that never "
34+
"fires under the non-interactive Agg backend",
35+
)
3236
def test_visualize(self):
3337
spline = BSplineSE3(self.control_poses)
3438
spline.visualize(
@@ -69,7 +73,11 @@ def test_small_delta_t(self):
6973
np.linspace(0, InterpSplineSE3._e, len(self.waypoints)), self.waypoints
7074
)
7175

72-
@pytest.mark.skipif(os.environ.get("CI") == "true", reason="no display in CI")
76+
@pytest.mark.skipif(
77+
plt.get_backend().lower() == "agg" or os.environ.get("CI") == "true",
78+
reason="animate=True busy-waits on a timer callback that never "
79+
"fires under the non-interactive Agg backend",
80+
)
7381
def test_visualize(self):
7482
spline = InterpSplineSE3(self.times, self.waypoints)
7583
spline.visualize(
@@ -110,7 +118,9 @@ def test_spline_fit(self):
110118

111119
assert fit.max_angular_error() < np.deg2rad(5.0)
112120
assert fit.max_angular_error() < 0.1
113-
if os.environ.get("CI") != "true":
121+
# animate=True busy-waits on a timer callback that never fires
122+
# under the non-interactive Agg backend
123+
if plt.get_backend().lower() != "agg" and os.environ.get("CI") != "true":
114124
spline.visualize(
115125
sample_times=np.linspace(0, self.time_horizon, 100),
116126
animate=True,

tests/test_twist.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,17 @@ def test_exp(self):
179179
tw = Twist3.UnitRevolute([0, 0, 1], [0, 0, 0])
180180
array_compare(tw.exp(pi / 2), SE3.Rz(pi / 2))
181181

182+
def test_pitch(self):
183+
# pitch = (w . v) / (w . w), regression test for missing denominator
184+
185+
# non-unit w: exercises the normalization, would fail without it
186+
tw = Twist3([0, 0, 4], [0, 0, 2])
187+
self.assertAlmostEqual(tw.pitch, 2.0)
188+
189+
# unit w: denominator is 1, sanity check against UnitRevolute's pitch arg
190+
tw = Twist3.UnitRevolute([0, 0, 1], [0, 0, 0], pitch=3)
191+
self.assertAlmostEqual(tw.pitch, 3.0)
192+
182193
def test_arith(self):
183194
# check overloaded *
184195

0 commit comments

Comments
 (0)