John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 1 | from constants import * |
| 2 | import cairo |
| 3 | from color import Color, palette |
| 4 | from points import Points |
| 5 | from drawing_constants import * |
| 6 | from libspline import Spline, DistanceSpline, Trajectory |
| 7 | |
| 8 | AXIS_MARGIN_SPACE = 40 |
| 9 | |
| 10 | |
| 11 | class Graph(): # (TODO): Remove Computer Calculation |
| 12 | def __init__(self, cr, mypoints): |
| 13 | # Background Box |
| 14 | set_color(cr, palette["WHITE"]) |
| 15 | cr.rectangle(-1.0 * SCREEN_SIZE, -0.5 * SCREEN_SIZE, SCREEN_SIZE, |
| 16 | SCREEN_SIZE * 0.6) |
| 17 | cr.fill() |
| 18 | |
| 19 | cr.set_source_rgb(0, 0, 0) |
| 20 | cr.rectangle(-1.0 * SCREEN_SIZE, -0.5 * SCREEN_SIZE, SCREEN_SIZE, |
| 21 | SCREEN_SIZE * 0.6) |
| 22 | #Axis |
| 23 | cr.move_to(-1.0 * SCREEN_SIZE + AXIS_MARGIN_SPACE, |
| 24 | -0.5 * SCREEN_SIZE + AXIS_MARGIN_SPACE) # Y |
| 25 | cr.line_to(-1.0 * SCREEN_SIZE + AXIS_MARGIN_SPACE, |
| 26 | 0.1 * SCREEN_SIZE - 10) |
| 27 | |
| 28 | cr.move_to(-1.0 * SCREEN_SIZE + AXIS_MARGIN_SPACE, |
| 29 | -0.5 * SCREEN_SIZE + AXIS_MARGIN_SPACE) # X |
| 30 | cr.line_to(-10, -0.5 * SCREEN_SIZE + AXIS_MARGIN_SPACE) |
| 31 | cr.stroke() |
| 32 | |
| 33 | skip = 2 |
| 34 | dT = 0.00505 |
| 35 | start = AXIS_MARGIN_SPACE - SCREEN_SIZE |
| 36 | end = -2.0 * AXIS_MARGIN_SPACE |
| 37 | height = 0.5 * (SCREEN_SIZE) - AXIS_MARGIN_SPACE |
| 38 | zero = AXIS_MARGIN_SPACE - SCREEN_SIZE / 2.0 |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 39 | legend_entries = {} |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 40 | if mypoints.getLibsplines(): |
| 41 | distanceSpline = DistanceSpline(mypoints.getLibsplines()) |
| 42 | traj = Trajectory(distanceSpline) |
Ravago Jones | 3b92afa | 2021-02-05 14:27:32 -0800 | [diff] [blame] | 43 | mypoints.addConstraintsToTrajectory(traj) |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 44 | traj.Plan() |
| 45 | XVA = traj.GetPlanXVA(dT) |
James Kuszmaul | c3eaa47 | 2021-03-03 19:43:45 -0800 | [diff] [blame^] | 46 | if XVA is not None: |
Ravago Jones | 26f7ad0 | 2021-02-05 15:45:59 -0800 | [diff] [blame] | 47 | self.draw_x_axis(cr, start, height, zero, XVA, end) |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 48 | self.drawVelocity(cr, XVA, start, height, skip, zero, end, |
| 49 | legend_entries) |
Ravago Jones | 26f7ad0 | 2021-02-05 15:45:59 -0800 | [diff] [blame] | 50 | self.drawAcceleration(cr, XVA, start, height, skip, zero, |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 51 | AXIS_MARGIN_SPACE, end, legend_entries) |
| 52 | self.drawVoltage(cr, XVA, start, height, skip, traj, zero, end, |
| 53 | legend_entries) |
Ravago Jones | 26f7ad0 | 2021-02-05 15:45:59 -0800 | [diff] [blame] | 54 | cr.set_source_rgb(0, 0, 0) |
| 55 | cr.move_to(-1.0 * AXIS_MARGIN_SPACE, zero + height / 2.0) |
| 56 | cr.line_to(AXIS_MARGIN_SPACE - SCREEN_SIZE, |
| 57 | zero + height / 2.0) |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 58 | self.drawLegend(cr, XVA, start, height, skip, zero, end, |
| 59 | legend_entries) |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 60 | cr.stroke() |
| 61 | |
| 62 | def connectLines(self, cr, points, color): |
| 63 | for i in range(0, len(points) - 1): |
| 64 | set_color(cr, color) |
| 65 | cr.move_to(points[i][0], points[i][1]) |
| 66 | cr.line_to(points[i + 1][0], points[i + 1][1]) |
| 67 | cr.stroke() |
| 68 | |
| 69 | def draw_x_axis(self, cr, start, height, zero, xva, end): |
| 70 | total_time = 0.00505 * len(xva[0]) |
| 71 | for k in np.linspace(0, 1, 11): |
| 72 | self.tickMark(cr, |
| 73 | k * np.abs(start - end) + start, zero + height / 2.0, |
| 74 | 10, palette["BLACK"]) |
| 75 | cr.move_to(k * np.abs(start - end) + start, |
| 76 | 10 + zero + height / 2.0) |
| 77 | txt_scale = SCREEN_SIZE / 1000.0 |
| 78 | display_text(cr, str(round(k * total_time, 3)), txt_scale, |
| 79 | txt_scale, 1.0 / txt_scale, 1.0 / txt_scale) |
| 80 | cr.stroke() |
| 81 | |
| 82 | def tickMark(self, cr, x, y, height, COLOR): |
| 83 | # X, Y is in the middle of the tick mark |
| 84 | set_color(cr, COLOR) |
| 85 | cr.move_to(x, y + (height / 2)) |
| 86 | cr.line_to(x, y - (height / 2)) |
| 87 | cr.stroke() |
| 88 | |
| 89 | def HtickMark(self, cr, x, y, width, COLOR): |
| 90 | # X, Y is in the middle of the tick mark |
| 91 | set_color(cr, COLOR) |
| 92 | cr.move_to(x + (width / 2), y) |
| 93 | cr.line_to(x - (width / 2), y) |
| 94 | cr.stroke() |
| 95 | |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 96 | def drawLegend(self, cr, xva, start, height, skip, zero, end, |
| 97 | legend_entries): |
| 98 | step_size = (end - start) / len(legend_entries) |
| 99 | margin_under_x_axis = height * 0.1 |
| 100 | for index, (name, color) in enumerate(legend_entries.items()): |
| 101 | set_color(cr, color) |
| 102 | cr.move_to(start + index * step_size, zero - margin_under_x_axis) |
| 103 | txt_scale = SCREEN_SIZE / 900.0 |
| 104 | display_text(cr, name, txt_scale, txt_scale, 1.0 / txt_scale, |
| 105 | 1.0 / txt_scale) |
| 106 | |
| 107 | def drawVelocity(self, cr, xva, start, height, skip, zero, end, |
| 108 | legend_entries): |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 109 | COLOR = palette["RED"] |
| 110 | velocity = xva[1] |
| 111 | n_timesteps = len(velocity) |
| 112 | max_v = np.amax(velocity) |
| 113 | spacing = np.abs(start - end) / float(n_timesteps) |
| 114 | scaler = height / max_v |
| 115 | cr.set_source_rgb(1, 0, 0) |
| 116 | points = [] |
| 117 | for i in range(0, len(velocity)): |
| 118 | if i % skip == 0: |
| 119 | points.append([ |
| 120 | start + (i * spacing), |
| 121 | zero + height / 2.0 + (velocity[i] * scaler / 2.0) |
| 122 | ]) |
| 123 | self.connectLines(cr, points, COLOR) |
| 124 | |
| 125 | # draw axes marking |
| 126 | for i in np.linspace(-1, 1, 11): |
| 127 | self.HtickMark(cr, start, zero + i * height / 2.0 + height / 2.0, |
| 128 | 10, palette["BLACK"]) |
| 129 | cr.set_source_rgb(1, 0, 0) |
| 130 | cr.move_to(start + 5, zero + i * height / 2.0 + height / 2.0) |
| 131 | txt_scale = SCREEN_SIZE / 1000.0 |
| 132 | display_text(cr, str(round(i * max_v, 2)), txt_scale, txt_scale, |
| 133 | 1.0 / txt_scale, 1.0 / txt_scale) |
| 134 | cr.stroke() |
| 135 | |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 136 | # add entry to legend |
| 137 | legend_entries["Velocity"] = COLOR |
| 138 | |
| 139 | def drawAcceleration(self, cr, xva, start, height, skip, zero, margin, end, |
| 140 | legend_entries): |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 141 | COLOR = palette["BLUE"] |
| 142 | accel = xva[2] |
| 143 | max_a = np.amax(accel) |
| 144 | min_a = np.amin(accel) |
| 145 | n_timesteps = len(accel) |
| 146 | spacing = np.abs(start - end) / float(n_timesteps) |
| 147 | scaler = height / (max_a - min_a) |
| 148 | cr.set_source_rgb(1, 0, 0) |
| 149 | points = [] |
| 150 | for i in range(0, len(accel)): |
| 151 | if i % skip == 0: |
| 152 | points.append([ |
| 153 | start + (i * spacing), zero + ((accel[i] - min_a) * scaler) |
| 154 | ]) |
| 155 | self.connectLines(cr, points, COLOR) |
| 156 | |
| 157 | # draw axes marking |
| 158 | for i in np.linspace(0, 1, 11): |
| 159 | self.HtickMark(cr, -1.5 * margin, zero + i * height, 10, |
| 160 | palette["BLACK"]) |
| 161 | cr.set_source_rgb(0, 0, 1) |
| 162 | cr.move_to(-1.2 * margin, zero + i * height) |
| 163 | txt_scale = SCREEN_SIZE / 1000.0 |
| 164 | display_text(cr, str(round(i * (max_a - min_a) + min_a, |
| 165 | 2)), txt_scale, txt_scale, |
| 166 | 1.0 / txt_scale, 1.0 / txt_scale) |
| 167 | cr.stroke() |
| 168 | |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 169 | # draw legend |
| 170 | legend_entries["Acceleration"] = COLOR |
| 171 | |
| 172 | def drawVoltage(self, cr, xva, start, height, skip, traj, zero, end, |
| 173 | legend_entries): |
| 174 | COLOR_LEFT = palette["GREEN"] |
| 175 | COLOR_RIGHT = palette["CYAN"] |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 176 | poses = xva[0] |
| 177 | n_timesteps = len(poses) |
| 178 | spacing = np.abs(start - end) / float(n_timesteps) |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 179 | points_left = [] |
| 180 | points_right = [] |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 181 | for i in range(0, len(poses)): |
| 182 | if i % skip == 0: |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 183 | # libspline says the order is left-right |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 184 | voltage = traj.Voltage(poses[i]) |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 185 | points_left.append([ |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 186 | start + (i * spacing), |
| 187 | zero + height / 2 + height * (voltage[0] / 24.0) |
| 188 | ]) |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 189 | points_right.append([ |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 190 | start + (i * spacing), |
| 191 | zero + height / 2 + height * (voltage[1] / 24.0) |
| 192 | ]) |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 193 | self.connectLines(cr, points_left, COLOR_LEFT) |
| 194 | self.connectLines(cr, points_right, COLOR_RIGHT) |
John Park | 91e6973 | 2019-03-03 13:12:43 -0800 | [diff] [blame] | 195 | |
| 196 | for i in np.linspace(-1, 1, 7): |
| 197 | self.HtickMark(cr, -1.0 * SCREEN_SIZE, |
| 198 | zero + i * height / 2.0 + height / 2.0, 10, |
| 199 | palette["BLACK"]) |
| 200 | cr.set_source_rgb(0, 1, 1) |
| 201 | cr.move_to(-1.0 * SCREEN_SIZE, |
| 202 | zero + i * height / 2.0 + height / 2.0) |
| 203 | txt_scale = SCREEN_SIZE / 1000.0 |
| 204 | display_text(cr, str(round(i * 12.0, 2)), txt_scale, txt_scale, |
| 205 | 1.0 / txt_scale, 1.0 / txt_scale) |
| 206 | cr.stroke() |
Ravago Jones | e44becc | 2021-01-16 17:41:48 -0800 | [diff] [blame] | 207 | |
| 208 | legend_entries["Left Voltage"] = COLOR_LEFT |
| 209 | legend_entries["Right Voltage"] = COLOR_RIGHT |