From cf58513e9ae3f8ece7f8f01ec1269f9889d27e07 Mon Sep 17 00:00:00 2001
From: m-guberina <gubi.guberina@gmail.com>
Date: Thu, 31 Oct 2024 23:32:58 +0100
Subject: [PATCH] i tried to get real time plotting to work with on clik event,
 but for that i needed to make logplotter a class, and now matplotlib is
 complaining about something and hangs when it's supposed to draw. i can't be
 bothered with this evil now

---
 python/examples/comparing_logs_example.py     |   2 +-
 .../__pycache__/visualize.cpython-312.pyc     | Bin 17147 -> 18211 bytes
 .../manipulator_comparison_visualizer.py      |  19 ++-
 .../ur_simple_control/visualize/visualize.py  | 155 +++++++++---------
 4 files changed, 88 insertions(+), 88 deletions(-)

diff --git a/python/examples/comparing_logs_example.py b/python/examples/comparing_logs_example.py
index c590978..3a8ca95 100644
--- a/python/examples/comparing_logs_example.py
+++ b/python/examples/comparing_logs_example.py
@@ -17,7 +17,7 @@ and that the same things are logged.
 
 key = list(cmp_manager.logm1.loop_logs.keys())[0]
 cmp_manager.createRunningPlot(cmp_manager.logm1.loop_logs[key], 0, len(cmp_manager.logm1.loop_logs[key]['qs']))
-cmp_manager.createRunningPlot(cmp_manager.logm2.loop_logs[key], 0, len(cmp_manager.logm2.loop_logs[key]['qs']))
+#cmp_manager.createRunningPlot(cmp_manager.logm2.loop_logs[key], 0, len(cmp_manager.logm2.loop_logs[key]['qs']))
 cmp_manager.visualizeWholeRuns()
 cmp_manager.manipulator_visualizer_cmd_queue.put("befree")
 print("main done")
diff --git a/python/ur_simple_control/visualize/__pycache__/visualize.cpython-312.pyc b/python/ur_simple_control/visualize/__pycache__/visualize.cpython-312.pyc
index cdb303e8174d784085e917dde458ea4c3b6b14d9..87272c72c0cd219d816377f13d47be8b84d16980 100644
GIT binary patch
delta 3742
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
J7(gW0AONvUVWt28

delta 2790
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
U*k|%dHxHiAA<W5)jKW~00N53v9smFU

diff --git a/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py b/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py
index 9537c15..5b6415d 100644
--- a/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py
+++ b/python/ur_simple_control/visualize/manipulator_comparison_visualizer.py
@@ -6,7 +6,7 @@ from itertools import zip_longest
 from multiprocessing import Process, Queue
 from ur_simple_control.managers import getMinimalArgParser, RobotManager
 from ur_simple_control.util.logging_utils import LogManager
-from ur_simple_control.visualize.visualize import manipulatorComparisonVisualizer, logPlotter
+from ur_simple_control.visualize.visualize import manipulatorComparisonVisualizer, LogPlotter
 
 def getLogComparisonArgs():
     parser = getMinimalArgParser()
@@ -78,7 +78,7 @@ class ManipulatorComparisonManager:
         ###########################################
         #  in case you will want log plotters too  #
         ###########################################
-        self.log_plotters = []
+        self.running_plotters = []
 
 
     # NOTE i assume what you want to plot is a time-indexed with
@@ -91,21 +91,22 @@ class ManipulatorComparisonManager:
             self.time_stop = log_plotter_time_stop
             self.cmd_queue = Queue()
             self.ack_queue = Queue()
