blob: 77288ea1303984b4bcb2b2229b3d96a802d2f555 [file] [log] [blame]
Ravago Jones6d460fe2021-07-03 16:59:55 -07001import gi
2gi.require_version('Gtk', '3.0')
3from gi.repository import Gtk
4import numpy as np
Ravago Jones56941a52021-07-31 14:42:38 -07005import queue
6import threading
7import copy
John Park91e69732019-03-03 13:12:43 -08008from points import Points
John Park91e69732019-03-03 13:12:43 -08009from libspline import Spline, DistanceSpline, Trajectory
10
Ravago Jones6d460fe2021-07-03 16:59:55 -070011from matplotlib.backends.backend_gtk3agg import (FigureCanvasGTK3Agg as
12 FigureCanvas)
13from matplotlib.figure import Figure
John Park91e69732019-03-03 13:12:43 -080014
Ravago Jones8da89c42022-07-17 19:34:06 -070015
Ravago Jones6d460fe2021-07-03 16:59:55 -070016class Graph(Gtk.Bin):
17 def __init__(self):
18 super(Graph, self).__init__()
19 fig = Figure(figsize=(5, 4), dpi=100)
20 self.axis = fig.add_subplot(111)
Ravago Jonese9584792022-05-28 16:16:46 -070021 self.canvas = FigureCanvas(fig) # a Gtk.DrawingArea
22 self.canvas.set_vexpand(True)
23 self.canvas.set_size_request(800, 250)
24 self.add(self.canvas)
Ravago Jones56941a52021-07-31 14:42:38 -070025 self.queue = queue.Queue(maxsize=1)
26
27 thread = threading.Thread(target=self.worker)
28 thread.daemon = True
29 thread.start()
30
31 def schedule_recalculate(self, points):
32 if not points.getLibsplines() or self.queue.full(): return
33 new_copy = copy.deepcopy(points)
34
35 # empty the queue
36 try:
37 self.queue.get_nowait()
38 except queue.Empty:
Ravago Jones8da89c42022-07-17 19:34:06 -070039 pass # was already empty
Ravago Jones56941a52021-07-31 14:42:38 -070040
41 # replace with new request
42 self.queue.put_nowait(new_copy)
43
44 def worker(self):
45 while True:
46 self.recalculate_graph(self.queue.get())
John Park91e69732019-03-03 13:12:43 -080047
Ravago Jones6d460fe2021-07-03 16:59:55 -070048 def recalculate_graph(self, points):
49 if not points.getLibsplines(): return
Ravago Jones6d460fe2021-07-03 16:59:55 -070050 # set the size of a timestep
51 dt = 0.00505
John Park91e69732019-03-03 13:12:43 -080052
Ravago Jones6d460fe2021-07-03 16:59:55 -070053 # call C++ wrappers to calculate the trajectory
54 distanceSpline = DistanceSpline(points.getLibsplines())
55 traj = Trajectory(distanceSpline)
56 points.addConstraintsToTrajectory(traj)
57 traj.Plan()
58 XVA = traj.GetPlanXVA(dt)
Ravago Jones56941a52021-07-31 14:42:38 -070059 if XVA is None: return
John Park91e69732019-03-03 13:12:43 -080060
Ravago Jones6d460fe2021-07-03 16:59:55 -070061 # extract values to be graphed
62 total_steps_taken = XVA.shape[1]
63 total_time = dt * total_steps_taken
Ravago Jones56941a52021-07-31 14:42:38 -070064 time = np.linspace(0, total_time, num=total_steps_taken)
Ravago Jones6d460fe2021-07-03 16:59:55 -070065 position, velocity, acceleration = XVA
66 left_voltage, right_voltage = zip(*(traj.Voltage(x) for x in position))
John Park91e69732019-03-03 13:12:43 -080067
Ravago Jones6d460fe2021-07-03 16:59:55 -070068 # update graph
69 self.axis.clear()
70 self.axis.plot(time, velocity)
71 self.axis.plot(time, acceleration)
72 self.axis.plot(time, left_voltage)
73 self.axis.plot(time, right_voltage)
74 self.axis.legend(
75 ["Velocity", "Acceleration", "Left Voltage", "Right Voltage"])
76 self.axis.xaxis.set_label_text("Time (sec)")
John Park91e69732019-03-03 13:12:43 -080077
Ravago Jones6d460fe2021-07-03 16:59:55 -070078 # renumber the x-axis to include the last point,
79 # the total time to drive the spline
80 self.axis.xaxis.set_ticks(np.linspace(0, total_time, num=8))
Ravago Jones128fb992021-07-31 13:56:58 -070081
Ravago Jonese9584792022-05-28 16:16:46 -070082 # redraw
83 self.canvas.draw()