blob: 870e0396203106cbda3e990200c5a2550f6e06af [file] [log] [blame]
milind upadhyay1a4663c2021-04-03 19:41:34 -07001#!/usr/bin/python3
2
3# Creates a UI for a user to select the regions in a camera image where the balls could be placed
4# for each field layout.
5# After the balls have been placed on the field and they submit the regions,
6# galactic_search_path.py will take another picture and based on the yellow regions
7# in that picture it will determine where the balls are.
8# This tells us which path the current field is. It then sends the Alliance and Letter of the path
9# with aos_send to the /camera channel for the robot to excecute the spline for that path.
10
11from galactic_search_path import *
12
13import getopt
14import glog
15import json
16import matplotlib.patches as patches
17import matplotlib.pyplot as plt
18from matplotlib.widgets import Button
19import numpy as np
20import os
21import sys
22
Ravago Jones5127ccc2022-07-31 16:32:45 -070023_num_rects = 3 # can be 3 or 2, can be specified in commang line arg
milind upadhyay1a4663c2021-04-03 19:41:34 -070024
25_path = Path(Letter.kA, Alliance.kRed, [Rect(None, None, None, None)])
26
27# current index in rects list
28_rect_index = 0
29
30_fig, _img_ax = plt.subplots()
31
Ravago Jones5127ccc2022-07-31 16:32:45 -070032_txt = _img_ax.text(0, 0, "", size=10, backgroundcolor="white")
milind upadhyay1a4663c2021-04-03 19:41:34 -070033
34_confirm = Button(plt.axes([0.7, 0.05, 0.1, 0.075]), "Confirm")
35_cancel = Button(plt.axes([0.81, 0.05, 0.1, 0.075]), "Cancel")
36_submit = Button(plt.axes([0.4, 0.05, 0.1, 0.1]), "Submit")
37
Ravago Jones5127ccc2022-07-31 16:32:45 -070038
milind upadhyay1a4663c2021-04-03 19:41:34 -070039def draw_txt(txt):
Ravago Jones5127ccc2022-07-31 16:32:45 -070040 txt.set_text(
41 "Click on top left point and bottom right point for rect #%u" %
42 (_rect_index + 1))
milind upadhyay1a4663c2021-04-03 19:41:34 -070043 txt.set_color(_path.alliance.value)
44
45
46def on_confirm(event):
47 global _rect_index
Ravago Jones5127ccc2022-07-31 16:32:45 -070048 if _path.rects[_rect_index].x1 != None and _path.rects[
49 _rect_index].x2 != None:
milind upadhyay1a4663c2021-04-03 19:41:34 -070050 _confirm.ax.set_visible(False)
51 _cancel.ax.set_visible(False)
52 _rect_index += 1
53 clear_rect()
54 if _rect_index == _num_rects:
55 _submit.ax.set_visible(True)
56 else:
57 draw_txt(_txt)
58 _path.rects.append(Rect(None, None, None, None))
59 plt.show()
60
Ravago Jones5127ccc2022-07-31 16:32:45 -070061
milind upadhyay1a4663c2021-04-03 19:41:34 -070062def on_cancel(event):
63 global _rect_index
64 if _rect_index < _num_rects:
65 _confirm.ax.set_visible(False)
66 _cancel.ax.set_visible(False)
67 clear_rect()
68 _path.rects[_rect_index].x1 = None
69 _path.rects[_rect_index].y1 = None
70 _path.rects[_rect_index].x2 = None
71 _path.rects[_rect_index].y2 = None
72 plt.show()
73
Ravago Jones5127ccc2022-07-31 16:32:45 -070074
milind upadhyay1a4663c2021-04-03 19:41:34 -070075def on_submit(event):
76 plt.close("all")
77 dict = None
78 dict = load_json()
79 if _path.letter.name not in dict:
80 dict[_path.letter.name] = {}
81 if _path.alliance.name not in dict[_path.letter.name]:
82 dict[_path.letter.name][_path.alliance.name] = []
Ravago Jones5127ccc2022-07-31 16:32:45 -070083 dict[_path.letter.name][_path.alliance.name] = [
84 rect.to_list() for rect in _path.rects
85 ]
milind upadhyay1a4663c2021-04-03 19:41:34 -070086 with open(RECTS_JSON_PATH, 'w') as rects_json:
Ravago Jones5127ccc2022-07-31 16:32:45 -070087 json.dump(dict, rects_json, indent=2)
88
milind upadhyay1a4663c2021-04-03 19:41:34 -070089
90# Clears rect on screen
91def clear_rect():
92 if len(_img_ax.patches) == 0:
93 glog.error("There were no patches found in _img_ax")
94 else:
95 _img_ax.patches[-1].remove()
96
Ravago Jones5127ccc2022-07-31 16:32:45 -070097
milind upadhyay1a4663c2021-04-03 19:41:34 -070098def on_click(event):
99 # This gets called for each click of the rectangle corners,
100 # but also gets called when the user clicks on the Submit button.
101 # At that time _rect_index will equal the length of rects, and so we'll ignore that click.
102 # If it checked the points of the rect at _rect_index, a list out of bounds exception would be thrown.
103 # Additionally, the event xdata or ydata will be None if the user clicks out of
104 # the bounds of the axis
105 if _rect_index < _num_rects and event.xdata != None and event.ydata != None:
106 if _path.rects[_rect_index].x1 == None:
Ravago Jones5127ccc2022-07-31 16:32:45 -0700107 _path.rects[_rect_index].x1, _path.rects[_rect_index].y1 = int(
108 event.xdata), int(event.ydata)
milind upadhyay1a4663c2021-04-03 19:41:34 -0700109 elif _path.rects[_rect_index].x2 == None:
Ravago Jones5127ccc2022-07-31 16:32:45 -0700110 _path.rects[_rect_index].x2, _path.rects[_rect_index].y2 = int(
111 event.xdata), int(event.ydata)
milind upadhyay1a4663c2021-04-03 19:41:34 -0700112 if _path.rects[_rect_index].x2 < _path.rects[_rect_index].x1:
113 tmp = _path.rects[_rect_index].x1
114 _path.rects[_rect_index].x1 = _path.rects[_rect_index].x2
115 _path.rects[_rect_index].x2 = tmp
116 if _path.rects[_rect_index].y2 < _path.rects[_rect_index].y1:
117 tmp = _path.rects[_rect_index].y1
118 _path.rects[_rect_index].y1 = _path.rects[_rect_index].y2
119 _path.rects[_rect_index].y2 = tmp
120
Ravago Jones5127ccc2022-07-31 16:32:45 -0700121 _img_ax.add_patch(
122 patches.Rectangle(
123 (_path.rects[_rect_index].x1, _path.rects[_rect_index].y1),
124 _path.rects[_rect_index].x2 - _path.rects[_rect_index].x1,
125 _path.rects[_rect_index].y2 - _path.rects[_rect_index].y1,
126 edgecolor='r',
127 linewidth=1,
128 facecolor="none"))
milind upadhyay1a4663c2021-04-03 19:41:34 -0700129 _confirm.ax.set_visible(True)
130 _cancel.ax.set_visible(True)
131 plt.show()
132 else:
Ravago Jones5127ccc2022-07-31 16:32:45 -0700133 glog.info(
134 "Either submitted or user pressed out of the bounds of the axis")
135
milind upadhyay1a4663c2021-04-03 19:41:34 -0700136
137def setup_button(button, on_clicked):
138 button.on_clicked(on_clicked)
139 button.ax.set_visible(False)
140
Ravago Jones5127ccc2022-07-31 16:32:45 -0700141
milind upadhyay1a4663c2021-04-03 19:41:34 -0700142def setup_ui():
143 _img_ax.imshow(capture_img())
144 release_stream()
145
146 _fig.canvas.mpl_connect("button_press_event", on_click)
147 setup_button(_confirm, on_confirm)
148 setup_button(_cancel, on_cancel)
149 setup_button(_submit, on_submit)
150 draw_txt(_txt)
151 plt.show()
152
Ravago Jones5127ccc2022-07-31 16:32:45 -0700153
milind upadhyay1a4663c2021-04-03 19:41:34 -0700154def view_rects():
155
156 rects_dict = load_json()
Ravago Jones5127ccc2022-07-31 16:32:45 -0700157 if (_path.letter.name in rects_dict
158 and _path.alliance.name in rects_dict[_path.letter.name]):
milind upadhyay1a4663c2021-04-03 19:41:34 -0700159 _confirm.ax.set_visible(False)
160 _cancel.ax.set_visible(False)
161 _submit.ax.set_visible(False)
162 _img_ax.imshow(capture_img())
163
164 for rect_list in rects_dict[_path.letter.name][_path.alliance.name]:
165 rect = Rect.from_list(rect_list)
Ravago Jones5127ccc2022-07-31 16:32:45 -0700166 _img_ax.add_patch(
167 patches.Rectangle((rect.x1, rect.y1),
168 rect.x2 - rect.x1,
169 rect.y2 - rect.y1,
170 edgecolor='r',
171 linewidth=1,
172 facecolor="none"))
milind upadhyay1a4663c2021-04-03 19:41:34 -0700173 plt.show()
174 else:
175 glog.error("Could not find path %s %s in rects.json",
Ravago Jones5127ccc2022-07-31 16:32:45 -0700176 _path.alliance.value, _path.letter.value)
177
milind upadhyay1a4663c2021-04-03 19:41:34 -0700178
179def main(argv):
180 global _num_rects
181
182 glog.setLevel("INFO")
Ravago Jones5127ccc2022-07-31 16:32:45 -0700183 opts = getopt.getopt(
184 argv[1:], "a:l:n:",
185 ["alliance = ", "letter = ", "_num_rects = ", "view"])[0]
milind upadhyay1a4663c2021-04-03 19:41:34 -0700186 view = False
187 for opt, arg in opts:
188 if opt in ["-a", "--alliance"]:
189 _path.alliance = Alliance.from_value(arg)
190 elif opt in ["-l", "--letter"]:
191 _path.letter = Letter.from_value(arg.upper())
192 elif opt in ["-n", "--_num_rects"] and arg.isdigit():
193 _num_rects = int(arg)
194 elif opt == "--view":
195 view = True
196
197 if view:
198 view_rects()
199 else:
200 setup_ui()
201
202
203if __name__ == "__main__":
204 main(sys.argv)