From 2e95e3a33bcb34aeec66551503c692c1cb80ab61 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 9 Feb 2009 20:05:30 +0100 Subject: * all python: - changed tabs to spaces. --- host/inter/dist_sensor.py | 88 ++++----- host/inter/drawable.py | 176 +++++++++--------- host/inter/inter.py | 380 +++++++++++++++++++-------------------- host/inter/inter_node.py | 266 +++++++++++++-------------- host/inter/path.py | 12 +- host/inter/test/test_drawable.py | 48 ++--- host/inter/trans_matrix.py | 226 +++++++++++------------ host/mex/hub.py | 268 +++++++++++++-------------- host/mex/msg.py | 96 +++++----- host/mex/node.py | 188 +++++++++---------- host/mex/test/test.py | 20 +-- host/proto/popen_io.py | 22 +-- host/proto/proto.py | 228 +++++++++++------------ host/proto/test/fio.py | 24 +-- host/proto/test/interactive.py | 2 +- host/utils/forked.py | 18 +- 16 files changed, 1031 insertions(+), 1031 deletions(-) (limited to 'host') diff --git a/host/inter/dist_sensor.py b/host/inter/dist_sensor.py index 54c61e6d..b1bd0d0d 100644 --- a/host/inter/dist_sensor.py +++ b/host/inter/dist_sensor.py @@ -32,51 +32,51 @@ class DistSensor (Drawable): """A distance sensor.""" def __init__ (self, onto, pos, angle, range): - Drawable.__init__ (self, onto) - self.pos = pos - self.angle = angle - self.range = range - self.target = (pos[0] + cos (angle) * range, - pos[1] + sin (angle) * range) - self.obstacles = [ ] - self.distance = None - self.hide = False + Drawable.__init__ (self, onto) + self.pos = pos + self.angle = angle + self.range = range + self.target = (pos[0] + cos (angle) * range, + pos[1] + sin (angle) * range) + self.obstacles = [ ] + self.distance = None + self.hide = False def compute (self): - # Could do better by trans_applying until on the same drawable as the - # obstacle. - pos = self.onto.trans_apply (self.pos) - target = self.onto.trans_apply (self.target) - n = ((target[0] - pos[0]) / self.range, - (target[1] - pos[1]) / self.range) - self.distance = None - for o in self.obstacles: - # Does the line intersect with the obstacle? - ao = (o.pos[0] - pos[0], o.pos[1] - pos[1]) - doc = abs (ao[0] * -n[1] + ao[1] * n[0]) - if doc < o.radius: - # Does the segment intersect? - m = ao[0] * n[0] + ao[1] * n[1] - f = sqrt (o.radius ** 2 - doc ** 2) - if m - f > 0 and m - f < self.range: - d = m - f - if self.distance is None or self.distance > d: - self.distance = d - elif m + f > 0 and m + f < self.range: - d = m + f - if self.distance is None or self.distance > d: - self.distance = d - return self.distance + # Could do better by trans_applying until on the same drawable as the + # obstacle. + pos = self.onto.trans_apply (self.pos) + target = self.onto.trans_apply (self.target) + n = ((target[0] - pos[0]) / self.range, + (target[1] - pos[1]) / self.range) + self.distance = None + for o in self.obstacles: + # Does the line intersect with the obstacle? + ao = (o.pos[0] - pos[0], o.pos[1] - pos[1]) + doc = abs (ao[0] * -n[1] + ao[1] * n[0]) + if doc < o.radius: + # Does the segment intersect? + m = ao[0] * n[0] + ao[1] * n[1] + f = sqrt (o.radius ** 2 - doc ** 2) + if m - f > 0 and m - f < self.range: + d = m - f + if self.distance is None or self.distance > d: + self.distance = d + elif m + f > 0 and m + f < self.range: + d = m + f + if self.distance is None or self.distance > d: + self.distance = d + return self.distance def draw (self): - self.compute () - self.reset () - if self.hide: - return - if self.distance is None: - self.draw_line (self.pos, self.target, fill = 'blue', arrow = LAST) - else: - inter = (self.pos[0] + cos (self.angle) * self.distance, - self.pos[1] + sin (self.angle) * self.distance) - self.draw_line (self.pos, inter, fill = 'red', arrow = LAST) - self.draw_line (inter, self.target, fill = 'blue', arrow = LAST) + self.compute () + self.reset () + if self.hide: + return + if self.distance is None: + self.draw_line (self.pos, self.target, fill = 'blue', arrow = LAST) + else: + inter = (self.pos[0] + cos (self.angle) * self.distance, + self.pos[1] + sin (self.angle) * self.distance) + self.draw_line (self.pos, inter, fill = 'red', arrow = LAST) + self.draw_line (inter, self.target, fill = 'blue', arrow = LAST) diff --git a/host/inter/drawable.py b/host/inter/drawable.py index 26628f40..81331548 100644 --- a/host/inter/drawable.py +++ b/host/inter/drawable.py @@ -32,78 +32,78 @@ class Drawable: """Define a drawable area with embedded transformations.""" def __init__ (self, onto): - """Initialise the drawable.""" - self.onto = onto - self.trans_matrix = trans_matrix.TransMatrix () - self.items = [ ] - self.trans_apply = self.trans_matrix.apply - self.trans_apply_angle = self.trans_matrix.apply_angle - self.trans_apply_distance = self.trans_matrix.apply_distance - self.trans_rotate = self.trans_matrix.rotate - self.trans_translate = self.trans_matrix.translate - self.trans_scale = self.trans_matrix.scale + """Initialise the drawable.""" + self.onto = onto + self.trans_matrix = trans_matrix.TransMatrix () + self.items = [ ] + self.trans_apply = self.trans_matrix.apply + self.trans_apply_angle = self.trans_matrix.apply_angle + self.trans_apply_distance = self.trans_matrix.apply_distance + self.trans_rotate = self.trans_matrix.rotate + self.trans_translate = self.trans_matrix.translate + self.trans_scale = self.trans_matrix.scale def __draw_rectangle (self, p1, p2, **kw): - if 'outline' not in kw: - kw = kw.copy () - kw['outline'] = 'black' - p = self.trans_apply (p1, (p2[0], p1[1]), p2, (p1[0], p2[1])) - return self.onto.__draw_polygon (*p, **kw) + if 'outline' not in kw: + kw = kw.copy () + kw['outline'] = 'black' + p = self.trans_apply (p1, (p2[0], p1[1]), p2, (p1[0], p2[1])) + return self.onto.__draw_polygon (*p, **kw) def __draw_line (self, *p, **kw): - p = self.trans_apply (*p) - return self.onto.__draw_line (*p, **kw) + p = self.trans_apply (*p) + return self.onto.__draw_line (*p, **kw) def __draw_polygon (self, *p, **kw): - p = self.trans_apply (*p) - return self.onto.__draw_polygon (*p, **kw) + p = self.trans_apply (*p) + return self.onto.__draw_polygon (*p, **kw) def __draw_circle (self, p, r, **kw): - p = self.trans_apply (p) - r = self.trans_apply_distance (r) - return self.onto.__draw_circle (p, r, **kw) + p = self.trans_apply (p) + r = self.trans_apply_distance (r) + return self.onto.__draw_circle (p, r, **kw) def __draw_arc (self, p, r, **kw): - p = self.trans_apply (p) - r = self.trans_apply_distance (r) - if 'start' in kw: - kw = kw.copy () - kw['start'] = self.trans_apply_angle (kw['start']) - import math - return self.onto.__draw_arc (p, r, **kw) + p = self.trans_apply (p) + r = self.trans_apply_distance (r) + if 'start' in kw: + kw = kw.copy () + kw['start'] = self.trans_apply_angle (kw['start']) + import math + return self.onto.__draw_arc (p, r, **kw) def draw_rectangle (self, *p, **kw): - """Draw a rectangle.""" - self.items.append (self.__draw_rectangle (*p, **kw)) + """Draw a rectangle.""" + self.items.append (self.__draw_rectangle (*p, **kw)) def draw_line (self, *p, **kw): - """Draw a line.""" - self.items.append (self.__draw_line (*p, **kw)) + """Draw a line.""" + self.items.append (self.__draw_line (*p, **kw)) def draw_polygon (self, *p, **kw): - """Draw a line.""" - self.items.append (self.__draw_polygon (*p, **kw)) + """Draw a line.""" + self.items.append (self.__draw_polygon (*p, **kw)) def draw_circle (self, p, r, **kw): - """Draw a circle of the given radius centered on p.""" - self.items.append (self.__draw_circle (p, r, **kw)) + """Draw a circle of the given radius centered on p.""" + self.items.append (self.__draw_circle (p, r, **kw)) def draw_arc (self, p, r, **kw): - """Draw a arc of the given radius centered on p.""" - self.items.append (self.__draw_arc (p, r, **kw)) + """Draw a arc of the given radius centered on p.""" + self.items.append (self.__draw_arc (p, r, **kw)) def trans_reset (self): - """Reset transformations.""" - self.trans_matrix.identity () + """Reset transformations.""" + self.trans_matrix.identity () def reset (self): - self.__delete (*self.items) - self.items = [ ] - self.trans_reset () + self.__delete (*self.items) + self.items = [ ] + self.trans_reset () def __delete (self, *list): - """Delete a list of items.""" - self.onto.__delete (*list) + """Delete a list of items.""" + self.onto.__delete (*list) class DrawableCanvas(Tkinter.Canvas): @@ -111,62 +111,62 @@ class DrawableCanvas(Tkinter.Canvas): the draw method.""" def __init__ (self, width, height, xorigin, yorigin, master = None, **kw): - """Initialise a DrawableCanvas. The width and height parameters - define the requested drawable area virtual size. The xorigin and - yorigin parameters define origin of the virtual coordinates relative - to the drawable center.""" - Tkinter.Canvas.__init__ (self, master, **kw) - self.__width = width - self.__height = height - self.__xorigin = xorigin - self.__yorigin = yorigin - self.bind ('', self.__resize) + """Initialise a DrawableCanvas. The width and height parameters + define the requested drawable area virtual size. The xorigin and + yorigin parameters define origin of the virtual coordinates relative + to the drawable center.""" + Tkinter.Canvas.__init__ (self, master, **kw) + self.__width = width + self.__height = height + self.__xorigin = xorigin + self.__yorigin = yorigin + self.bind ('', self.__resize) def __resize (self, ev): - # Compute new scale. - w, h = float (ev.width), float (ev.height) - self.__scale = min (w / self.__width, h / self.__height) - self.__xoffset = w / 2 + self.__xorigin * self.__scale - self.__yoffset = h / 2 - self.__yorigin * self.__scale - # Redraw. - self.draw () + # Compute new scale. + w, h = float (ev.width), float (ev.height) + self.__scale = min (w / self.__width, h / self.__height) + self.__xoffset = w / 2 + self.__xorigin * self.__scale + self.__yoffset = h / 2 - self.__yorigin * self.__scale + # Redraw. + self.draw () def _Drawable__draw_line (self, *p, **kw): - p = self.__coord (*p) - return self.create_line (*p, **kw) + p = self.__coord (*p) + return self.create_line (*p, **kw) def _Drawable__draw_polygon (self, *p, **kw): - p = self.__coord (*p) - return self.create_polygon (*p, **kw) + p = self.__coord (*p) + return self.create_polygon (*p, **kw) def _Drawable__draw_circle (self, p, r, **kw): - p, = self.__coord (p) - r = r * self.__scale - p1 = (p[0] - r, p[1] - r) - p2 = (p[0] + r, p[1] + r) - return self.create_oval (p1, p2, **kw) + p, = self.__coord (p) + r = r * self.__scale + p1 = (p[0] - r, p[1] - r) + p2 = (p[0] + r, p[1] + r) + return self.create_oval (p1, p2, **kw) def _Drawable__draw_arc (self, p, r, **kw): - p, = self.__coord (p) - r = r * self.__scale - p1 = (p[0] - r, p[1] - r) - p2 = (p[0] + r, p[1] + r) - for k in ('start', 'extent'): - if k in kw: - kw = kw.copy () - kw[k] = degrees (kw[k]) - return self.create_arc (p1, p2, **kw) + p, = self.__coord (p) + r = r * self.__scale + p1 = (p[0] - r, p[1] - r) + p2 = (p[0] + r, p[1] + r) + for k in ('start', 'extent'): + if k in kw: + kw = kw.copy () + kw[k] = degrees (kw[k]) + return self.create_arc (p1, p2, **kw) def _Drawable__delete (self, *list): - self.delete (*list) + self.delete (*list) def __coord (self, *args): - return [ (i[0] * self.__scale + self.__xoffset, - -i[1] * self.__scale + self.__yoffset) for i in args ] + return [ (i[0] * self.__scale + self.__xoffset, + -i[1] * self.__scale + self.__yoffset) for i in args ] def screen_coord (self, screen): - """Return drawable coordinates corresponding to the given screen - coordinates.""" - return ((self.canvasx (screen[0]) - self.__xoffset) / self.__scale, - -(self.canvasy (screen[1]) - self.__yoffset) / self.__scale) + """Return drawable coordinates corresponding to the given screen + coordinates.""" + return ((self.canvasx (screen[0]) - self.__xoffset) / self.__scale, + -(self.canvasy (screen[1]) - self.__yoffset) / self.__scale) diff --git a/host/inter/inter.py b/host/inter/inter.py index cde1bd73..4c19e5c8 100644 --- a/host/inter/inter.py +++ b/host/inter/inter.py @@ -31,105 +31,105 @@ class Robot (Drawable): """The robot.""" def __init__ (self, onto): - Drawable.__init__ (self, onto) - self.drawn = [ ] + Drawable.__init__ (self, onto) + self.drawn = [ ] def draw (self): - self.reset () - self.trans_rotate (self.angle) - self.trans_translate (self.pos) - self.draw_polygon ((115, 30), (170, 85), (150, 127), (130, 145), - (-25, 200), (-70, 200), (-70, -200), (-25, -200), - (130, -145), (150, -127), (170, -85), (115, -30)) - axes_fill = '#404040' - self.draw_line ((-70, 0), (170, 0), fill = axes_fill, arrow = LAST) - f = 142 + 2 * 31.5 - 13.5 - wr = 63 / 2 - self.draw_line ((0, +f / 2), (0, -f / 2), fill = axes_fill) - self.draw_line ((-wr, f / 2), (+wr, f / 2), fill = axes_fill) - self.draw_line ((-wr, -f / 2), (+wr, -f / 2), fill = axes_fill) - for i in self.drawn: - i.draw () + self.reset () + self.trans_rotate (self.angle) + self.trans_translate (self.pos) + self.draw_polygon ((115, 30), (170, 85), (150, 127), (130, 145), + (-25, 200), (-70, 200), (-70, -200), (-25, -200), + (130, -145), (150, -127), (170, -85), (115, -30)) + axes_fill = '#404040' + self.draw_line ((-70, 0), (170, 0), fill = axes_fill, arrow = LAST) + f = 142 + 2 * 31.5 - 13.5 + wr = 63 / 2 + self.draw_line ((0, +f / 2), (0, -f / 2), fill = axes_fill) + self.draw_line ((-wr, f / 2), (+wr, f / 2), fill = axes_fill) + self.draw_line ((-wr, -f / 2), (+wr, -f / 2), fill = axes_fill) + for i in self.drawn: + i.draw () class Obstacle (Drawable): """An obstacle.""" def __init__ (self, onto, pos, radius): - Drawable.__init__ (self, onto) - self.pos = pos - self.radius = radius + Drawable.__init__ (self, onto) + self.pos = pos + self.radius = radius def draw (self): - self.reset () - self.trans_translate (self.pos) - self.draw_circle ((0, 0), self.radius, fill = '#31aa23') - self.draw_circle ((0, 0), self.radius + 250, outlinestipple = 'gray25') + self.reset () + self.trans_translate (self.pos) + self.draw_circle ((0, 0), self.radius, fill = '#31aa23') + self.draw_circle ((0, 0), self.radius + 250, outlinestipple = 'gray25') class Table (Drawable): """The table and its elements.""" def draw (self): - # Redraw. - self.reset () - # Table. - self.draw_rectangle ((-22, -22 - 80), (3000 / 2, 2100 + 22), fill = '#ff1f1f') - self.draw_rectangle ((3000 / 2, -22 - 80), (3000 + 22, 2100 + 22), fill = '#201fff') - self.draw_rectangle ((0, 0), (3000, 2100), fill = '#a49d8b') - self.draw_rectangle ((0, -22 - 80), (3000, -22), fill = '#a49d8b') - self.draw_rectangle ((0, 2100 - 500), (500, 2100), fill = '#201fff') - self.draw_rectangle ((3000 - 500, 2100 - 500), (3000, 2100), fill = '#ff1f1f') - self.draw_line ((3000 / 2, -22 - 80), (3000 / 2, 2100 + 22)) - # Axes. - self.draw_line ((0, 200), (0, 0), (200, 0), arrow = BOTH) - # Beacons and baskets. - self.draw_rectangle ((-22, 2100), (-22 - 80, 2100 + 80), fill = '#5b5b5d') - self.draw_rectangle ((-22, 1050 - 40), (-22 - 80, 1050 + 40), fill = '#5b5b5d') - self.draw_rectangle ((-22, 500), (-22 - 80, 500 + 80), fill = '#5b5b5d') - self.draw_rectangle ((-22, -80), (-22 - 80, 0), fill = '#5b5b5d') - self.draw_rectangle ((-22, 0), (-22 - 80, 500), fill = '#5b5b5d') - self.draw_rectangle ((-22 - 80 - 250, 0), (-22 - 80, 500), fill = '#6d6dad', stipple = 'gray75') - self.draw_rectangle ((3000 + 22, 2100), (3000 + 22 + 80, 2100 + 80), fill = '#5b5b5d') - self.draw_rectangle ((3000 + 22, 1050 - 40), (3000 + 22 + 80, 1050 + 40), fill = '#5b5b5d') - self.draw_rectangle ((3000 + 22, 500), (3000 + 22 + 80, 500 + 80), fill = '#5b5b5d') - self.draw_rectangle ((3000 + 22, -80), (3000 + 22 + 80, 0), fill = '#5b5b5d') - self.draw_rectangle ((3000 + 22, 0), (3000 + 22 + 80, 500), fill = '#5b5b5d') - self.draw_rectangle ((3000 + 22 + 80 + 250, 0), (3000 + 22 + 80, 500), fill = '#6d6dad', stipple = 'gray75') - # Vertical dispensers. - self.draw_rectangle ((-22, 2100 - 750 - 85 / 2), (0, 2100 - 750 + 85 / 2), fill = '#5b5b5b') - self.draw_circle ((40, 2100 - 750), 40) - self.draw_rectangle ((700 - 85 / 2, 2100), (700 + 85 / 2, 2100 + 22), fill = '#5b5b5b') - self.draw_circle ((700, 2100 - 40), 40) - self.draw_rectangle ((3000 + 22, 2100 - 750 - 85 / 2), (3000, 2100 - 750 + 85 / 2), fill = '#5b5b5b') - self.draw_circle ((3000 - 40, 2100 - 750), 40) - self.draw_rectangle ((3000 - 700 + 85 / 2, 2100), (3000 - 700 - 85 / 2, 2100 + 22), fill = '#5b5b5b') - self.draw_circle ((3000 - 700, 2100 - 40), 40) - # Horizontal dispenser. - self.draw_rectangle ((3000 / 2 - 924 / 2, 2100 + 22), (3000 / 2 + 924 / 2, 2100 + 22 + 80 + 22), fill = '#5b5b5b') - self.draw_rectangle ((3000 / 2 - 924 / 2 + 22, 2100 + 22), (3000 / 2 + 924 / 2 - 22, 2100 + 22 + 80), fill = '#5b5b5b') - self.draw_rectangle ((3000 / 2 - 880 / 2 - 35 - 60, 2100), (3000 / 2 - 880 / 2 - 35, 2100 + 44), fill = '#5b5b5b') - self.draw_rectangle ((3000 / 2 + 880 / 2 + 35 + 60, 2100), (3000 / 2 + 880 / 2 + 35, 2100 + 44), fill = '#5b5b5b') - # Balls. - balls = [ (800, 200, 'rb'), (800, 400, 'RB'), (800, 600, 'ww'), - (1300, 200, 'rb'), (1300, 400, 'rb'), (1300, 600, 'ww'), - (520, 800, 'WW'), (700, 40, 'RB'), (40, 750, 'WW'), - (450, 1120, 'ww'), (750, 1070, 'ww'), (1050, 1020, 'ww'), - (1500 - 72 / 2, -22 - 80 / 2, 'BR'), - (1500 - 72 / 2 - 1 * 73, -22 - 80 / 2, 'RB'), - (1500 - 72 / 2 - 2 * 73, -22 - 80 / 2, 'BR'), - (1500 - 72 / 2 - 3 * 73, -22 - 80 / 2, 'RB'), - (1500 - 72 / 2 - 4 * 73, -22 - 80 / 2, 'BR'), - (1500 - 72 / 2 - 5 * 73, -22 - 80 / 2, 'RB'), - (1500, 1000, 'W'), - ] - balls_config = { 'r': { 'outline': '#bf4141' }, 'R': { 'fill': '#bf4141' }, - 'b': { 'outline': '#4241bf' }, 'B': { 'fill': '#4241bf' }, - 'w': { 'outline': '#bfbfbf' }, 'W': { 'fill': '#bfbfbf' } } - for b in balls: - self.draw_circle ((3000 - b[0], 2100 - b[1]), 72 / 2, - **balls_config[b[2][0]]) - if len (b[2]) > 1: - self.draw_circle ((b[0], 2100 - b[1]), 72 / 2, - **balls_config[b[2][1]]) + # Redraw. + self.reset () + # Table. + self.draw_rectangle ((-22, -22 - 80), (3000 / 2, 2100 + 22), fill = '#ff1f1f') + self.draw_rectangle ((3000 / 2, -22 - 80), (3000 + 22, 2100 + 22), fill = '#201fff') + self.draw_rectangle ((0, 0), (3000, 2100), fill = '#a49d8b') + self.draw_rectangle ((0, -22 - 80), (3000, -22), fill = '#a49d8b') + self.draw_rectangle ((0, 2100 - 500), (500, 2100), fill = '#201fff') + self.draw_rectangle ((3000 - 500, 2100 - 500), (3000, 2100), fill = '#ff1f1f') + self.draw_line ((3000 / 2, -22 - 80), (3000 / 2, 2100 + 22)) + # Axes. + self.draw_line ((0, 200), (0, 0), (200, 0), arrow = BOTH) + # Beacons and baskets. + self.draw_rectangle ((-22, 2100), (-22 - 80, 2100 + 80), fill = '#5b5b5d') + self.draw_rectangle ((-22, 1050 - 40), (-22 - 80, 1050 + 40), fill = '#5b5b5d') + self.draw_rectangle ((-22, 500), (-22 - 80, 500 + 80), fill = '#5b5b5d') + self.draw_rectangle ((-22, -80), (-22 - 80, 0), fill = '#5b5b5d') + self.draw_rectangle ((-22, 0), (-22 - 80, 500), fill = '#5b5b5d') + self.draw_rectangle ((-22 - 80 - 250, 0), (-22 - 80, 500), fill = '#6d6dad', stipple = 'gray75') + self.draw_rectangle ((3000 + 22, 2100), (3000 + 22 + 80, 2100 + 80), fill = '#5b5b5d') + self.draw_rectangle ((3000 + 22, 1050 - 40), (3000 + 22 + 80, 1050 + 40), fill = '#5b5b5d') + self.draw_rectangle ((3000 + 22, 500), (3000 + 22 + 80, 500 + 80), fill = '#5b5b5d') + self.draw_rectangle ((3000 + 22, -80), (3000 + 22 + 80, 0), fill = '#5b5b5d') + self.draw_rectangle ((3000 + 22, 0), (3000 + 22 + 80, 500), fill = '#5b5b5d') + self.draw_rectangle ((3000 + 22 + 80 + 250, 0), (3000 + 22 + 80, 500), fill = '#6d6dad', stipple = 'gray75') + # Vertical dispensers. + self.draw_rectangle ((-22, 2100 - 750 - 85 / 2), (0, 2100 - 750 + 85 / 2), fill = '#5b5b5b') + self.draw_circle ((40, 2100 - 750), 40) + self.draw_rectangle ((700 - 85 / 2, 2100), (700 + 85 / 2, 2100 + 22), fill = '#5b5b5b') + self.draw_circle ((700, 2100 - 40), 40) + self.draw_rectangle ((3000 + 22, 2100 - 750 - 85 / 2), (3000, 2100 - 750 + 85 / 2), fill = '#5b5b5b') + self.draw_circle ((3000 - 40, 2100 - 750), 40) + self.draw_rectangle ((3000 - 700 + 85 / 2, 2100), (3000 - 700 - 85 / 2, 2100 + 22), fill = '#5b5b5b') + self.draw_circle ((3000 - 700, 2100 - 40), 40) + # Horizontal dispenser. + self.draw_rectangle ((3000 / 2 - 924 / 2, 2100 + 22), (3000 / 2 + 924 / 2, 2100 + 22 + 80 + 22), fill = '#5b5b5b') + self.draw_rectangle ((3000 / 2 - 924 / 2 + 22, 2100 + 22), (3000 / 2 + 924 / 2 - 22, 2100 + 22 + 80), fill = '#5b5b5b') + self.draw_rectangle ((3000 / 2 - 880 / 2 - 35 - 60, 2100), (3000 / 2 - 880 / 2 - 35, 2100 + 44), fill = '#5b5b5b') + self.draw_rectangle ((3000 / 2 + 880 / 2 + 35 + 60, 2100), (3000 / 2 + 880 / 2 + 35, 2100 + 44), fill = '#5b5b5b') + # Balls. + balls = [ (800, 200, 'rb'), (800, 400, 'RB'), (800, 600, 'ww'), + (1300, 200, 'rb'), (1300, 400, 'rb'), (1300, 600, 'ww'), + (520, 800, 'WW'), (700, 40, 'RB'), (40, 750, 'WW'), + (450, 1120, 'ww'), (750, 1070, 'ww'), (1050, 1020, 'ww'), + (1500 - 72 / 2, -22 - 80 / 2, 'BR'), + (1500 - 72 / 2 - 1 * 73, -22 - 80 / 2, 'RB'), + (1500 - 72 / 2 - 2 * 73, -22 - 80 / 2, 'BR'), + (1500 - 72 / 2 - 3 * 73, -22 - 80 / 2, 'RB'), + (1500 - 72 / 2 - 4 * 73, -22 - 80 / 2, 'BR'), + (1500 - 72 / 2 - 5 * 73, -22 - 80 / 2, 'RB'), + (1500, 1000, 'W'), + ] + balls_config = { 'r': { 'outline': '#bf4141' }, 'R': { 'fill': '#bf4141' }, + 'b': { 'outline': '#4241bf' }, 'B': { 'fill': '#4241bf' }, + 'w': { 'outline': '#bfbfbf' }, 'W': { 'fill': '#bfbfbf' } } + for b in balls: + self.draw_circle ((3000 - b[0], 2100 - b[1]), 72 / 2, + **balls_config[b[2][0]]) + if len (b[2]) > 1: + self.draw_circle ((b[0], 2100 - b[1]), 72 / 2, + **balls_config[b[2][1]]) class TableView (DrawableCanvas): """This class handle the view of the table and every items inside it.""" @@ -140,102 +140,102 @@ class TableView (DrawableCanvas): YORIGIN = -2100 / 2 def __init__ (self, master = None): - DrawableCanvas.__init__ (self, self.WIDTH, self.HEIGHT, self.XORIGIN, - self.YORIGIN, - master, borderwidth = 1, relief = 'sunken', - background = 'white') - self.table = Table (self) - self.robot = Robot (self.table) - self.robot.angle = 0 - self.robot.pos = (0, 0) - self.drawn = [ ] + DrawableCanvas.__init__ (self, self.WIDTH, self.HEIGHT, self.XORIGIN, + self.YORIGIN, + master, borderwidth = 1, relief = 'sunken', + background = 'white') + self.table = Table (self) + self.robot = Robot (self.table) + self.robot.angle = 0 + self.robot.pos = (0, 0) + self.drawn = [ ] def draw (self): - self.table.draw () - for i in self.drawn: - i.draw () - self.robot.draw () + self.table.draw () + for i in self.drawn: + i.draw () + self.robot.draw () class Arm (Drawable): """The robot arm.""" def draw (self): - self.reset () - self.draw_arc ((0, 0), 0.45, start = 7 * pi / 12, extent = 10 * pi / 12, - style = 'arc', outline = '#808080') - self.draw_arc ((0, 0), 0.45, start = -5 * pi / 12, extent = 10 * pi / 12, - style = 'arc', outline = '#808080') - self.draw_arc ((0, 0), 0.25, start = -7 * pi / 12, extent = 14 * pi / 12, - style = 'arc', outline = '#808080') - self.trans_scale (0.4) - self.trans_rotate (-self.angle) - self.draw_line ((0, 0), (0, 1)) - self.draw_line ((0, 1), (0.3, 1), arrow = LAST, fill = '#808080') - self.draw_line ((0, 0), (cos (pi / 6), -sin (pi / 6))) - self.draw_line ((0, 0), (-cos (pi / 6), -sin (pi / 6))) + self.reset () + self.draw_arc ((0, 0), 0.45, start = 7 * pi / 12, extent = 10 * pi / 12, + style = 'arc', outline = '#808080') + self.draw_arc ((0, 0), 0.45, start = -5 * pi / 12, extent = 10 * pi / 12, + style = 'arc', outline = '#808080') + self.draw_arc ((0, 0), 0.25, start = -7 * pi / 12, extent = 14 * pi / 12, + style = 'arc', outline = '#808080') + self.trans_scale (0.4) + self.trans_rotate (-self.angle) + self.draw_line ((0, 0), (0, 1)) + self.draw_line ((0, 1), (0.3, 1), arrow = LAST, fill = '#808080') + self.draw_line ((0, 0), (cos (pi / 6), -sin (pi / 6))) + self.draw_line ((0, 0), (-cos (pi / 6), -sin (pi / 6))) class Servo: """Servo motor.""" def __init__ (self, coord, l, start, extent): - self.coord = coord - self.l = l - self.start = start - self.extent = extent - self.pos = 0 + self.coord = coord + self.l = l + self.start = start + self.extent = extent + self.pos = 0 def draw (self, d): - d.draw_arc (self.coord, self.l, start = self.start, - extent = self.extent, style = 'arc', outline = '#808080') - a = self.start + self.pos * self.extent - d.draw_line (self.coord, (self.coord[0] + self.l * cos (a), - self.coord[1] + self.l * sin (a))) + d.draw_arc (self.coord, self.l, start = self.start, + extent = self.extent, style = 'arc', outline = '#808080') + a = self.start + self.pos * self.extent + d.draw_line (self.coord, (self.coord[0] + self.l * cos (a), + self.coord[1] + self.l * sin (a))) class Rear (Drawable): """Rear actuators.""" def __init__ (self, onto): - Drawable.__init__ (self, onto) - self.traps = [ - Servo ((-2.5, -1), 0.8, 0, pi/2), - Servo ((-1.5, -0.9), 0.8, 0, pi/2), - Servo ((-0.5, -0.8), 0.8, 0, pi/2), - Servo ((0.5, -0.8), 0.8, pi, -pi/2), - Servo ((1.5, -0.9), 0.8, pi, -pi/2), - Servo ((-2.5, 1.3), 0.8, -pi/6, pi/3), - ] + Drawable.__init__ (self, onto) + self.traps = [ + Servo ((-2.5, -1), 0.8, 0, pi/2), + Servo ((-1.5, -0.9), 0.8, 0, pi/2), + Servo ((-0.5, -0.8), 0.8, 0, pi/2), + Servo ((0.5, -0.8), 0.8, pi, -pi/2), + Servo ((1.5, -0.9), 0.8, pi, -pi/2), + Servo ((-2.5, 1.3), 0.8, -pi/6, pi/3), + ] def draw (self): - self.reset () - self.trans_scale (0.9/5) - for i in self.traps: - i.draw (self) - self.draw_line ((-0.5, 1.5), (-0.5, 0.5), (-2.5, 0.2), - fill = '#808080') - self.draw_line ((-2.5, -1.2), (-2.5, -2.3), (2.5, -2.3), (2.5, 0.2), - (0.5, 0.5), (0.5, 1.5), fill = '#808080') - for i in (-1.5, -0.5, 0.5, 1.5): - self.draw_line ((i, -2.3), (i, -2), fill = '#808080') + self.reset () + self.trans_scale (0.9/5) + for i in self.traps: + i.draw (self) + self.draw_line ((-0.5, 1.5), (-0.5, 0.5), (-2.5, 0.2), + fill = '#808080') + self.draw_line ((-2.5, -1.2), (-2.5, -2.3), (2.5, -2.3), (2.5, 0.2), + (0.5, 0.5), (0.5, 1.5), fill = '#808080') + for i in (-1.5, -0.5, 0.5, 1.5): + self.draw_line ((i, -2.3), (i, -2), fill = '#808080') class ActuatorView (DrawableCanvas): """This class handle the view of the actuators inside the robot.""" def __init__ (self, master = None): - DrawableCanvas.__init__ (self, 1, 2, 0, 0, master, - borderwidth = 1, relief = 'sunken', background = 'white') - self.configure (width = 120, height = 240) - self.arm_drawable = Drawable (self) - self.arm_drawable.trans_translate ((0, 0.5)) - self.arm = Arm (self.arm_drawable) - self.arm.angle = 0 - self.rear_drawable = Drawable (self) - self.rear_drawable.trans_translate ((0, -0.5)) - self.rear = Rear (self.rear_drawable) + DrawableCanvas.__init__ (self, 1, 2, 0, 0, master, + borderwidth = 1, relief = 'sunken', background = 'white') + self.configure (width = 120, height = 240) + self.arm_drawable = Drawable (self) + self.arm_drawable.trans_translate ((0, 0.5)) + self.arm = Arm (self.arm_drawable) + self.arm.angle = 0 + self.rear_drawable = Drawable (self) + self.rear_drawable.trans_translate ((0, -0.5)) + self.rear = Rear (self.rear_drawable) def draw (self): - self.arm.draw () - self.rear.draw () + self.arm.draw () + self.rear.draw () class Inter (Frame): """Robot simulation interface.""" @@ -244,54 +244,54 @@ class Inter (Frame): Frame.__init__ (self, master) self.pack (expand = 1, fill = 'both') self.createWidgets () - self.updated = [ ] + self.updated = [ ] def createWidgets (self): - self.rightFrame = Frame (self) - self.rightFrame.pack (side = 'right', fill = 'y') - self.quitButton = Button (self.rightFrame, text = 'Quit', command = self.quit) - self.quitButton.pack (side = 'top') - self.actuatorview = ActuatorView (self.rightFrame) - self.actuatorview.pack (side = 'bottom', fill = 'x') - - self.sensorFrame = Frame (self.rightFrame, borderwidth = 1, relief = - 'sunken') - self.sensorFrame.pack (side = 'bottom', fill = 'x') - self.jackVar = IntVar () - self.jackButton = Checkbutton (self.sensorFrame, text = 'Jack', - indicatoron = False, variable = self.jackVar) - self.jackButton.pack (side = 'top') - self.colorVar = IntVar () - self.colorButton = Checkbutton (self.sensorFrame, text = 'Color', - indicatoron = False, variable = self.colorVar) - self.colorButton.pack (side = 'top') - - self.tableview = TableView (self) - self.tableview.pack (expand = True, fill = 'both') + self.rightFrame = Frame (self) + self.rightFrame.pack (side = 'right', fill = 'y') + self.quitButton = Button (self.rightFrame, text = 'Quit', command = self.quit) + self.quitButton.pack (side = 'top') + self.actuatorview = ActuatorView (self.rightFrame) + self.actuatorview.pack (side = 'bottom', fill = 'x') + + self.sensorFrame = Frame (self.rightFrame, borderwidth = 1, relief = + 'sunken') + self.sensorFrame.pack (side = 'bottom', fill = 'x') + self.jackVar = IntVar () + self.jackButton = Checkbutton (self.sensorFrame, text = 'Jack', + indicatoron = False, variable = self.jackVar) + self.jackButton.pack (side = 'top') + self.colorVar = IntVar () + self.colorButton = Checkbutton (self.sensorFrame, text = 'Color', + indicatoron = False, variable = self.colorVar) + self.colorButton.pack (side = 'top') + + self.tableview = TableView (self) + self.tableview.pack (expand = True, fill = 'both') def update (self, *args): - """If called with arguments, add them to the list of objects to be - updated. - If called without argument, redraw all objects to be updated.""" - if args: - for i in args: - if i not in self.updated: - self.updated.append (i) - else: - for i in self.updated: - i.draw () - self.updated = [ ] + """If called with arguments, add them to the list of objects to be + updated. + If called without argument, redraw all objects to be updated.""" + if args: + for i in args: + if i not in self.updated: + self.updated.append (i) + else: + for i in self.updated: + i.draw () + self.updated = [ ] if __name__ == '__main__': app = Inter () app.tableview.robot.angle = pi / 3 app.tableview.robot.pos = (700, 700) if 0: - from dist_sensor import DistSensor - ds = DistSensor (app.tableview.robot, (150, -127), -pi / 12, 800) - app.tableview.robot.drawn.append (ds) - app.tableview.drawn.append (Obstacle (app.tableview, (1300, 1200), 150)) - ds.obstacles = app.tableview.drawn + from dist_sensor import DistSensor + ds = DistSensor (app.tableview.robot, (150, -127), -pi / 12, 800) + app.tableview.robot.drawn.append (ds) + app.tableview.drawn.append (Obstacle (app.tableview, (1300, 1200), 150)) + ds.obstacles = app.tableview.drawn app.actuatorview.arm.angle = pi/6 app.actuatorview.rear.traps[0].pos = 1 app.actuatorview.rear.traps[1].pos = 0 diff --git a/host/inter/inter_node.py b/host/inter/inter_node.py index 96648c6f..12aaee6e 100644 --- a/host/inter/inter_node.py +++ b/host/inter/inter_node.py @@ -49,160 +49,160 @@ class InterNode (Inter): IO_PATH = 0xb4 def __init__ (self): - Inter.__init__ (self) - self.node = Node () - self.node.register (0xa0, self.handle_asserv_0) - self.node.register (0xa8, self.handle_asserv_8) - self.node.register (self.IO_JACK, self.handle_IO_JACK) - self.node.register (self.IO_COLOR, self.handle_IO_COLOR) - self.node.register (self.IO_SERVO, self.handle_IO_SERVO) - self.node.register (self.IO_SHARPS, self.handle_IO_SHARPS) - self.node.register (self.IO_PATH, self.handle_IO_PATH) - self.tk.createfilehandler (self.node, READABLE, self.read) - self.date = 0 - self.synced = True - self.step_after = None - self.step_time = None - self.obstacles = [ ] - self.dist_sensors = [ - DistSensor (self.tableview.robot, (150, 127), 0, 800), - DistSensor (self.tableview.robot, (150, 0), 0, 800), - DistSensor (self.tableview.robot, (150, -127), 0, 800), - DistSensor (self.tableview.robot, (-70, 100), pi, 800), - DistSensor (self.tableview.robot, (-70, -100), pi, 800), - ] - for s in self.dist_sensors: - s.obstacles = self.obstacles - s.hide = True - self.tableview.robot.drawn.extend (self.dist_sensors) - self.path = Path (self.tableview.table) - self.tableview.drawn.append (self.path) - self.tableview + Inter.__init__ (self) + self.node = Node () + self.node.register (0xa0, self.handle_asserv_0) + self.node.register (0xa8, self.handle_asserv_8) + self.node.register (self.IO_JACK, self.handle_IO_JACK) + self.node.register (self.IO_COLOR, self.handle_IO_COLOR) + self.node.register (self.IO_SERVO, self.handle_IO_SERVO) + self.node.register (self.IO_SHARPS, self.handle_IO_SHARPS) + self.node.register (self.IO_PATH, self.handle_IO_PATH) + self.tk.createfilehandler (self.node, READABLE, self.read) + self.date = 0 + self.synced = True + self.step_after = None + self.step_time = None + self.obstacles = [ ] + self.dist_sensors = [ + DistSensor (self.tableview.robot, (150, 127), 0, 800), + DistSensor (self.tableview.robot, (150, 0), 0, 800), + DistSensor (self.tableview.robot, (150, -127), 0, 800), + DistSensor (self.tableview.robot, (-70, 100), pi, 800), + DistSensor (self.tableview.robot, (-70, -100), pi, 800), + ] + for s in self.dist_sensors: + s.obstacles = self.obstacles + s.hide = True + self.tableview.robot.drawn.extend (self.dist_sensors) + self.path = Path (self.tableview.table) + self.tableview.drawn.append (self.path) + self.tableview def createWidgets (self): - Inter.createWidgets (self) - self.nowLabel = Label (self.rightFrame, text = 'Now: 0 s') - self.nowLabel.pack () - self.stepButton = Button (self.rightFrame, text = 'Step', - command = self.step) - self.stepButton.pack () - self.stepSizeScale = Scale (self.rightFrame, orient = HORIZONTAL, - from_ = 0.05, to = 1.0, resolution = 0.05) - self.stepSizeScale.pack () - self.playVar = IntVar () - self.playButton = Checkbutton (self.rightFrame, variable = - self.playVar, text = 'Play', command = self.play) - self.playButton.pack () - self.tableview.bind ('<2>', self.place_obstacle) - self.showSensorsVar = IntVar () - self.showSensorsButton = Checkbutton (self.sensorFrame, variable = - self.showSensorsVar, text = 'Show sensors', command = - self.show_sensors) - self.showSensorsButton.pack () + Inter.createWidgets (self) + self.nowLabel = Label (self.rightFrame, text = 'Now: 0 s') + self.nowLabel.pack () + self.stepButton = Button (self.rightFrame, text = 'Step', + command = self.step) + self.stepButton.pack () + self.stepSizeScale = Scale (self.rightFrame, orient = HORIZONTAL, + from_ = 0.05, to = 1.0, resolution = 0.05) + self.stepSizeScale.pack () + self.playVar = IntVar () + self.playButton = Checkbutton (self.rightFrame, variable = + self.playVar, text = 'Play', command = self.play) + self.playButton.pack () + self.tableview.bind ('<2>', self.place_obstacle) + self.showSensorsVar = IntVar () + self.showSensorsButton = Checkbutton (self.sensorFrame, variable = + self.showSensorsVar, text = 'Show sensors', command = + self.show_sensors) + self.showSensorsButton.pack () def step (self): - """Do a step. Signal to the Hub we are ready to wait to the next step - date.""" - self.node.wait_async (self.date - + int (self.stepSizeScale.get () * self.TICK)) - self.synced = False - self.step_after = None - self.step_time = time.time () + """Do a step. Signal to the Hub we are ready to wait to the next step + date.""" + self.node.wait_async (self.date + + int (self.stepSizeScale.get () * self.TICK)) + self.synced = False + self.step_after = None + self.step_time = time.time () def play (self): - """Activate auto-steping.""" - if self.playVar.get (): - if self.step_after is None and self.synced: - self.step () - self.stepButton.configure (state = DISABLED) - else: - if self.step_after is not None: - self.after_cancel (self.step_after) - self.step_after = None - self.stepButton.configure (state = NORMAL) + """Activate auto-steping.""" + if self.playVar.get (): + if self.step_after is None and self.synced: + self.step () + self.stepButton.configure (state = DISABLED) + else: + if self.step_after is not None: + self.after_cancel (self.step_after) + self.step_after = None + self.stepButton.configure (state = NORMAL) def read (self, file, mask): - """Handle event on the Node.""" - self.node.read () - if not self.synced and self.node.sync (): - self.synced = True - self.date = self.node.date - self.nowLabel.configure (text = 'Now: %.2f s' % (self.date - / self.TICK)) - self.update () - if self.playVar.get (): - assert self.step_after is None - next = self.step_time + self.stepSizeScale.get () - delay = next - time.time () - if delay > 0: - self.step_after = self.after (int (delay * 1000), - self.step) - else: - self.step () + """Handle event on the Node.""" + self.node.read () + if not self.synced and self.node.sync (): + self.synced = True + self.date = self.node.date + self.nowLabel.configure (text = 'Now: %.2f s' % (self.date + / self.TICK)) + self.update () + if self.playVar.get (): + assert self.step_after is None + next = self.step_time + self.stepSizeScale.get () + delay = next - time.time () + if delay > 0: + self.step_after = self.after (int (delay * 1000), + self.step) + else: + self.step () def handle_asserv_0 (self, msg): - x, y, a = msg.pop ('hhl') - self.tableview.robot.pos = (x, y) - self.tableview.robot.angle = float (a) / 1024 - self.update (self.tableview.robot) + x, y, a = msg.pop ('hhl') + self.tableview.robot.pos = (x, y) + self.tableview.robot.angle = float (a) / 1024 + self.update (self.tableview.robot) def handle_asserv_8 (self, msg): - a, = msg.pop ('l') - self.actuatorview.arm.angle = float (a) / 1024 - self.update (self.actuatorview.arm) + a, = msg.pop ('l') + self.actuatorview.arm.angle = float (a) / 1024 + self.update (self.actuatorview.arm) def handle_IO_JACK (self, msg): - m = Msg (self.IO_JACK) - m.push ('B', self.jackVar.get ()) - self.node.response (m) + m = Msg (self.IO_JACK) + m.push ('B', self.jackVar.get ()) + self.node.response (m) def handle_IO_COLOR (self, msg): - m = Msg (self.IO_COLOR) - m.push ('B', self.colorVar.get ()) - self.node.response (m) + m = Msg (self.IO_COLOR) + m.push ('B', self.colorVar.get ()) + self.node.response (m) def handle_IO_SERVO (self, msg): - for t in self.actuatorview.rear.traps: - t.pos = float (msg.pop ('B')[0]) / 255 - self.update (self.actuatorview.rear) + for t in self.actuatorview.rear.traps: + t.pos = float (msg.pop ('B')[0]) / 255 + self.update (self.actuatorview.rear) def handle_IO_SHARPS (self, msg): - m = Msg (self.IO_SHARPS) - for i in self.dist_sensors: - d = i.distance or 800 - d /= 10 - if d > 10: - v = 0.000571429 * d*d + -0.0752381 * d + 2.89107 - else: - v = 2.2 / 10 * d - v *= 1024 / 5 - m.push ('H', v) - assert v >= 0 and v < 1024 - self.node.response (m) + m = Msg (self.IO_SHARPS) + for i in self.dist_sensors: + d = i.distance or 800 + d /= 10 + if d > 10: + v = 0.000571429 * d*d + -0.0752381 * d + 2.89107 + else: + v = 2.2 / 10 * d + v *= 1024 / 5 + m.push ('H', v) + assert v >= 0 and v < 1024 + self.node.response (m) def handle_IO_PATH (self, msg): - self.path.path = [ ] - while len (msg) >= 4: - self.path.path.append (msg.pop ('hh')) - self.update (self.path) + self.path.path = [ ] + while len (msg) >= 4: + self.path.path.append (msg.pop ('hh')) + self.update (self.path) def place_obstacle (self, ev): - pos = self.tableview.screen_coord ((ev.x, ev.y)) - if self.obstacles: - self.obstacles[0].pos = pos - else: - self.obstacles.append (Obstacle (self.tableview.table, pos, 150)) - self.tableview.drawn.append (self.obstacles[0]) - self.update (*self.obstacles) - self.update (*self.dist_sensors) - self.update () + pos = self.tableview.screen_coord ((ev.x, ev.y)) + if self.obstacles: + self.obstacles[0].pos = pos + else: + self.obstacles.append (Obstacle (self.tableview.table, pos, 150)) + self.tableview.drawn.append (self.obstacles[0]) + self.update (*self.obstacles) + self.update (*self.dist_sensors) + self.update () def show_sensors (self): - hide = not self.showSensorsVar.get () - for i in self.dist_sensors: - i.hide = hide - self.update (*self.dist_sensors) - self.update () + hide = not self.showSensorsVar.get () + for i in self.dist_sensors: + i.hide = hide + self.update (*self.dist_sensors) + self.update () if __name__ == '__main__': import mex.hub @@ -210,9 +210,9 @@ if __name__ == '__main__': h = mex.hub.Hub (min_clients = 1) fh = utils.forked.Forked (h.wait) try: - app = InterNode () - app.mainloop() + app = InterNode () + app.mainloop() finally: - fh.kill () - import time - time.sleep (1) + fh.kill () + import time + time.sleep (1) diff --git a/host/inter/path.py b/host/inter/path.py index 76db970a..eb5744eb 100644 --- a/host/inter/path.py +++ b/host/inter/path.py @@ -32,11 +32,11 @@ class Path (Drawable): """Computed path drawing.""" def __init__ (self, onto): - Drawable.__init__ (self, onto) - self.path = [ ] + Drawable.__init__ (self, onto) + self.path = [ ] def draw (self): - self.reset () - if len (self.path) > 2: - fmt = dict (fill = 'green', arrow = LAST) - self.draw_line (*self.path, **fmt) + self.reset () + if len (self.path) > 2: + fmt = dict (fill = 'green', arrow = LAST) + self.draw_line (*self.path, **fmt) diff --git a/host/inter/test/test_drawable.py b/host/inter/test/test_drawable.py index 79948e12..6f86dd2d 100644 --- a/host/inter/test/test_drawable.py +++ b/host/inter/test/test_drawable.py @@ -7,38 +7,38 @@ from math import pi class Test (Drawable): def draw (self): - self.draw_rectangle ((-100, -100), (100, 100), fill = '', outline = 'gray') - self.draw_rectangle ((0, 0), (5, 5), fill = 'red') - self.draw_rectangle ((20, 20), (50, 50), fill = '', outline = 'blue') - self.draw_line ((20, 20), (25, 25), (80, 0), (0, 80), fill = 'green') - self.draw_line ((20, 20), (25, 25), (80, 0), (0, 80), smooth = True) - self.draw_circle ((40, -40), 10) - self.draw_arc ((-40, 0), 20, start = pi / 4, extent = pi / 2) + self.draw_rectangle ((-100, -100), (100, 100), fill = '', outline = 'gray') + self.draw_rectangle ((0, 0), (5, 5), fill = 'red') + self.draw_rectangle ((20, 20), (50, 50), fill = '', outline = 'blue') + self.draw_line ((20, 20), (25, 25), (80, 0), (0, 80), fill = 'green') + self.draw_line ((20, 20), (25, 25), (80, 0), (0, 80), smooth = True) + self.draw_circle ((40, -40), 10) + self.draw_arc ((-40, 0), 20, start = pi / 4, extent = pi / 2) class App (DrawableCanvas): def __init__ (self, master = None): - DrawableCanvas.__init__ (self, 300, 300, 20, 20, master) - self.pack (expand = True, fill = 'both') - self.test = Test (self) - self.animated = False - self.i = 0 + DrawableCanvas.__init__ (self, 300, 300, 20, 20, master) + self.pack (expand = True, fill = 'both') + self.test = Test (self) + self.animated = False + self.i = 0 def animate (self): - # Real user should reset at each redraw. - self.after (500, self.animate) - self.test.draw () - self.test.trans_rotate (-pi/12) - self.test.trans_translate ((10, 10)) - self.test.trans_scale (1.05) - self.i += 1 - if self.i == 10: - self.test.reset () + # Real user should reset at each redraw. + self.after (500, self.animate) + self.test.draw () + self.test.trans_rotate (-pi/12) + self.test.trans_translate ((10, 10)) + self.test.trans_scale (1.05) + self.i += 1 + if self.i == 10: + self.test.reset () def draw (self): - if not self.animated: - self.animate () - self.animated = True + if not self.animated: + self.animate () + self.animated = True app = App () app.mainloop () diff --git a/host/inter/trans_matrix.py b/host/inter/trans_matrix.py index dcaab134..a8f3849a 100644 --- a/host/inter/trans_matrix.py +++ b/host/inter/trans_matrix.py @@ -33,138 +33,138 @@ class TransMatrix: IDENTITY = ((1, 0), (0, 1), (0, 0)) def __init__ (self, *m): - """Initialise the matrix, with optional initial value. - - >>> TransMatrix () - ((1, 0), (0, 1), (0, 0)) - >>> TransMatrix ((1, 2), (3, 4), (5, 6)) - ((1, 2), (3, 4), (5, 6)) - """ - if m: - assert len (m) == 3 - for i in m: - assert len (i) == 2 - self.matrix = m - else: - self.matrix = self.IDENTITY + """Initialise the matrix, with optional initial value. + + >>> TransMatrix () + ((1, 0), (0, 1), (0, 0)) + >>> TransMatrix ((1, 2), (3, 4), (5, 6)) + ((1, 2), (3, 4), (5, 6)) + """ + if m: + assert len (m) == 3 + for i in m: + assert len (i) == 2 + self.matrix = m + else: + self.matrix = self.IDENTITY def identity (self): - """Set to identity. + """Set to identity. - >>> a = TransMatrix () - >>> a.translate ((2, 3)) - >>> a.identity (); a - ((1, 0), (0, 1), (0, 0)) - """ - self.matrix = self.IDENTITY + >>> a = TransMatrix () + >>> a.translate ((2, 3)) + >>> a.identity (); a + ((1, 0), (0, 1), (0, 0)) + """ + self.matrix = self.IDENTITY def rotate (self, angle): - """Transform the current matrix to do a rotation. - - >>> from math import pi - >>> a = TransMatrix () - >>> a.rotate (pi / 3); a # doctest: +ELLIPSIS - ((0.5..., 0.866...), (-0.866..., 0.5...), (0.0, 0.0)) - """ - s = sin (angle) - c = cos (angle) - m = TransMatrix ((c, s), (-s, c), (0, 0)) - self *= m + """Transform the current matrix to do a rotation. + + >>> from math import pi + >>> a = TransMatrix () + >>> a.rotate (pi / 3); a # doctest: +ELLIPSIS + ((0.5..., 0.866...), (-0.866..., 0.5...), (0.0, 0.0)) + """ + s = sin (angle) + c = cos (angle) + m = TransMatrix ((c, s), (-s, c), (0, 0)) + self *= m def translate (self, by): - """Transform the current matrix to do a translation. - - >>> a = TransMatrix () - >>> a.translate ((2, 3)); a - ((1, 0), (0, 1), (2, 3)) - """ - m = TransMatrix ((1, 0), (0, 1), by) - self *= m + """Transform the current matrix to do a translation. + + >>> a = TransMatrix () + >>> a.translate ((2, 3)); a + ((1, 0), (0, 1), (2, 3)) + """ + m = TransMatrix ((1, 0), (0, 1), by) + self *= m def scale (self, factor): - """Transform the current matrix to do a scaling. - - >>> a = TransMatrix () - >>> a.scale (2); a - ((2, 0), (0, 2), (0, 0)) - """ - m = TransMatrix ((factor, 0), (0, factor), (0, 0)) - self *= m + """Transform the current matrix to do a scaling. + + >>> a = TransMatrix () + >>> a.scale (2); a + ((2, 0), (0, 2), (0, 0)) + """ + m = TransMatrix ((factor, 0), (0, factor), (0, 0)) + self *= m def __imul__ (self, other): - """Multiply by an other matrix. - - >>> a = TransMatrix ((1, 0), (0, 1), (1, 0)) - >>> b = TransMatrix ((0, 1), (1, 0), (0, 1)) - >>> a *= b; a - ((0, 1), (1, 0), (0, 2)) - """ - s = self.matrix - o = other.matrix - self.matrix = ( - (s[0][0] * o[0][0] + s[0][1] * o[1][0], - s[0][0] * o[0][1] + s[0][1] * o[1][1]), - (s[1][0] * o[0][0] + s[1][1] * o[1][0], - s[1][0] * o[0][1] + s[1][1] * o[1][1]), - (s[2][0] * o[0][0] + s[2][1] * o[1][0] + o[2][0], - s[2][0] * o[0][1] + s[2][1] * o[1][1] + o[2][1])) - return self + """Multiply by an other matrix. + + >>> a = TransMatrix ((1, 0), (0, 1), (1, 0)) + >>> b = TransMatrix ((0, 1), (1, 0), (0, 1)) + >>> a *= b; a + ((0, 1), (1, 0), (0, 2)) + """ + s = self.matrix + o = other.matrix + self.matrix = ( + (s[0][0] * o[0][0] + s[0][1] * o[1][0], + s[0][0] * o[0][1] + s[0][1] * o[1][1]), + (s[1][0] * o[0][0] + s[1][1] * o[1][0], + s[1][0] * o[0][1] + s[1][1] * o[1][1]), + (s[2][0] * o[0][0] + s[2][1] * o[1][0] + o[2][0], + s[2][0] * o[0][1] + s[2][1] * o[1][1] + o[2][1])) + return self def apply (self, *args): - """Apply (multiply) the matrix to all the given arguments. - - >>> m = TransMatrix ((1, 2), (4, 8), (16, 32)) - >>> m.apply ((1, 0)) - (17, 34) - >>> m.apply ((0, 1), (1, 1)) - ((20, 40), (21, 42)) - """ - r = tuple ( - (i[0] * self.matrix[0][0] + i[1] * self.matrix[1][0] - + self.matrix[2][0], - i[0] * self.matrix[0][1] + i[1] * self.matrix[1][1] - + self.matrix[2][1]) - for i in args) - if len (args) == 1: - return r[0] - else: - return r + """Apply (multiply) the matrix to all the given arguments. + + >>> m = TransMatrix ((1, 2), (4, 8), (16, 32)) + >>> m.apply ((1, 0)) + (17, 34) + >>> m.apply ((0, 1), (1, 1)) + ((20, 40), (21, 42)) + """ + r = tuple ( + (i[0] * self.matrix[0][0] + i[1] * self.matrix[1][0] + + self.matrix[2][0], + i[0] * self.matrix[0][1] + i[1] * self.matrix[1][1] + + self.matrix[2][1]) + for i in args) + if len (args) == 1: + return r[0] + else: + return r def apply_angle (self, angle): - """Apply the matrix to an angle. - - >>> from math import pi - >>> a = TransMatrix () - >>> a.rotate (pi / 6) - >>> a.translate ((2, 3)) - >>> a.scale (4) - >>> a.apply_angle (pi / 6), pi / 3 # doctest: +ELLIPSIS - (1.0471..., 1.0471...) - """ - o, m = self.apply ((0, 0), (cos (angle), sin (angle))) - v = (m[0] - o[0], m[1] - o[1]) - vl = sqrt (v[0] ** 2 + v[1] ** 2) - v = (v[0] / vl, v[1] / vl) - return atan2 (v[1], v[0]) + """Apply the matrix to an angle. + + >>> from math import pi + >>> a = TransMatrix () + >>> a.rotate (pi / 6) + >>> a.translate ((2, 3)) + >>> a.scale (4) + >>> a.apply_angle (pi / 6), pi / 3 # doctest: +ELLIPSIS + (1.0471..., 1.0471...) + """ + o, m = self.apply ((0, 0), (cos (angle), sin (angle))) + v = (m[0] - o[0], m[1] - o[1]) + vl = sqrt (v[0] ** 2 + v[1] ** 2) + v = (v[0] / vl, v[1] / vl) + return atan2 (v[1], v[0]) def apply_distance (self, distance): - """Apply the matrix to a distance. - - >>> from math import pi - >>> a = TransMatrix () - >>> a.rotate (pi / 6) - >>> a.translate ((2, 3)) - >>> a.scale (4) - >>> round (a.apply_distance (2)) - 8.0 - """ - o, m = self.apply ((0, 0), (distance, 0)) - v = (m[0] - o[0], m[1] - o[1]) - vl = sqrt (v[0] ** 2 + v[1] ** 2) - return vl + """Apply the matrix to a distance. + + >>> from math import pi + >>> a = TransMatrix () + >>> a.rotate (pi / 6) + >>> a.translate ((2, 3)) + >>> a.scale (4) + >>> round (a.apply_distance (2)) + 8.0 + """ + o, m = self.apply ((0, 0), (distance, 0)) + v = (m[0] - o[0], m[1] - o[1]) + vl = sqrt (v[0] ** 2 + v[1] ** 2) + return vl def __repr__ (self): - return self.matrix.__repr__ () + return self.matrix.__repr__ () def _test (): import doctest diff --git a/host/mex/hub.py b/host/mex/hub.py index 5ae88ba7..4dd796a4 100644 --- a/host/mex/hub.py +++ b/host/mex/hub.py @@ -30,152 +30,152 @@ from struct import pack, unpack, calcsize class Hub: def __init__ (self, addr = mex.DEFAULT_ADDR, min_clients = 0, log = None): - """Initialise a new Hub and bind to server address.""" - self.addr = addr - self.min_clients = min_clients - self.log = log - self.clients = { } - self.next_client_id = 1 - self.date = 0 - self.socket = socket.socket () - self.socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - self.socket.setsockopt (socket.SOL_TCP, socket.TCP_NODELAY, 1) - self.socket.bind (self.addr) - self.socket.listen (5) + """Initialise a new Hub and bind to server address.""" + self.addr = addr + self.min_clients = min_clients + self.log = log + self.clients = { } + self.next_client_id = 1 + self.date = 0 + self.socket = socket.socket () + self.socket.setsockopt (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.setsockopt (socket.SOL_TCP, socket.TCP_NODELAY, 1) + self.socket.bind (self.addr) + self.socket.listen (5) def wait (self, cond = False): - """Wait until a cond is True and handle message exchanges.""" - while not cond and self.date != None: - self.select () + """Wait until a cond is True and handle message exchanges.""" + while not cond and self.date != None: + self.select () def select (self): - """Wait until the next event (connection or message) occurs and handle - it.""" - if not self.min_clients: - # Check idle and wanted dates. - idle = True - min_wait_date = None - for c in self.clients.itervalues (): - if not c.idle: - idle = False - break - if c.wait_date != None and (c.wait_date < min_wait_date or - min_wait_date == None): - min_wait_date = c.wait_date - # Abort if everyone waits forever. - if idle and min_wait_date == None: - self.date = None - return - # Send new date. - if idle: - self.date = min_wait_date - if self.log: - self.log ('[%d] date' % self.date) - date = Msg (mex.DATE) - date.push ('L', self.date) - for c in self.clients.itervalues (): - c.send (date) - # Prepare fdset and select. - infds = [ self.socket ] - if not self.min_clients: - infds += self.clients.values () - readyfds = select.select (infds, (), ()) [0] - for i in readyfds: - if i is self.socket: - self.accept () - else: - i.read () + """Wait until the next event (connection or message) occurs and handle + it.""" + if not self.min_clients: + # Check idle and wanted dates. + idle = True + min_wait_date = None + for c in self.clients.itervalues (): + if not c.idle: + idle = False + break + if c.wait_date != None and (c.wait_date < min_wait_date or + min_wait_date == None): + min_wait_date = c.wait_date + # Abort if everyone waits forever. + if idle and min_wait_date == None: + self.date = None + return + # Send new date. + if idle: + self.date = min_wait_date + if self.log: + self.log ('[%d] date' % self.date) + date = Msg (mex.DATE) + date.push ('L', self.date) + for c in self.clients.itervalues (): + c.send (date) + # Prepare fdset and select. + infds = [ self.socket ] + if not self.min_clients: + infds += self.clients.values () + readyfds = select.select (infds, (), ()) [0] + for i in readyfds: + if i is self.socket: + self.accept () + else: + i.read () def accept (self): - """Accept a new connection and create a client.""" - # Add client. - a = self.socket.accept () - if self.log: - self.log ('[%d] connect from %s' % (self.date, str (a[1]))) - c = Hub.Client (self, a[0], self.next_client_id) - self.next_client_id += 1 - assert self.next_client_id < 256 - self.clients[c.id] = c - if self.min_clients: - self.min_clients -= 1 - # Send first date. - date = Msg (mex.DATE) - date.push ('L', self.date) - c.send (date) + """Accept a new connection and create a client.""" + # Add client. + a = self.socket.accept () + if self.log: + self.log ('[%d] connect from %s' % (self.date, str (a[1]))) + c = Hub.Client (self, a[0], self.next_client_id) + self.next_client_id += 1 + assert self.next_client_id < 256 + self.clients[c.id] = c + if self.min_clients: + self.min_clients -= 1 + # Send first date. + date = Msg (mex.DATE) + date.push ('L', self.date) + c.send (date) def broadcast (self, msg, exclude = None): - """Send a message broadcasted, could exclude a client.""" - for c in self.clients.itervalues (): - if c is not exclude: - c.send (msg) + """Send a message broadcasted, could exclude a client.""" + for c in self.clients.itervalues (): + if c is not exclude: + c.send (msg) class Client: - def __init__ (self, hub, socket, id): - """Initialise a new client.""" - self.hub = hub - self.socket = socket - self.id = id - self.seq = 0 - self.idle = True - self.wait_date = None + def __init__ (self, hub, socket, id): + """Initialise a new client.""" + self.hub = hub + self.socket = socket + self.id = id + self.seq = 0 + self.idle = True + self.wait_date = None - def read (self): - """Read and dispatch a message from this client.""" - # Read message. - head = self.socket.recv (calcsize (mex.HEADER_FMT)) - if head == '': - self.socket.close () - del self.hub.clients[self.id] - return - size, seq = unpack (mex.HEADER_FMT, head) - data = self.socket.recv (size) - m = Msg (data) - if self.hub.log: - self.hub.log ('[%d] received from %d(%d): %s' % - (self.hub.date, self.id, seq, str (m))) - # Dispatch. - if m.mtype == mex.IDLE: - if seq == self.seq: - self.idle = True - if len (m): - self.wait_date, = m.pop ('L') - assert self.wait_date >= self.hub.date - else: - self.wait_date = None - elif m.mtype == mex.DATE: - date = Msg (mex.DATE) - date.push ('L', self.hub.date) - self.send (date) - elif m.mtype == mex.REQ: - m.pop ('B') - mr = Msg (mex.REQ) - mr.push ('B', self.id) - mr.push (m.pop ()) - self.hub.broadcast (mr, self) - elif m.mtype == mex.RSP: - to, = m.pop ('B') - mr = Msg (mex.RSP) - mr.push ('B', 0) - mr.push (m.pop ()) - self.hub.clients[to].send (mr) - else: - self.hub.broadcast (m, self) + def read (self): + """Read and dispatch a message from this client.""" + # Read message. + head = self.socket.recv (calcsize (mex.HEADER_FMT)) + if head == '': + self.socket.close () + del self.hub.clients[self.id] + return + size, seq = unpack (mex.HEADER_FMT, head) + data = self.socket.recv (size) + m = Msg (data) + if self.hub.log: + self.hub.log ('[%d] received from %d(%d): %s' % + (self.hub.date, self.id, seq, str (m))) + # Dispatch. + if m.mtype == mex.IDLE: + if seq == self.seq: + self.idle = True + if len (m): + self.wait_date, = m.pop ('L') + assert self.wait_date >= self.hub.date + else: + self.wait_date = None + elif m.mtype == mex.DATE: + date = Msg (mex.DATE) + date.push ('L', self.hub.date) + self.send (date) + elif m.mtype == mex.REQ: + m.pop ('B') + mr = Msg (mex.REQ) + mr.push ('B', self.id) + mr.push (m.pop ()) + self.hub.broadcast (mr, self) + elif m.mtype == mex.RSP: + to, = m.pop ('B') + mr = Msg (mex.RSP) + mr.push ('B', 0) + mr.push (m.pop ()) + self.hub.clients[to].send (mr) + else: + self.hub.broadcast (m, self) - def send (self, msg): - """Send a message to this client.""" - data = msg.data () - self.seq += 1 - if self.seq == 256: - self.seq = 0 - packet = pack (mex.HEADER_FMT, len (data), self.seq) + data - self.socket.sendall (packet) - self.idle = False - if self.hub.log: - self.hub.log ('[%d] sending to %d(%d): %s' % (self.hub.date, - self.id, self.seq, str (msg))) + def send (self, msg): + """Send a message to this client.""" + data = msg.data () + self.seq += 1 + if self.seq == 256: + self.seq = 0 + packet = pack (mex.HEADER_FMT, len (data), self.seq) + data + self.socket.sendall (packet) + self.idle = False + if self.hub.log: + self.hub.log ('[%d] sending to %d(%d): %s' % (self.hub.date, + self.id, self.seq, str (msg))) - def fileno (self): - """Return socket filedescriptor.""" - return self.socket.fileno () + def fileno (self): + """Return socket filedescriptor.""" + return self.socket.fileno () diff --git a/host/mex/msg.py b/host/mex/msg.py index 5399a3c9..0cd01c8c 100644 --- a/host/mex/msg.py +++ b/host/mex/msg.py @@ -84,64 +84,64 @@ class Msg: """ def __init__ (self, f): - """Initialise a new message, see class documentation for - signatures.""" - try: - f[0] - except TypeError: - # New empty message. - self.mtype = f - self.header = pack ('!B', self.mtype) - self.payload = '' - else: - # Read from a buffer. - self.header = f[0:1] - self.payload = f[1:] - self.mtype = unpack ('!B', self.header)[0] + """Initialise a new message, see class documentation for + signatures.""" + try: + f[0] + except TypeError: + # New empty message. + self.mtype = f + self.header = pack ('!B', self.mtype) + self.payload = '' + else: + # Read from a buffer. + self.header = f[0:1] + self.payload = f[1:] + self.mtype = unpack ('!B', self.header)[0] def data (self): - """Get the message data, ready to be sent.""" - return self.header + self.payload + """Get the message data, ready to be sent.""" + return self.header + self.payload def __str__ (self): - """Return an text representation.""" - payload = ' '.join (['%02x' % ord (i) for i in self.payload]) - return '' % (self.mtype, payload) + """Return an text representation.""" + payload = ' '.join (['%02x' % ord (i) for i in self.payload]) + return '' % (self.mtype, payload) def push (self, fmt, *args): - """ - Add data to the payload. - - msg.push (string) -> None. Add the given string to the payload. - - msg.push (fmt, values...) -> None. Add the given values to the - payload, using a struct.pack format string. - """ - if args: - self.payload += pack ('!' + fmt, *args) - else: - self.payload += fmt + """ + Add data to the payload. + + msg.push (string) -> None. Add the given string to the payload. + + msg.push (fmt, values...) -> None. Add the given values to the + payload, using a struct.pack format string. + """ + if args: + self.payload += pack ('!' + fmt, *args) + else: + self.payload += fmt def pop (self, fmt = None): - """ - Get data from the payload. - - msg.pop () -> payload. Get all the remaining payload. - - msg.pop (fmt) -> (values, ...). Get values extracted according to a - struct.unpack format string. - """ - if fmt: - nb = calcsize (fmt) - ex, self.payload = self.payload[0:nb], self.payload[nb:] - return unpack ('!' + fmt, ex) - else: - ex, self.payload = self.payload, '' - return ex + """ + Get data from the payload. + + msg.pop () -> payload. Get all the remaining payload. + + msg.pop (fmt) -> (values, ...). Get values extracted according to a + struct.unpack format string. + """ + if fmt: + nb = calcsize (fmt) + ex, self.payload = self.payload[0:nb], self.payload[nb:] + return unpack ('!' + fmt, ex) + else: + ex, self.payload = self.payload, '' + return ex def __len__ (self): - """Get payload remaining length.""" - return len (self.payload) + """Get payload remaining length.""" + return len (self.payload) def _test (): import doctest diff --git a/host/mex/node.py b/host/mex/node.py index 3307a4d7..2a6a5d22 100644 --- a/host/mex/node.py +++ b/host/mex/node.py @@ -30,128 +30,128 @@ from struct import pack, unpack, calcsize class Node: class closed: - """Raised on closed connection.""" - pass + """Raised on closed connection.""" + pass def __init__ (self, addr = mex.DEFAULT_ADDR): - """Create a new Node and connect it to given Hub address.""" - self.socket = socket.socket () - self.socket.setsockopt (socket.SOL_TCP, socket.TCP_NODELAY, 1) - self.socket.connect (addr) - self.date = 0 - self.seq = 0 - self.req = None - self.handlers = { } - self.register (mex.DATE, lambda msg: self.handle_DATE (msg)) - self.register (mex.REQ, lambda msg: self.handle_REQ (msg)) - # Synchronise. - rsp = None - while rsp == None or rsp.mtype != mex.DATE: - rsp = self.recv () - self.dispatch (rsp) + """Create a new Node and connect it to given Hub address.""" + self.socket = socket.socket () + self.socket.setsockopt (socket.SOL_TCP, socket.TCP_NODELAY, 1) + self.socket.connect (addr) + self.date = 0 + self.seq = 0 + self.req = None + self.handlers = { } + self.register (mex.DATE, lambda msg: self.handle_DATE (msg)) + self.register (mex.REQ, lambda msg: self.handle_REQ (msg)) + # Synchronise. + rsp = None + while rsp == None or rsp.mtype != mex.DATE: + rsp = self.recv () + self.dispatch (rsp) def wait (self, date = None): - """Wait forever or until a date is reached.""" - while date == None or self.date != date: - idle = Msg (mex.IDLE) - if date != None: - idle.push ('L', date) - self.send (idle) - msg = self.recv () - self.dispatch (msg) + """Wait forever or until a date is reached.""" + while date == None or self.date != date: + idle = Msg (mex.IDLE) + if date != None: + idle.push ('L', date) + self.send (idle) + msg = self.recv () + self.dispatch (msg) def wait_async (self, date = None): - """Asynchronous version of wait. This should not be called again - until sync return True.""" - self.async_waited = date - synced = self.sync () - assert not synced + """Asynchronous version of wait. This should not be called again + until sync return True.""" + self.async_waited = date + synced = self.sync () + assert not synced def sync (self): - """To be called after read or wait_async. Return True if the waited - date is reached or signal the Hub our waiting status.""" - if self.date == self.async_waited: - return True - else: - idle = Msg (mex.IDLE) - if self.async_waited != None: - idle.push ('L', self.async_waited) - self.send (idle) + """To be called after read or wait_async. Return True if the waited + date is reached or signal the Hub our waiting status.""" + if self.date == self.async_waited: + return True + else: + idle = Msg (mex.IDLE) + if self.async_waited != None: + idle.push ('L', self.async_waited) + self.send (idle) def read (self): - """Used for asynchronous operations. Handle incoming data. The sync - method should be called after this one returns.""" - msg = self.recv () - self.dispatch (msg) + """Used for asynchronous operations. Handle incoming data. The sync + method should be called after this one returns.""" + msg = self.recv () + self.dispatch (msg) def send (self, msg): - """Send a message.""" - data = msg.data () - packet = pack (mex.HEADER_FMT, len (data), self.seq) + data - self.socket.sendall (packet) + """Send a message.""" + data = msg.data () + packet = pack (mex.HEADER_FMT, len (data), self.seq) + data + self.socket.sendall (packet) def request (self, msg): - """Send a request and return response.""" - # Send request. - req = Msg (mex.REQ) - req.push ('B', 0) - req.push (msg.data ()) - self.send (req) - # Wait for response. - rsp = self.recv () - while rsp.mtype != mex.RSP: - self.dispatch (rsp) - rsp = self.recv () - # Discard reqid. - rsp.pop ('B') - return Msg (rsp.pop ()) + """Send a request and return response.""" + # Send request. + req = Msg (mex.REQ) + req.push ('B', 0) + req.push (msg.data ()) + self.send (req) + # Wait for response. + rsp = self.recv () + while rsp.mtype != mex.RSP: + self.dispatch (rsp) + rsp = self.recv () + # Discard reqid. + rsp.pop ('B') + return Msg (rsp.pop ()) def response (self, msg): - """Send a response to the currently serviced request.""" - assert self.req != None - rsp = Msg (mex.RSP) - rsp.push ('B', self.req) - self.req = None - rsp.push (msg.data ()) - self.send (rsp) + """Send a response to the currently serviced request.""" + assert self.req != None + rsp = Msg (mex.RSP) + rsp.push ('B', self.req) + self.req = None + rsp.push (msg.data ()) + self.send (rsp) def register (self, mtype, handler): - """Register an handler for the given message type.""" - assert mtype not in self.handlers - self.handlers[mtype] = handler + """Register an handler for the given message type.""" + assert mtype not in self.handlers + self.handlers[mtype] = handler def close (self): - """Close connection with the Hub.""" - self.socket.close () - self.socket = None + """Close connection with the Hub.""" + self.socket.close () + self.socket = None def fileno (self): - """Return socket fileno () for asynchronous operations.""" - return self.socket.fileno () + """Return socket fileno () for asynchronous operations.""" + return self.socket.fileno () def recv (self): - """Receive one message.""" - head = self.socket.recv (calcsize (mex.HEADER_FMT)) - if head == '': - self.close () - raise Node.closed - size, self.seq = unpack (mex.HEADER_FMT, head) - data = self.socket.recv (size) - return Msg (data) + """Receive one message.""" + head = self.socket.recv (calcsize (mex.HEADER_FMT)) + if head == '': + self.close () + raise Node.closed + size, self.seq = unpack (mex.HEADER_FMT, head) + data = self.socket.recv (size) + return Msg (data) def dispatch (self, msg): - """Call the right handler for the given message.""" - if msg.mtype in self.handlers: - self.handlers[msg.mtype] (msg) + """Call the right handler for the given message.""" + if msg.mtype in self.handlers: + self.handlers[msg.mtype] (msg) def handle_DATE (self, msg): - """Handle an incoming DATE.""" - self.date, = msg.pop ('L') + """Handle an incoming DATE.""" + self.date, = msg.pop ('L') def handle_REQ (self, msg): - """Handle an incoming REQ.""" - self.req, = msg.pop ('B') - dec = Msg (msg.pop ()) - self.dispatch (dec) - self.req = None + """Handle an incoming REQ.""" + self.req, = msg.pop ('B') + dec = Msg (msg.pop ()) + self.dispatch (dec) + self.req = None diff --git a/host/mex/test/test.py b/host/mex/test/test.py index c4382c2c..4be24f49 100644 --- a/host/mex/test/test.py +++ b/host/mex/test/test.py @@ -15,12 +15,12 @@ h = Hub (min_clients = 2, log = log) def c1 (): n = Node () def a (msg): - print 'oucouc' - nb, = msg.pop ('B') - nb += 1 - m = Msg (msg.mtype) - m.push ('B', nb) - n.response (m) + print 'oucouc' + nb, = msg.pop ('B') + nb += 1 + m = Msg (msg.mtype) + m.push ('B', nb) + n.response (m) n.register (0x82, a) m = Msg (0x81) n.send (m) @@ -31,7 +31,7 @@ f1 = Forked (c1) def c2 (): n = Node () def a (msg): - print 'coucou' + print 'coucou' n.register (0x81, a) m = Msg (0x82) m.push ('B', 42) @@ -40,9 +40,9 @@ def c2 (): assert r.pop ('B') == (43,) n.wait_async (42) while not n.sync (): - fds = select.select ((n, ), (), ())[0] - for i in fds: - i.read () + fds = select.select ((n, ), (), ())[0] + for i in fds: + i.read () n.wait () f2 = Forked (c2) diff --git a/host/proto/popen_io.py b/host/proto/popen_io.py index 235151d3..0f582802 100644 --- a/host/proto/popen_io.py +++ b/host/proto/popen_io.py @@ -29,22 +29,22 @@ class PopenIO: convert from and to \r and \n.""" def __init__ (self, cmd): - """Initialise and start the given commande line.""" - fout, fin = os.popen2 (cmd, 'b', 0) - time.sleep (0.2) - self.fin = fin - self.fout = fout + """Initialise and start the given commande line.""" + fout, fin = os.popen2 (cmd, 'b', 0) + time.sleep (0.2) + self.fin = fin + self.fout = fout def read (self, *args): - buf = self.fin.read (*args).replace ('\n', '\r') - return buf + buf = self.fin.read (*args).replace ('\n', '\r') + return buf def write (self, *args): - return self.fout.write (*[i.replace ('\r', '\n') for i in args]) + return self.fout.write (*[i.replace ('\r', '\n') for i in args]) def fileno (self): - return self.fin.fileno () + return self.fin.fileno () def close (self): - self.fin.close () - self.fout.close () + self.fin.close () + self.fout.close () diff --git a/host/proto/proto.py b/host/proto/proto.py index 9eb401e1..19dff792 100644 --- a/host/proto/proto.py +++ b/host/proto/proto.py @@ -32,149 +32,149 @@ ARG = 3 class Proto: def __init__ (self, file, date, timeout, log = None): - """Initialise and set file (serial port, pty, socket...), date - function and timeout value. - - - file: open file connected to the slave device. - - date: when called, should return the current time. - - timeout: time after which retransmission is done. - - log: if defined, will be called with a log string. - - """ - self.file = file - self.date = date - self.last_send = None - self.timeout = timeout - self.send_queue = [ ] - self.state = START - self.log = log - self.handlers = { } + """Initialise and set file (serial port, pty, socket...), date + function and timeout value. + + - file: open file connected to the slave device. + - date: when called, should return the current time. + - timeout: time after which retransmission is done. + - log: if defined, will be called with a log string. + + """ + self.file = file + self.date = date + self.last_send = None + self.timeout = timeout + self.send_queue = [ ] + self.state = START + self.log = log + self.handlers = { } def send (self, *frame): - """Queue a frame to send.""" - if not self.send_queue: - self.last_send = None - self.send_queue.append (Frame (*frame)) + """Queue a frame to send.""" + if not self.send_queue: + self.last_send = None + self.send_queue.append (Frame (*frame)) def read (self): - """Read from file and receive frames.""" - for f in self.recv (): - if self.log: - self.log ('recv %s' % f) - if self.send_queue and f == self.send_queue[0]: - del self.send_queue[0] - if self.send_queue: - self.send_head () - else: - self.dispatch (f) + """Read from file and receive frames.""" + for f in self.recv (): + if self.log: + self.log ('recv %s' % f) + if self.send_queue and f == self.send_queue[0]: + del self.send_queue[0] + if self.send_queue: + self.send_head () + else: + self.dispatch (f) def sync (self): - """Send frames, return True if all is sent.""" - if self.send_queue and (self.last_send is None - or self.last_send + self.timeout < self.date ()): - self.send_head () - return not self.send_queue + """Send frames, return True if all is sent.""" + if self.send_queue and (self.last_send is None + or self.last_send + self.timeout < self.date ()): + self.send_head () + return not self.send_queue def wait (self, cond = None): - """Wait forever or until cond () is True.""" - while not (self.sync () and (cond is not None or cond ())): - fds = select.select ((self,), (), (), self.timeout)[0] - for i in fds: - assert i is self - i.read () + """Wait forever or until cond () is True.""" + while not (self.sync () and (cond is not None or cond ())): + fds = select.select ((self,), (), (), self.timeout)[0] + for i in fds: + assert i is self + i.read () def register (self, command, fmt, handler): - """Register a handler for the specified command and format. The - handler will receive decoded arguments.""" - key = (command, struct.calcsize ('!' + fmt)) - assert key not in self.handlers - self.handlers[key] = (handler, fmt) + """Register a handler for the specified command and format. The + handler will receive decoded arguments.""" + key = (command, struct.calcsize ('!' + fmt)) + assert key not in self.handlers + self.handlers[key] = (handler, fmt) def fileno (self): - """Return file descriptor, for use with select.""" - return self.file.fileno () + """Return file descriptor, for use with select.""" + return self.file.fileno () def send_head (self): - """Send first frame from the send queue.""" - if self.log: - self.log ('send %s' % self.send_queue[0]) - self.file.write (self.send_queue[0].data ()) - self.last_send = self.date () + """Send first frame from the send queue.""" + if self.log: + self.log ('send %s' % self.send_queue[0]) + self.file.write (self.send_queue[0].data ()) + self.last_send = self.date () def recv (self): - """Receive a frame, used as a generator.""" - for c in self.file.read (1): - if c == '!': - self.state = BANG - else: - if self.state == START: - pass - elif self.state == BANG: - if c.isalpha (): - self.recv_command = c - self.recv_args = '' - self.state = CMD - else: - self.recv_error () - elif self.state == CMD: - if c == '\r': - f = Frame (self.recv_command) - f.args = binascii.unhexlify (self.recv_args) - yield f - elif (c >= '0' and c <= '9') or (c >= 'a' and c <= 'f'): - self.recv_args += c - self.state = ARG - else: - self.recv_error () - else: - assert self.state == ARG - if (c >= '0' and c <= '9') or (c >= 'a' and c <= 'f'): - self.recv_args += c - self.state = CMD - else: - self.recv_error () + """Receive a frame, used as a generator.""" + for c in self.file.read (1): + if c == '!': + self.state = BANG + else: + if self.state == START: + pass + elif self.state == BANG: + if c.isalpha (): + self.recv_command = c + self.recv_args = '' + self.state = CMD + else: + self.recv_error () + elif self.state == CMD: + if c == '\r': + f = Frame (self.recv_command) + f.args = binascii.unhexlify (self.recv_args) + yield f + elif (c >= '0' and c <= '9') or (c >= 'a' and c <= 'f'): + self.recv_args += c + self.state = ARG + else: + self.recv_error () + else: + assert self.state == ARG + if (c >= '0' and c <= '9') or (c >= 'a' and c <= 'f'): + self.recv_args += c + self.state = CMD + else: + self.recv_error () def recv_error (self): - """Handle reception errors.""" - self.state = START - if self.log: - self.log ('error') - # Resend now. - if self.send_queue: - self.send_head () + """Handle reception errors.""" + self.state = START + if self.log: + self.log ('error') + # Resend now. + if self.send_queue: + self.send_head () def dispatch (self, frame): - """Pass a received frame to the correct handler.""" - key = (frame.command, len (frame.args)) - if key in self.handlers: - h = self.handlers[key] - h[0] (*(frame.decode (h[1]))) + """Pass a received frame to the correct handler.""" + key = (frame.command, len (frame.args)) + if key in self.handlers: + h = self.handlers[key] + h[0] (*(frame.decode (h[1]))) class Frame: def __init__ (self, command = None, fmt = '', *args): - """Initiliase a frame. If command is given, the frame is constructed - using a struct.pack like fmt string.""" - if command: - assert len (command) == 1 and command.isalpha () - self.command = command - self.args = struct.pack ('!' + fmt, *args) - else: - self.command = None - self.args = '' + """Initiliase a frame. If command is given, the frame is constructed + using a struct.pack like fmt string.""" + if command: + assert len (command) == 1 and command.isalpha () + self.command = command + self.args = struct.pack ('!' + fmt, *args) + else: + self.command = None + self.args = '' def data (self): - """Get a frame representation ready to send.""" - return '!' + self.command + binascii.hexlify (self.args) + '\r' + """Get a frame representation ready to send.""" + return '!' + self.command + binascii.hexlify (self.args) + '\r' def decode (self, fmt): - """Decode using a struct.unpack like fmt string.""" - return struct.unpack ('!' + fmt, self.args) + """Decode using a struct.unpack like fmt string.""" + return struct.unpack ('!' + fmt, self.args) def __eq__ (self, other): - """Compare for equality.""" - return self.command == other.command and self.args == other.args + """Compare for equality.""" + return self.command == other.command and self.args == other.args def __str__ (self): - """Convert to string.""" - return '!' + self.command + binascii.hexlify (self.args) + """Convert to string.""" + return '!' + self.command + binascii.hexlify (self.args) diff --git a/host/proto/test/fio.py b/host/proto/test/fio.py index 07646199..f520d41e 100644 --- a/host/proto/test/fio.py +++ b/host/proto/test/fio.py @@ -1,22 +1,22 @@ class IO: def __init__ (self, fin = None, fout = None): - if fin is None: - import sys, tty - self.fin = sys.stdin - self.fout = sys.stdout - tty.setcbreak (sys.stdin.fileno ()) - else: - self.fin = fin - self.fout = fout + if fin is None: + import sys, tty + self.fin = sys.stdin + self.fout = sys.stdout + tty.setcbreak (sys.stdin.fileno ()) + else: + self.fin = fin + self.fout = fout def read (self, *args): - buf = self.fin.read (*args).replace ('\n', '\r') - return buf + buf = self.fin.read (*args).replace ('\n', '\r') + return buf def write (self, *args): - return self.fout.write (*[i.replace ('\r', '\n') for i in args]) + return self.fout.write (*[i.replace ('\r', '\n') for i in args]) def fileno (self): - return self.fin.fileno () + return self.fin.fileno () diff --git a/host/proto/test/interactive.py b/host/proto/test/interactive.py index a8251f6d..d34d6d59 100644 --- a/host/proto/test/interactive.py +++ b/host/proto/test/interactive.py @@ -26,4 +26,4 @@ while True: p.sync () fds = select.select ((p,), (), (), 0.1)[0] for i in fds: - i.read () + i.read () diff --git a/host/utils/forked.py b/host/utils/forked.py index 9e72d7d3..5185034a 100644 --- a/host/utils/forked.py +++ b/host/utils/forked.py @@ -35,14 +35,14 @@ class Forked: """ def __init__ (self, function): - """Initialise, fork, and call the given function in the children - process.""" - self.pid = os.fork () - if self.pid == 0: - function () - sys.exit (0) + """Initialise, fork, and call the given function in the children + process.""" + self.pid = os.fork () + if self.pid == 0: + function () + sys.exit (0) def kill (self): - """Kill the forked function.""" - os.kill (self.pid, signal.SIGTERM) - os.waitpid (self.pid, 0) + """Kill the forked function.""" + os.kill (self.pid, signal.SIGTERM) + os.waitpid (self.pid, 0) -- cgit v1.2.3