root / trunk / code / projects / mapping / python / map.py @ 935
History | View | Annotate | Download (7 KB)
| 1 | #!/usr/bin/env python |
|---|---|
| 2 | |
| 3 | from scipy import linalg, array |
| 4 | from gtk import * |
| 5 | from socket import * |
| 6 | from struct import * |
| 7 | import gobject |
| 8 | import sys, pickle, pygtk, gtk, string, cairo, gobject, math, weakref |
| 9 | from random import random |
| 10 | |
| 11 | #mine |
| 12 | from model import model |
| 13 | |
| 14 | pi = 3.1415927 |
| 15 | |
| 16 | #stolen from emily |
| 17 | BOT_IR = [[4.5, 3.5], [7.5, 0], [4.5, -3.5], [-4, -3.5], [-4, 3.5]] |
| 18 | ANGLE_IR = [[.78, .63], [1, 0], [0.78, -.63], [0, -1], [0,1]] |
| 19 | |
| 20 | #endmine |
| 21 | |
| 22 | class map_model(model): |
| 23 | def __init__(self): |
| 24 | self.eqn = [] |
| 25 | |
| 26 | def __setattr__(self,name,value): |
| 27 | self.__dict__[name] = value |
| 28 | self.changed() |
| 29 | |
| 30 | def add_eqn(self, eqn): |
| 31 | self.eqn = [eqn] + self.eqn |
| 32 | |
| 33 | hostname = 'localhost' |
| 34 | |
| 35 | class Screen(gtk.DrawingArea): |
| 36 | __gsignals__ = { "expose-event" : "override" }
|
| 37 | |
| 38 | def __init__ (self, socket): |
| 39 | gtk.DrawingArea.__init__(self) |
| 40 | |
| 41 | self.xres, self.yres = (800,800) |
| 42 | |
| 43 | self.set_size_request(self.xres, self.yres) |
| 44 | |
| 45 | self.socket = socket |
| 46 | self.bots = [i for i in xrange(16)] |
| 47 | self.ir_pts = [] |
| 48 | |
| 49 | self.draw = map_model() |
| 50 | self.draw.bot = [[1,1,pi/2],0] # x y theta |
| 51 | self.draw.add_dependent(self.redraw) |
| 52 | |
| 53 | self.scale_const = 50 |
| 54 | self.xdisp = 400 |
| 55 | self.ydisp = 400 |
| 56 | self.nticks = 21 |
| 57 | self.units = 10 |
| 58 | |
| 59 | def add_scale_button_ref(self, scale_button): |
| 60 | self.scale_button = scale_button |
| 61 | |
| 62 | |
| 63 | def redraw(self, eqn): |
| 64 | self.ir_scale = self.scale_button.get_value() |
| 65 | self.clear_area() |
| 66 | self.draw_bot() |
| 67 | self.draw_grid() |
| 68 | self.draw_ir_pts() |
| 69 | |
| 70 | def do_expose_event(self, event): |
| 71 | self.redraw(None) |
| 72 | |
| 73 | def clear_area(self): |
| 74 | self.ctx = self.window.cairo_create() |
| 75 | self.ctx.rectangle(0,0,1000,1000) |
| 76 | self.ctx.set_source_rgb(1,1,1) |
| 77 | self.ctx.fill() |
| 78 | |
| 79 | def draw_ir_pts(self): |
| 80 | self.ctx = self.window.cairo_create() |
| 81 | self.ctx.new_path() |
| 82 | self.ctx.set_source_rgb(0,0,1) |
| 83 | |
| 84 | for pt in self.ir_pts: |
| 85 | x,y = pt |
| 86 | self.ctx.move_to(x * self.ir_scale, y * self.ir_scale) |
| 87 | self.ctx.rel_line_to(2,2) |
| 88 | self.ctx.stroke() |
| 89 | |
| 90 | |
| 91 | def draw_bot(self): |
| 92 | self.ctx = self.window.cairo_create() |
| 93 | self.ctx.new_path() |
| 94 | |
| 95 | tbot = self.draw.bot |
| 96 | print tbot |
| 97 | x, y, theta = tbot[:3] |
| 98 | y = -y #because we don't want to draw down more units |
| 99 | |
| 100 | #draw blob |
| 101 | self.ctx.set_source_rgb(0,1,0) |
| 102 | xscl = (self.xres - self.xdisp) / self.units |
| 103 | yscl = (self.yres - self.ydisp) / self.units |
| 104 | |
| 105 | cx = x * xscl + self.xdisp |
| 106 | cy = y * yscl + self.ydisp |
| 107 | self.ctx.arc(cx, cy, 20, 0, 2*pi) |
| 108 | self.ctx.fill() |
| 109 | |
| 110 | #draw "arrow" |
| 111 | self.ctx.set_source_rgb(0,0,1) |
| 112 | self.ctx.arc(cx,cy, 5, 0, 2*pi) |
| 113 | self.ctx.fill() |
| 114 | |
| 115 | self.ctx.move_to(cx,cy) |
| 116 | dx = 20 * math.cos(theta + 0.05) |
| 117 | dy = -20 * math.sin(theta + 0.05) |
| 118 | dx = int(dx) |
| 119 | dy = int(dy) |
| 120 | |
| 121 | self.ctx.rel_line_to(dx, dy) |
| 122 | self.ctx.stroke() |
| 123 | |
| 124 | def draw_grid(self): |
| 125 | |
| 126 | self.ctx.set_source_rgb(0,0,0) |
| 127 | self.ctx.new_path() |
| 128 | |
| 129 | #vertical |
| 130 | self.ctx.move_to(400,0) |
| 131 | self.ctx.rel_line_to(0,800) |
| 132 | self.ctx.stroke() |
| 133 | |
| 134 | #vticks |
| 135 | self.ctx.move_to(400,0) |
| 136 | for i in range( self.nticks + 1 ): |
| 137 | self.ctx.rel_line_to(5,0) |
| 138 | self.ctx.stroke() |
| 139 | self.ctx.move_to(400, i * 800 / self.nticks) |
| 140 | |
| 141 | #horiz |
| 142 | self.ctx.move_to(0,400) |
| 143 | self.ctx.rel_line_to(800,0) |
| 144 | self.ctx.stroke() |
| 145 | |
| 146 | #hticks |
| 147 | self.ctx.move_to(0,400) |
| 148 | for i in range(self.nticks + 1): |
| 149 | self.ctx.rel_line_to(0,-5) |
| 150 | self.ctx.stroke() |
| 151 | self.ctx.move_to(i * 800 / self.nticks, 400) |
| 152 | |
| 153 | def draw_graph(self, equations, n): |
| 154 | self.ctx = self.window.cairo_create() |
| 155 | self.ctx.set_source_rgb(0,0,0) |
| 156 | self.ctx.new_path() |
| 157 | |
| 158 | for equn in equations: |
| 159 | xmin, xmax = equn[-2],equn[-1] |
| 160 | eqn = equn[:-2] |
| 161 | dx = float(xmax - xmin) / n |
| 162 | x = xmin |
| 163 | y = 0 |
| 164 | for i in range(len(eqn)): |
| 165 | y += eqn[-1 * i - 1] * ( x ** i) |
| 166 | |
| 167 | self.ctx.move_to(self.x_disp + x * self.scale_const,400 - y * self.scale_const) |
| 168 | |
| 169 | for diffel in range(1,n+1): |
| 170 | x = xmin + diffel * dx |
| 171 | y = 0 |
| 172 | for i in range(len(eqn)): |
| 173 | y += eqn[-1 * i - 1] * ( x ** i) |
| 174 | self.ctx.line_to(self.x_disp + int(x * self.scale_const),400 - int(y * self.scale_const)) |
| 175 | self.ctx.stroke() |
| 176 | self.ctx.move_to(self.x_disp + int(x * self.scale_const),400 - int(y * self.scale_const)) |
| 177 | |
| 178 | def receive_info(self): |
| 179 | |
| 180 | buf = self.socket.recv(100) |
| 181 | if (buf): |
| 182 | items = unpack('4c2hf5h',buf)
|
| 183 | src = ord(items[0]) |
| 184 | old = self.draw.bot #the info of bot src at prev iter |
| 185 | newx = items[4] / 30.0 |
| 186 | newy = items[5] / 30.0 |
| 187 | new = [newx, newy] + [items[i] for i in range(6,12)] |
| 188 | |
| 189 | for ir_ind in range(5): |
| 190 | ir_reading = items[ir_ind + 7] |
| 191 | if ir_reading != -1: |
| 192 | vec = map(lambda y: ir_reading * y, ANGLE_IR[ir_ind]) |
| 193 | vec = map(lambda x,y: x+y, vec, BOT_IR[ir_ind]) |
| 194 | |
| 195 | R = math.sqrt(vec[0]**2 + vec[1] ** 2) |
| 196 | ttheta = math.atan2(vec[1], vec[0]) |
| 197 | ttheta += items[6] |
| 198 | |
| 199 | reading_x = (R * math.cos(ttheta)) + newx |
| 200 | reading_y = (R * math.sin(ttheta)) + newy |
| 201 | |
| 202 | self.ir_pts.append([reading_x, reading_y]) |
| 203 | |
| 204 | |
| 205 | self.draw.bot = new |
| 206 | |
| 207 | return True |
| 208 | |
| 209 | |
| 210 | def solve(lisvals): |
| 211 | p0y, p1y, m0y, m1y, x0, x1 = lisvals |
| 212 | A = array([[x0**3 , x0**2 , x0 , 1], |
| 213 | [x1**3 , x1**2 , x1 , 1], |
| 214 | [3 * x0**2 , 2 * x0 , 1 , 0], |
| 215 | [3 * x1**2 , 2 * x1 , 1 , 0]]) |
| 216 | |
| 217 | B = array([p0y, p1y, m0y, m1y]) |
| 218 | tarr = linalg.solve(A,B) |
| 219 | lis = [] |
| 220 | for i in range(4): |
| 221 | lis.append(tarr[i]) |
| 222 | return lis + [0,1] |
| 223 | |
| 224 | def main(): |
| 225 | |
| 226 | window = gtk.Window() |
| 227 | window.connect("delete-event", gtk.main_quit)
|
| 228 | |
| 229 | sock = socket() |
| 230 | sock.connect((hostname, int(sys.argv[1]))) |
| 231 | |
| 232 | mywidg = Screen(sock) |
| 233 | |
| 234 | bigbox = gtk.HBox() |
| 235 | bigbox.pack_start(mywidg, True, True, 0) |
| 236 | |
| 237 | buttonbox = gtk.VBox() |
| 238 | bigbox.pack_end(buttonbox, False, False, 0) |
| 239 | |
| 240 | IRScale = gtk.ScaleButton(10, 0, 100, 10) |
| 241 | buttonbox.pack_start(IRScale, False, False, 0) |
| 242 | |
| 243 | mywidg.add_scale_button_ref(IRScale) |
| 244 | |
| 245 | window.add(bigbox) |
| 246 | bigbox.show() |
| 247 | mywidg.show() |
| 248 | buttonbox.show() |
| 249 | IRScale.show() |
| 250 | window.show() |
| 251 | |
| 252 | gobject.idle_add(mywidg.receive_info) |
| 253 | gtk.main() |
| 254 | |
| 255 | if __name__=='__main__': |
| 256 | if (len(sys.argv) < 2): #or not str.isdecimal(sys.argv[1])): |
| 257 | print("Usage: %s <portno>" % sys.argv[0])
|
| 258 | sys.exit() |
| 259 | |
| 260 | main() |