-            self.process = Process(target=logPlotter, 
-                                         args=(args, log, self.cmd_queue, 
+            log_plotter = LogPlotter(args, log)
+            self.process = Process(target=log_plotter.runLogPlotter, 
+                                         args=(self.cmd_queue, 
                                                self.ack_queue))
             self.process.start()
             self.ack_queue.get()
 
     def createRunningPlot(self, log, log_plotter_time_start, log_plotter_time_stop):
-        self.log_plotters.append(self.RunningPlotter(self.args, log, log_plotter_time_start, log_plotter_time_stop))
+        self.running_plotters.append(self.RunningPlotter(self.args, log, log_plotter_time_start, log_plotter_time_stop))
 
     def updateViz(self, q1, q2, time_index):
         self.manipulator_visualizer_cmd_queue.put((q1, q2))
-        for log_plotter in self.log_plotters:
-            if (time_index >= log_plotter.time_start) and (time_index < log_plotter.time_stop):
-                log_plotter.cmd_queue.put(time_index - log_plotter.time_start)
-                log_plotter.ack_queue.get()
+        for running_plotter in self.running_plotters:
+            if (time_index >= running_plotter.time_start) and (time_index < running_plotter.time_stop):
+                running_plotter.cmd_queue.put(time_index - running_plotter.time_start)
+                running_plotter.ack_queue.get()
         self.manipulator_visualizer_ack_queue.get()
 
     # NOTE: this uses slightly fancy python to make it bareable to code
diff --git a/python/ur_simple_control/visualize/visualize.py b/python/ur_simple_control/visualize/visualize.py
index 6d1cfde..6b51acf 100644
--- a/python/ur_simple_control/visualize/visualize.py
+++ b/python/ur_simple_control/visualize/visualize.py
@@ -305,7 +305,7 @@ def manipulatorComparisonVisualizer(args, model, collision_model, visual_model,
 # but otherwise i can't pass arguments to that.
 # even if i could with partial, i can't return them,
 # so no cigar from that
-def logPlotter(args, log, cmd_queue, ack_queue):
+class LogPlotter:
     """
     logPlotter
     ---------------
@@ -318,90 +318,89 @@ def logPlotter(args, log, cmd_queue, ack_queue):
       as then you don't need to think about IPC - just use what's here.
     - this might be shoved into a tkinter gui if i decide i really need buttons
     """
-    if len(log) == 0:
-        print("you've send me nothing, so no real-time plotting for you")
-        return
+    def __init__(self, args, log):
+        self.log = log
+        self.args = args
+        if len(self.log) == 0:
+            print("you've send me nothing, so no real-time plotting for you")
+            return
 
-    plt.ion()
-    fig = plt.figure()
-    canvas = fig.canvas
-    AxisAndArtists = namedtuple("AxAndArtists", "ax artists")
-    axes_and_updating_artists = {}
+        plt.ion()
+        self.fig = plt.figure()
+        self.canvas = self.fig.canvas
+        self.AxisAndArtists = namedtuple("AxAndArtists", "ax artists")
+        self.axes_and_updating_artists = {}
 
-    n_cols, n_rows = getNRowsMColumnsFromTotalNumber(len(log))
-    # this is what subplot wants
-    subplot_col_row = str(n_cols) + str(n_rows)
-    # preload some zeros and initialize plots
-    for i, data_key in enumerate(log):
-        # you give single-vector numpy arrays, i instantiate and plot lists of these 
-        # so for your (6,) vector, i plot (N, 6) ndarrays resulting in 6 lines of length N.
-        # i manage N because plot data =/= all data for efficiency reasons.
-        assert type(log[data_key]) == np.ndarray
+        n_cols, n_rows = getNRowsMColumnsFromTotalNumber(len(log))
+        # this is what subplot wants
+        subplot_col_row = str(n_cols) + str(n_rows)
+        # preload some zeros and initialize plots
+        for i, data_key in enumerate(self.log):
+            # you give single-vector numpy arrays, i instantiate and plot lists of these 
+            # so for your (6,) vector, i plot (N, 6) ndarrays resulting in 6 lines of length N.
+            # i manage N because plot data =/= all data for efficiency reasons.
+            assert type(self.log[data_key]) == np.ndarray
 
-        colors = plt.cm.jet(np.linspace(0, 1, log[data_key].shape[1]))
-        ax = fig.add_subplot(int(subplot_col_row + str(i + 1)))
-        ax.set_title(data_key)
-        # we plot each line separately so that they have different colors
-        # we assume (N_timesteps, your_vector) shapes.
-        # values do not update
-        for j in range(log[data_key].shape[1]):
-            # NOTE the same length assumption plays a part for correctness,
-            # but i don't want that to be an error in case you know what you're doing
-            ax.plot(np.arange(len(log[data_key])), log[data_key][:,j], 
-                        color=colors[j], label=data_key + "_" + str(j))
+            colors = plt.cm.jet(np.linspace(0, 1, log[data_key].shape[1]))
+            ax = self.fig.add_subplot(int(subplot_col_row + str(i + 1)))
+            ax.set_title(data_key)
+            # we plot each line separately so that they have different colors
+            # we assume (N_timesteps, your_vector) shapes.
+            # values do not update
+            for j in range(log[data_key].shape[1]):
+                # NOTE the same length assumption plays a part for correctness,
+                # but i don't want that to be an error in case you know what you're doing
+                ax.plot(np.arange(len(log[data_key])), log[data_key][:,j], 
+                            color=colors[j], label=data_key + "_" + str(j))
 
-        # vertical bar does update
-        point_in_time_line = ax.axvline(x=0, color='red', animated=True)
-        axes_and_updating_artists[data_key] = AxisAndArtists(ax, point_in_time_line)
-        axes_and_updating_artists[data_key].ax.legend(loc='upper left')
+            # vertical bar does update
+            point_in_time_line = ax.axvline(x=0, color='red', animated=True)
+            self.axes_and_updating_artists[data_key] = self.AxisAndArtists(ax, point_in_time_line)
+            self.axes_and_updating_artists[data_key].ax.legend(loc='upper left')
 
-    # need to call it once to start, more if something breaks
-    canvas.draw()
-    canvas.flush_events()
-    background = canvas.copy_from_bbox(fig.bbox)
+        # need to call it once to start, more if something breaks
+        self.canvas.draw()
+        self.canvas.flush_events()
+        self.background = self.canvas.copy_from_bbox(self.fig.bbox)
 
-    # we need to have an event that triggers redrawing
-    #cid = fig.canvas.mpl_connect('button_press_event', onclick)
-    def onEvent(event):
-        print("drawing")
-        canvas.draw()
-        canvas.flush_events()
-        background = canvas.copy_from_bbox(fig.bbox)
-        print("copied canvas")
+        # we need to have an event that triggers redrawing
+        #cid = fig.canvas.mpl_connect('button_press_event', onclick)
 
-    cid = fig.canvas.mpl_connect('button_press_event', onEvent)
+        self.cid = self.fig.canvas.mpl_connect('button_press_event', self.onEvent)
+        self.cid = self.fig.canvas.mpl_connect('resize_event', self.onEvent)
 
+    def onEvent(self, event):
+        print("re-drawing")
+        self.canvas.draw()
+        self.canvas.flush_events()
+        self.background = self.canvas.copy_from_bbox(self.fig.bbox)
 
-    ack_queue.put("ready")
-    if args.debug_prints:
-        print("LOG_PLOTTER: FULLY ONLINE")
-    try:
-        counter = 0
-        while True:
-            counter += 1
-            time_index = cmd_queue.get()
-            if time_index == "befree":
-                if args.debug_prints:
-                    print("LOG_PLOTTER: got befree, logPlotter out")
-                break
-            canvas.restore_region(background)
-            for data_key in log:
-                axes_and_updating_artists[data_key].artists.set_xdata([time_index])
-                axes_and_updating_artists[data_key].ax.draw_artist(axes_and_updating_artists[data_key].artists)
-            # NOTE: this is stupid, i just want to catch the resize event
-            if not (counter % 50 == 0):
-            #if True:
+    def runLogPlotter(self, cmd_queue, ack_queue):
+        ack_queue.put("ready")
+        if self.args.debug_prints:
+            print("LOG_PLOTTER: FULLY ONLINE")
+        try:
+            counter = 0
+            while True:
+                counter += 1
+                time_index = cmd_queue.get()
+                if time_index == "befree":
+                    if self.args.debug_prints:
+                        print("LOG_PLOTTER: got befree, logPlotter out")
+                    break
+                self.canvas.restore_region(self.background)
+                for data_key in self.log:
+                    self.axes_and_updating_artists[data_key].artists.set_xdata([time_index])
+                    self.axes_and_updating_artists[data_key].ax.draw_artist(self.axes_and_updating_artists[data_key].artists)
+                # NOTE: this is stupid, i just want to catch the resize event
                 print(counter)
-                canvas.blit(fig.bbox)
-                canvas.flush_events()
-            else:
-                print("drawing")
-                canvas.draw()
-                canvas.flush_events()
-                background = canvas.copy_from_bbox(fig.bbox)
-                print("copied canvas")
-            ack_queue.put("ready")
-    except KeyboardInterrupt:
-        if args.debug_prints:
-            print("LOG_PLOTTER: caught KeyboardInterrupt, i'm out")
-    plt.close(fig)
+                #self.canvas.blit(self.fig.bbox)
+                #self.canvas.flush_events()
+                self.onEvent(None)
+                print("putting ready")
+                ack_queue.put("ready")
+                print("put ready")
+        except KeyboardInterrupt:
+            if self.args.debug_prints:
+                print("LOG_PLOTTER: caught KeyboardInterrupt, i'm out")
+        plt.close(self.fig)
-- 
GitLab