1import matplotlib.pyplot
as plt
8 A class to interactively track and mark points on a matplotlib plot.
11 - Marking yellow and blue cones (track positions).
12 - Setting an initial position.
13 - Defining a target for orientation.
14 - Selecting two points for a final rectangular box.
16 Data is saved to a file when the user finishes.
21 self.
fig, self.
ax = plt.subplots(figsize=(10, 6))
43 self.
fig.canvas.mpl_disconnect(self.
fig.canvas.manager.key_press_handler_id)
49 self.
fig.canvas.draw()
52 """Configure the matplotlib plot with title, labels, gridlines, and limits."""
53 title = (
'Track Setup Tool\n'
54 'Y: Yellow Cones, B: Blue Cones\n'
55 'P: Initial Position, T: Target for Orientation\n'
56 'F: Final Box Points\n'
57 'Right-click to Finish')
58 self.
ax.set_title(title)
59 self.
ax.set_xlabel(
'X Coordinate')
60 self.
ax.set_ylabel(
'Y Coordinate')
62 self.
ax.minorticks_on()
63 self.
ax.grid(which=
'minor', linestyle=
':', linewidth=0.5)
64 self.
ax.grid(which=
'major', linestyle=
'-', linewidth=1)
65 self.
ax.set_xlim(-5, 40)
66 self.
ax.set_ylim(-5, 40)
67 self.
ax.set_autoscale_on(
False)
70 """Connect mouse and key events to their handlers."""
75 """Delegate key press actions to helper methods."""
76 key = event.key.lower()
87 elif event.key ==
'ctrl+z':
89 self.
fig.canvas.draw()
92 """Set mode for adding cones of a given color."""
95 title_color =
"Yellow" if color ==
'yellow' else "Blue"
96 self.
ax.set_title(f
"Adding {title_color} Cones\nLeft-click to add, Right-click to finish\nCtrl+Z to undo")
99 """Reset the initial position and clear any orientation markers."""
100 self.
mode =
'init_pos'
106 self.
ax.set_title(
'Select Initial Position')
109 """Prepare to select a target point for orientation."""
114 self.
ax.set_title(
'Select Target Point for Orientation')
117 """Initialize final box mode and clear any previous box."""
118 self.
mode =
'final_box'
123 self.
ax.set_title(
'Select First Point of Final Box')
126 """Remove the last added cone point and update the display."""
135 display_colors = [
'yellow' if c ==
'yellow_cone' else 'blue' for c
in self.
colors]
145 """Remove a marker attribute if it exists."""
146 marker = getattr(self, marker_name,
None)
149 setattr(self, marker_name,
None)
152 """Route mouse click events based on button and current mode."""
153 if event.inaxes != self.
ax:
155 if event.button == 1:
157 elif event.button == 3:
159 self.
fig.canvas.draw()
162 """Process a left-click event depending on the current mode."""
163 if self.
mode in [
'yellow',
'blue']:
165 elif self.
mode ==
'init_pos':
169 elif self.
mode ==
'final_box':
173 """On right-click, save data (if any) and close the plot."""
179 """Add a cone point and update the scatter plot."""
185 display_colors = [
'yellow' if c ==
'yellow_cone' else 'blue' for c
in self.
colors]
195 """Set the initial position and mark it on the plot."""
196 self.
init_pos = (event.xdata, event.ydata)
205 label=
'Initial Position'
207 self.
ax.set_title(
'Press F to set orientation')
210 """Set the target point, compute orientation, and update markers."""
231 """Collect final box points and draw the rectangle if two points are set."""
237 """Draw the rectangle representing the final box."""
257 Calculate the angle (in radians) between two points relative to the horizontal axis.
261 return math.atan2(dy, dx)
265 Save the configuration (initial position, orientation, final box, and cones)
268 filename =
'cones.txt'
269 filepath = os.path.join(
"/home/ws/src/planning/test/integration_tests/tests/", filename)
270 with open(filepath,
'w')
as f:
272 f.write(f
'P {self.init_pos[0]:.1f} {self.init_pos[1]:.1f} {self.theta:.6f}\n')
278 f.write(f
'F {x1:.1f} {x2:.1f} {y1:.1f} {y2:.1f}\n')
280 f.write(f
'C {x:.1f} {y:.1f} {color}\n')
281 print(f
"Data saved to {filepath}")
285 Main function to display instructions and run the Track Setup Tool.
287 print(
"Track Setup Tool")
288 print(
"1. Press 'Y' for yellow cones")
289 print(
"2. Press 'B' for blue cones")
290 print(
"3. Press 'P' to set initial position")
291 print(
"4. Press 'T' to set orientation target")
292 print(
"5. Press 'F' to set final box (2 points)")
293 print(
"6. Left-click to add points")
294 print(
"7. Right-click to finish and save")
299if __name__ ==
'__main__':
add_final_box_point(self, event)
reset_initial_position(self)
calculate_theta(self, p1, p2)
remove_marker(self, marker_name)
handle_left_click(self, event)
set_cone_mode(self, color)
set_initial_position(self, event)