blob: 2801f88ffdc11e39f7e829dbe4151bf860db65ee [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 Jones6d460fe2021-07-03 16:59:55 -070015class Graph(Gtk.Bin):
16 def __init__(self):
17 super(Graph, self).__init__()
18 fig = Figure(figsize=(5, 4), dpi=100)
19 self.axis = fig.add_subplot(111)
Ravago Jonese9584792022-05-28 16:16:46 -070020 self.canvas = FigureCanvas(fig) # a Gtk.DrawingArea
21 self.canvas.set_vexpand(True)
22 self.canvas.set_size_request(800, 250)
23 self.add(self.canvas)
Ravago Jones56941a52021-07-31 14:42:38 -070024 self.queue = queue.Queue(maxsize=1)
25
26 thread = threading.Thread(target=self.worker)
27 thread.daemon = True
28 thread.start()
29
30 def schedule_recalculate(self, points):
31 if not points.getLibsplines() or self.queue.full(): return
32 new_copy = copy.deepcopy(points)
33
34 # empty the queue
35 try:
36 self.queue.get_nowait()
37 except queue.Empty:
38 pass # was already empty
39
40 # replace with new request
41 self.queue.put_nowait(new_copy)
42
43 def worker(self):
44 while True:
45 self.recalculate_graph(self.queue.get())
John Park91e69732019-03-03 13:12:43 -080046
Ravago Jones6d460fe2021-07-03 16:59:55 -070047 def recalculate_graph(self, points):
48 if not points.getLibsplines(): return
Ravago Jones6d460fe2021-07-03 16:59:55 -070049 # set the size of a timestep
50 dt = 0.00505
John Park91e69732019-03-03 13:12:43 -080051
Ravago Jones6d460fe2021-07-03 16:59:55 -070052 # call C++ wrappers to calculate the trajectory
53 distanceSpline = DistanceSpline(points.getLibsplines())
54 traj = Trajectory(distanceSpline)
55 points.addConstraintsToTrajectory(traj)
56 traj.Plan()
57 XVA = traj.GetPlanXVA(dt)
Ravago Jones56941a52021-07-31 14:42:38 -070058 if XVA is None: return
John Park91e69732019-03-03 13:12:43 -080059
Ravago Jones6d460fe2021-07-03 16:59:55 -070060 # extract values to be graphed
61 total_steps_taken = XVA.shape[1]
62 total_time = dt * total_steps_taken
Ravago Jones56941a52021-07-31 14:42:38 -070063 time = np.linspace(0, total_time, num=total_steps_taken)
Ravago Jones6d460fe2021-07-03 16:59:55 -070064 position, velocity, acceleration = XVA
65 left_voltage, right_voltage = zip(*(traj.Voltage(x) for x in position))
John Park91e69732019-03-03 13:12:43 -080066
Ravago Jones6d460fe2021-07-03 16:59:55 -070067 # update graph
68 self.axis.clear()
69 self.axis.plot(time, velocity)
70 self.axis.plot(time, acceleration)
71 self.axis.plot(time, left_voltage)
72 self.axis.plot(time, right_voltage)
73 self.axis.legend(
74 ["Velocity", "Acceleration", "Left Voltage", "Right Voltage"])
75 self.axis.xaxis.set_label_text("Time (sec)")
John Park91e69732019-03-03 13:12:43 -080076
Ravago Jones6d460fe2021-07-03 16:59:55 -070077 # renumber the x-axis to include the last point,
78 # the total time to drive the spline
79 self.axis.xaxis.set_ticks(np.linspace(0, total_time, num=8))
Ravago Jones128fb992021-07-31 13:56:58 -070080
Ravago Jonese9584792022-05-28 16:16:46 -070081 # redraw
82 self.canvas.draw()