Skip to content

fix(pyplot): robot.plot(..., movie=...) crashes on save - #645

Merged
petercorke merged 3 commits into
mainfrom
fix/pyplot-movie-crash
Aug 26, 2026
Merged

fix(pyplot): robot.plot(..., movie=...) crashes on save#645
petercorke merged 3 commits into
mainfrom
fix/pyplot-movie-crash

Conversation

@petercorke

Copy link
Copy Markdown
Owner

Summary

Two real, independent bugs in the movie-recording path (robot.plot(q, backend="pyplot", movie=...)), both found by actually reproducing #405 rather than assuming the original w_xaxis traceback was the whole story:

  • BaseRobot.plot() referenced PyPlot in an isinstance check with no import of PyPlot anywhere in the module — an immediate NameError the instant movie= was used, on any platform, regardless of matplotlib version.
  • PyPlot.getframe() called canvas.tostring_rgb(), which no longer exists on matplotlib's Agg canvas (removed after being deprecated). Replaced with the modern canvas.buffer_rgba(), converting the resulting RGBA image to RGB before saving (GIFs don't need the alpha channel).

Test plan

  • New regression test test_plot_movie in tests/test_PyPlot.py: runs a real 3-frame trajectory through robot.plot(..., movie=path), confirms the output is a valid multi-frame GIF (not just "no exception").
  • Confirmed the new test fails with a NameError against the pre-fix code, and passes with the fix.
  • Full tests/test_PyPlot.py suite green (6 passed).
  • Manually reproduced the original using <robot>.plot() causes pyplot to crash #405 report end-to-end and confirmed a real, valid 5-frame GIF is produced.

Fixes #405.

🤖 Generated with Claude Code

Two real, independent bugs in the movie-recording path, both surfaced
by real reproduction of #405:

- BaseRobot.plot() referenced PyPlot in an isinstance check
  (`isinstance(env, PyPlot)`) with no import of PyPlot anywhere in the
  module -- immediate NameError the instant movie= was used, on every
  platform.
- PyPlot.getframe() called canvas.tostring_rgb(), removed from
  matplotlib's Agg canvas in a later release (the w_xaxis-era API this
  issue's traceback also shows). Replaced with the modern
  canvas.buffer_rgba() (RGBA -> converted to RGB for GIF saving).

Verified end-to-end: a real trajectory now saves a valid multi-frame
GIF via robot.plot(qt.q, backend="pyplot", movie=path).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t_movie

Image.open() keeps a lazy file handle open on multi-frame images to
support seek(). Windows refuses to delete a file while a handle to it
is still open, so tempfile.TemporaryDirectory()'s cleanup raised
PermissionError [WinError 32] on Windows CI. macOS/Linux allow
unlinking an open file (POSIX semantics), which is why this only
failed on windows-latest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@petercorke

Copy link
Copy Markdown
Owner Author

Closing and reopening to force a fresh CI run against the latest commit (a direct push to this branch didn't trigger the pull_request workflow event for some reason).

@petercorke petercorke closed this Aug 26, 2026
@petercorke petercorke reopened this Aug 26, 2026
Resolves trivial conflict in tests/test_PyPlot.py: both this branch
and main (via #642) added a new test method at the same location.
Kept both test_plot_movie and test_options_scalar_override.
@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 0.00%. Comparing base (6691113) to head (22a45f6).

Files with missing lines Patch % Lines
src/roboticstoolbox/backends/PyPlot/PyPlot.py 0.00% 2 Missing ⚠️
src/roboticstoolbox/robot/BaseRobot.py 0.00% 2 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff          @@
##            main    #645   +/-   ##
=====================================
  Coverage   0.00%   0.00%           
=====================================
  Files        143     143           
  Lines      14026   14029    +3     
=====================================
- Misses     14026   14029    +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@petercorke
petercorke merged commit 2e2bfe2 into main Aug 26, 2026
23 checks passed
@petercorke
petercorke deleted the fix/pyplot-movie-crash branch August 26, 2026 11:28
@github-actions github-actions Bot mentioned this pull request Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

using <robot>.plot() causes pyplot to crash

1 participant