summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Schodet2009-04-30 09:53:44 +0200
committerNicolas Schodet2009-04-30 09:53:44 +0200
commit69305ae1ed6da084b6ee65dba3ce44f0d6cbe2d1 (patch)
treebb898529fc7e986429094dd9b5d28ce4397dbba7
parentfb3cfa5a0ac1acb58c2067cd1aad0339b534f982 (diff)
* host/simu, digital/io/tools:
- new simulation infrastructure.
-rw-r--r--digital/io/tools/test_simu.py35
-rw-r--r--host/simu/inter/drawable.py10
-rw-r--r--host/simu/inter/inter.py127
-rw-r--r--host/simu/inter/inter_node.py110
-rw-r--r--host/simu/model/__init__.py0
-rw-r--r--host/simu/model/position.py39
-rw-r--r--host/simu/model/servo.py38
-rw-r--r--host/simu/model/switch.py39
-rw-r--r--host/simu/robots/__init__.py0
-rw-r--r--host/simu/robots/giboulee/__init__.py0
-rw-r--r--host/simu/robots/giboulee/link/__init__.py0
-rw-r--r--host/simu/robots/giboulee/link/bag.py33
-rw-r--r--host/simu/robots/giboulee/model/__init__.py0
-rw-r--r--host/simu/robots/giboulee/model/arm.py38
-rw-r--r--host/simu/robots/giboulee/model/bag.py38
-rw-r--r--host/simu/robots/giboulee/model/sorter.py32
-rw-r--r--host/simu/robots/giboulee/view/__init__.py0
-rw-r--r--host/simu/robots/giboulee/view/arm.py60
-rw-r--r--host/simu/robots/giboulee/view/bag.py41
-rw-r--r--host/simu/robots/giboulee/view/robot.py64
-rw-r--r--host/simu/robots/giboulee/view/sorter.py61
-rw-r--r--host/simu/view/__init__.py0
-rw-r--r--host/simu/view/servo.py54
-rw-r--r--host/simu/view/switch.py40
-rw-r--r--host/simu/view/table_eurobot2008.py98
25 files changed, 946 insertions, 11 deletions
diff --git a/digital/io/tools/test_simu.py b/digital/io/tools/test_simu.py
index 943d6935..158b006e 100644
--- a/digital/io/tools/test_simu.py
+++ b/digital/io/tools/test_simu.py
@@ -32,14 +32,21 @@ import io
import io.init
from proto.popen_io import PopenIO
-from inter.inter_node import InterNode
+import simu.view.table_eurobot2008 as table
+import simu.robots.giboulee.link.bag as robot_link
+import simu.robots.giboulee.model.bag as robot_model
+import simu.robots.giboulee.view.bag as robot_view
+
+from simu.inter.inter_node import InterNode
from Tkinter import *
class TestSimu (InterNode):
- """Inter, with simulated programs."""
+ """Interface, with simulated programs."""
- robot_start_pos = ((200, 2100 - 70, math.radians (-90)),
- (3000 - 200, 2100 - 70, math.radians (-90)))
+ robot_start_pos = {
+ False: (200, 2100 - 70, math.radians (-90)),
+ True: (3000 - 200, 2100 - 70, math.radians (-90))
+ }
def __init__ (self, asserv_cmd, io_cmd):
# Hub.
@@ -48,7 +55,7 @@ class TestSimu (InterNode):
# InterNode.
InterNode.__init__ (self)
def time ():
- return self.node.date / self.TICK
+ return self.node.date / self.node.tick
# Asserv.
self.asserv = asserv.Proto (PopenIO (asserv_cmd), time,
**asserv.init.host)
@@ -58,9 +65,18 @@ class TestSimu (InterNode):
self.io = io.Proto (PopenIO (io_cmd), time, **io.init.host)
self.io.async = True
self.tk.createfilehandler (self.io, READABLE, self.io_read)
+ # Add table.
+ self.table = table.Table (self.table_view)
+ # Add robot.
+ self.robot_link = robot_link.Bag (self.node)
+ self.robot_model = robot_model.Bag (self.robot_link)
+ self.robot_view = robot_view.Bag (self.table, self.actuator_view,
+ self.sensor_frame, self.robot_model)
+ for adc in self.robot_link.io.adc:
+ adc.value = 0
# Color switch.
+ self.robot_model.color_switch.register (self.change_color)
self.change_color ()
- self.colorVar.trace_variable ('w', self.change_color)
def close (self):
self.forked_hub.kill ()
@@ -85,13 +101,10 @@ class TestSimu (InterNode):
self.io.proto.sync ()
def change_color (self, *dummy):
- i = self.colorVar.get ()
+ i = self.robot_model.color_switch.state
self.asserv.set_simu_pos (*self.robot_start_pos[i]);
if __name__ == '__main__':
app = TestSimu (('../../asserv/src/asserv/asserv.host', '-m', 'giboulee'),
('../src/io.host'))
- try:
- app.mainloop ()
- finally:
- app.close ()
+ app.mainloop ()
diff --git a/host/simu/inter/drawable.py b/host/simu/inter/drawable.py
index d11ad9d6..bcf1823f 100644
--- a/host/simu/inter/drawable.py
+++ b/host/simu/inter/drawable.py
@@ -140,6 +140,16 @@ class DrawableCanvas(Tkinter.Canvas):
self.__updated = [ ]
self._Drawable__children = [ ]
+ def resize (self, width, height, xorigin = None, yorigin = None):
+ """Change size given at initialisation. Will be used on next
+ configure event."""
+ self.__width = width
+ self.__height = height
+ if xorigin is not None:
+ self.__xorigin = xorigin
+ if yorigin is not None:
+ self.__yorigin = yorigin
+
def __resize (self, ev):
# Compute new scale.
w, h = float (ev.width), float (ev.height)
diff --git a/host/simu/inter/inter.py b/host/simu/inter/inter.py
new file mode 100644
index 00000000..b8a889e5
--- /dev/null
+++ b/host/simu/inter/inter.py
@@ -0,0 +1,127 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Simulation interface."""
+from simu.inter.drawable import *
+from Tkinter import *
+
+class TableView (DrawableCanvas):
+ """This class handle the view of the table and every items inside it."""
+
+ TABLE_WIDTH = 3000
+ TABLE_HEIGHT = 2100
+ MARGIN = 150
+
+ def __init__ (self, master = None,
+ width = TABLE_WIDTH, height = TABLE_HEIGHT):
+ DrawableCanvas.__init__ (self,
+ width + 2 * self.MARGIN, height + 2 * self.MARGIN,
+ -width / 2, -height / 2,
+ master, borderwidth = 1, relief = 'sunken',
+ background = 'white')
+
+class ActuatorView (DrawableCanvas):
+ """This class handle the view of the actuators inside the robot."""
+
+ UNIT = 120
+
+ def __init__ (self, master = None):
+ DrawableCanvas.__init__ (self, 1, 1, 0, 0, master,
+ borderwidth = 1, relief = 'sunken', background = 'white')
+ self.configure (width = self.UNIT, height = self.UNIT)
+ self.size = 0.0
+
+ def add_view (self, width = 1.0, height = 1.0):
+ """Return a drawable suitable for an actuator view."""
+ ratio = float (height) / float (width)
+ self.size += ratio
+ self.resize (1, self.size, 0, self.size / 2)
+ self.configure (width = self.UNIT, height = self.UNIT * self.size)
+ d = Drawable (self)
+ d.trans_scale (1.0 / width)
+ d.trans_translate ((0, - self.size + ratio / 2))
+ return d
+
+class Inter (Frame):
+ """Robot simulation interface."""
+
+ def __init__ (self, master = None):
+ Frame.__init__ (self, master)
+ self.pack (expand = True, fill = 'both')
+ self.create_widgets ()
+
+ def create_widgets (self):
+ # Main layout.
+ self.right_frame = Frame (self)
+ self.right_frame.pack (side = 'right', fill = 'y')
+ self.quit_button = Button (self.right_frame, text = 'Quit',
+ command = self.quit)
+ self.quit_button.pack (side = 'top')
+ # Actuator view.
+ self.actuator_view = ActuatorView (self.right_frame)
+ self.actuator_view.pack (side = 'bottom', fill = 'x')
+ # Sensor frame.
+ self.sensor_frame = Frame (self.right_frame, borderwidth = 1,
+ relief = 'sunken')
+ self.sensor_frame.pack (side = 'bottom', fill = 'x')
+ # Table view.
+ self.table_view = TableView (self)
+ self.table_view.pack (expand = True, fill = 'both')
+
+ def update (self, *args):
+ self.table_view.update ()
+ self.actuator_view.update ()
+
+if __name__ == '__main__':
+ class TestTable (Drawable):
+ def __init__ (self, onto, w, h):
+ Drawable.__init__ (self, onto)
+ self.w, self.h = w, h
+ def draw (self):
+ self.reset ()
+ w, h = self.w, self.h
+ self.draw_rectangle ((0, 0), (w, h), fill = 'blue')
+ Drawable.draw (self)
+ class TestRectangle (Drawable):
+ def __init__ (self, onto, w, h, c1, c2):
+ Drawable.__init__ (self, onto)
+ self.w, self.h = 0.9 * w, 0.9 * h
+ self.c1, self.c2 = c1, c2
+ def draw (self):
+ self.reset ()
+ w, h = self.w, self.h
+ self.draw_rectangle ((-w/2, -h/2), (w/2, h/2), fill = self.c1)
+ self.draw_rectangle ((0, 0), (w/2, h/2), fill = self.c2)
+ Drawable.draw (self)
+ class TestSensor:
+ def __init__ (self, master):
+ self.button = Checkbutton (master, text = 'Sensor',
+ indicatoron = False)
+ self.button.pack (side = 'top')
+ app = Inter ()
+ TestTable (app.table_view, 3000, 2100)
+ TestRectangle (app.actuator_view.add_view (1, 1), 1, 1, 'red', 'green')
+ TestRectangle (app.actuator_view.add_view (2, 1), 2, 1, 'green', 'blue')
+ TestRectangle (app.actuator_view.add_view (1, 2), 1, 2, 'blue', 'red')
+ TestSensor (app.sensor_frame)
+ app.mainloop ()
diff --git a/host/simu/inter/inter_node.py b/host/simu/inter/inter_node.py
new file mode 100644
index 00000000..ab1b5acf
--- /dev/null
+++ b/host/simu/inter/inter_node.py
@@ -0,0 +1,110 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Simulation interface coupled with a mex node."""
+from simu.inter.inter import Inter
+from mex.node import Node
+from Tkinter import *
+import time
+
+class InterNode (Inter):
+
+ def __init__ (self):
+ Inter.__init__ (self)
+ # Create node and bind to Tk.
+ self.node = Node ()
+ self.node.tick = 900 # tick/s
+ self.tk.createfilehandler (self.node, READABLE, self.read)
+ # Animation attributes.
+ self.date = 0
+ self.synced = True
+ self.step_after = None
+ self.step_time = None
+
+ def create_widgets (self):
+ Inter.create_widgets (self)
+ self.now_label = Label (self.right_frame, text = 'Now: 0 s')
+ self.now_label.pack ()
+ self.step_button = Button (self.right_frame, text = 'Step',
+ command = self.step)
+ self.step_button.pack ()
+ self.step_size_scale = Scale (self.right_frame, orient = HORIZONTAL,
+ from_ = 0.05, to = 1.0, resolution = 0.05)
+ self.step_size_scale.pack ()
+ self.play_var = IntVar ()
+ self.play_button = Checkbutton (self.right_frame,
+ variable = self.play_var, text = 'Play', command = self.play)
+ self.play_button.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.step_size_scale.get () * self.node.tick))
+ self.synced = False
+ self.step_after = None
+ self.step_time = time.time ()
+
+ def play (self):
+ """Activate auto-steping."""
+ if self.play_var.get ():
+ if self.step_after is None and self.synced:
+ self.step ()
+ self.step_button.configure (state = DISABLED)
+ else:
+ if self.step_after is not None:
+ self.after_cancel (self.step_after)
+ self.step_after = None
+ self.step_button.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.now_label.configure (text = 'Now: %.2f s'
+ % (float (self.date) / self.node.tick))
+ self.update ()
+ if self.play_var.get ():
+ assert self.step_after is None
+ next = self.step_time + self.step_size_scale.get ()
+ delay = next - time.time ()
+ if delay > 0:
+ self.step_after = self.after (int (delay * 1000),
+ self.step)
+ else:
+ self.step ()
+
+if __name__ == '__main__':
+ import mex.hub
+ import utils.forked
+ h = mex.hub.Hub (min_clients = 1)
+ fh = utils.forked.Forked (h.wait)
+ try:
+ app = InterNode ()
+ app.mainloop()
+ finally:
+ fh.kill ()
+ import time
+ time.sleep (1)
diff --git a/host/simu/model/__init__.py b/host/simu/model/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/model/__init__.py
diff --git a/host/simu/model/position.py b/host/simu/model/position.py
new file mode 100644
index 00000000..eec395e7
--- /dev/null
+++ b/host/simu/model/position.py
@@ -0,0 +1,39 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Robot position model."""
+from utils.observable import Observable
+
+class Position (Observable):
+
+ def __init__ (self, link):
+ Observable.__init__ (self)
+ self.link = link
+ self.link.register (self.__notified)
+ self.__notified ()
+
+ def __notified (self):
+ self.pos = self.link.pos
+ self.angle = self.link.angle
+ self.notify ()
+
diff --git a/host/simu/model/servo.py b/host/simu/model/servo.py
new file mode 100644
index 00000000..7c83d4b3
--- /dev/null
+++ b/host/simu/model/servo.py
@@ -0,0 +1,38 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Servo motor model."""
+from utils.observable import Observable
+
+class Servo (Observable):
+
+ def __init__ (self, link):
+ Observable.__init__ (self)
+ self.link = link
+ self.link.register (self.__notified)
+ self.__notified ()
+
+ def __notified (self):
+ self.value = self.link.value
+ self.notify ()
+
diff --git a/host/simu/model/switch.py b/host/simu/model/switch.py
new file mode 100644
index 00000000..617a22ff
--- /dev/null
+++ b/host/simu/model/switch.py
@@ -0,0 +1,39 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Switch model."""
+from utils.observable import Observable
+
+class Switch (Observable):
+
+ def __init__ (self, link):
+ Observable.__init__ (self)
+ self.link = link
+ self.state = None
+ self.register (self.__update)
+ self.__update ()
+
+ def __update (self):
+ self.link.state = self.state
+ self.link.notify ()
+
diff --git a/host/simu/robots/__init__.py b/host/simu/robots/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/robots/__init__.py
diff --git a/host/simu/robots/giboulee/__init__.py b/host/simu/robots/giboulee/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/robots/giboulee/__init__.py
diff --git a/host/simu/robots/giboulee/link/__init__.py b/host/simu/robots/giboulee/link/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/robots/giboulee/link/__init__.py
diff --git a/host/simu/robots/giboulee/link/bag.py b/host/simu/robots/giboulee/link/bag.py
new file mode 100644
index 00000000..c8c1b285
--- /dev/null
+++ b/host/simu/robots/giboulee/link/bag.py
@@ -0,0 +1,33 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee bag of links."""
+import io.mex
+import asserv.mex
+
+class Bag:
+
+ def __init__ (self, node):
+ self.asserv = asserv.mex.Mex (node)
+ self.io = io.mex.Mex (node)
+
diff --git a/host/simu/robots/giboulee/model/__init__.py b/host/simu/robots/giboulee/model/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/robots/giboulee/model/__init__.py
diff --git a/host/simu/robots/giboulee/model/arm.py b/host/simu/robots/giboulee/model/arm.py
new file mode 100644
index 00000000..cfefd11b
--- /dev/null
+++ b/host/simu/robots/giboulee/model/arm.py
@@ -0,0 +1,38 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee arm."""
+from utils.observable import Observable
+
+class Arm (Observable):
+
+ def __init__ (self, motor_link):
+ Observable.__init__ (self)
+ self.motor_link = motor_link
+ self.motor_link.register (self.__motor_notified)
+ self.__motor_notified ()
+
+ def __motor_notified (self):
+ self.angle = self.motor_link.angle
+ self.notify ()
+
diff --git a/host/simu/robots/giboulee/model/bag.py b/host/simu/robots/giboulee/model/bag.py
new file mode 100644
index 00000000..fadccabe
--- /dev/null
+++ b/host/simu/robots/giboulee/model/bag.py
@@ -0,0 +1,38 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee bag of models."""
+from simu.model.switch import Switch
+from simu.model.position import Position
+from simu.robots.giboulee.model.arm import Arm
+from simu.robots.giboulee.model.sorter import Sorter
+
+class Bag:
+
+ def __init__ (self, link_bag):
+ self.jack = Switch (link_bag.io.jack)
+ self.color_switch = Switch (link_bag.io.color_switch)
+ self.position = Position (link_bag.asserv.position)
+ self.arm = Arm (link_bag.asserv.aux[0])
+ self.sorter = Sorter (link_bag.io.servo[0:5], link_bag.io.servo[5])
+
diff --git a/host/simu/robots/giboulee/model/sorter.py b/host/simu/robots/giboulee/model/sorter.py
new file mode 100644
index 00000000..042b0717
--- /dev/null
+++ b/host/simu/robots/giboulee/model/sorter.py
@@ -0,0 +1,32 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee balls sorter."""
+from simu.model.servo import Servo
+
+class Sorter:
+
+ def __init__ (self, trap_servo_links, door_servo_link):
+ self.traps = [ Servo (link) for link in trap_servo_links ]
+ self.door = Servo (door_servo_link)
+
diff --git a/host/simu/robots/giboulee/view/__init__.py b/host/simu/robots/giboulee/view/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/robots/giboulee/view/__init__.py
diff --git a/host/simu/robots/giboulee/view/arm.py b/host/simu/robots/giboulee/view/arm.py
new file mode 100644
index 00000000..205857a2
--- /dev/null
+++ b/host/simu/robots/giboulee/view/arm.py
@@ -0,0 +1,60 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee arm."""
+from simu.inter.drawable import Drawable
+from math import pi, cos, sin
+
+class Arm (Drawable):
+ """Giboulee arm."""
+
+ width = 1
+ height = 1
+
+ def __init__ (self, onto, model):
+ Drawable.__init__ (self, onto)
+ self.model = model
+ self.model.register (self.__notified)
+ self.__notified ()
+
+ def __notified (self):
+ self.angle = self.model.angle
+ self.update ()
+
+ 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')
+ if self.angle is not None:
+ 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)))
+ Drawable.draw (self)
+
diff --git a/host/simu/robots/giboulee/view/bag.py b/host/simu/robots/giboulee/view/bag.py
new file mode 100644
index 00000000..709d775f
--- /dev/null
+++ b/host/simu/robots/giboulee/view/bag.py
@@ -0,0 +1,41 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee bag of views."""
+from simu.view.switch import Switch
+from simu.robots.giboulee.view.robot import Robot
+from simu.robots.giboulee.view.arm import Arm
+from simu.robots.giboulee.view.sorter import Sorter
+
+class Bag:
+
+ def __init__ (self, table, actuator_view, sensor_frame, model_bag):
+ self.jack = Switch (sensor_frame, model_bag.jack, 'Jack')
+ self.color_switch = Switch (sensor_frame, model_bag.color_switch,
+ 'Color')
+ self.robot = Robot (table, model_bag.position)
+ self.arm = Arm (actuator_view.add_view (Arm.width, Arm.height),
+ model_bag.arm)
+ self.sorter = Sorter (actuator_view.add_view (Sorter.width,
+ Sorter.height), model_bag.sorter)
+
diff --git a/host/simu/robots/giboulee/view/robot.py b/host/simu/robots/giboulee/view/robot.py
new file mode 100644
index 00000000..2ffcacb2
--- /dev/null
+++ b/host/simu/robots/giboulee/view/robot.py
@@ -0,0 +1,64 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2008 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee robot view."""
+import simu.inter.drawable
+
+class Robot (simu.inter.drawable.Drawable):
+
+ def __init__ (self, onto, position_model):
+ """Construct and make connections."""
+ simu.inter.drawable.Drawable.__init__ (self, onto)
+ self.position_model = position_model
+ self.position_model.register (self.__position_notified)
+ self.__position_notified ()
+
+ def __position_notified (self):
+ """Called on position modifications."""
+ self.pos = self.position_model.pos
+ self.angle = self.position_model.angle
+ self.update ()
+
+ def draw (self):
+ """Draw the robot."""
+ self.reset ()
+ if self.pos is not None:
+ self.trans_rotate (self.angle)
+ self.trans_translate (self.pos)
+ # Draw robot body.
+ 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))
+ # Draw Robot axis.
+ axes_fill = '#404040'
+ self.draw_line ((-70, 0), (170, 0), fill = axes_fill,
+ arrow = 'last')
+ # Draw Robot wheels.
+ f = 142 + 2 * 31.5 - 13.5 # Wheel spacing
+ wr = 63 / 2 # Wheel diameter
+ 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)
+ # Extends.
+ simu.inter.drawable.Drawable.draw (self)
+
diff --git a/host/simu/robots/giboulee/view/sorter.py b/host/simu/robots/giboulee/view/sorter.py
new file mode 100644
index 00000000..a0e09197
--- /dev/null
+++ b/host/simu/robots/giboulee/view/sorter.py
@@ -0,0 +1,61 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Giboulee balls sorter."""
+from simu.inter.drawable import Drawable
+from simu.view.servo import Servo
+from math import pi
+
+class Sorter (Drawable):
+
+ width = 1
+ height = 1
+
+ def __init__ (self, onto, sorter_model):
+ Drawable.__init__ (self, onto)
+ self.traps = [
+ Servo (self, sorter_model.traps[0],
+ (-2.5, -1), 0.8, 0, pi/2),
+ Servo (self, sorter_model.traps[1],
+ (-1.5, -0.9), 0.8, 0, pi/2),
+ Servo (self, sorter_model.traps[2],
+ (-0.5, -0.8), 0.8, 0, pi/2),
+ Servo (self, sorter_model.traps[3],
+ (0.5, -0.8), 0.8, pi, -pi/2),
+ Servo (self, sorter_model.traps[4],
+ (1.5, -0.9), 0.8, pi, -pi/2),
+ ]
+ self.door = Servo (self, sorter_model.door,
+ (-2.5, 1.3), 0.8, -pi/6, pi/3),
+
+ def draw (self):
+ self.reset ()
+ self.trans_scale (0.9/5)
+ 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')
+ Drawable.draw (self)
+
diff --git a/host/simu/view/__init__.py b/host/simu/view/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/host/simu/view/__init__.py
diff --git a/host/simu/view/servo.py b/host/simu/view/servo.py
new file mode 100644
index 00000000..7c67df09
--- /dev/null
+++ b/host/simu/view/servo.py
@@ -0,0 +1,54 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Generic servo motor."""
+from simu.inter.drawable import Drawable
+from math import pi, sin, cos
+
+class Servo (Drawable):
+
+ def __init__ (self, onto, model, coord = (0, 0), l = 1, start = 0,
+ extent = pi / 2):
+ Drawable.__init__ (self, onto)
+ self.model = model
+ self.coord = coord
+ self.l = l
+ self.start = start
+ self.extent = extent
+ self.model.register (self.__notified)
+ self.__notified ()
+
+ def __notified (self):
+ self.value = self.model.value
+ self.update ()
+
+ def draw (self):
+ self.reset ()
+ if self.value is not None:
+ self.draw_arc (self.coord, self.l, start = self.start,
+ extent = self.extent, style = 'arc', outline = '#808080')
+ a = self.start + self.value * self.extent
+ self.draw_line (self.coord, (self.coord[0] + self.l * cos (a),
+ self.coord[1] + self.l * sin (a)))
+ Drawable.draw (self)
+
diff --git a/host/simu/view/switch.py b/host/simu/view/switch.py
new file mode 100644
index 00000000..c0ec2d58
--- /dev/null
+++ b/host/simu/view/switch.py
@@ -0,0 +1,40 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2009 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Generic switch."""
+from Tkinter import *
+
+class Switch:
+
+ def __init__ (self, frame, model, text):
+ self.var = IntVar ()
+ self.button = Checkbutton (frame, variable = self.var,
+ command = self.__update, text = text, indicatoron = False)
+ self.button.pack ()
+ self.model = model
+ self.__update ()
+
+ def __update (self):
+ self.model.state = self.var.get () != 0
+ self.model.notify ()
+
diff --git a/host/simu/view/table_eurobot2008.py b/host/simu/view/table_eurobot2008.py
new file mode 100644
index 00000000..b956101a
--- /dev/null
+++ b/host/simu/view/table_eurobot2008.py
@@ -0,0 +1,98 @@
+# simu - Robot simulation. {{{
+#
+# Copyright (C) 2008 Nicolas Schodet
+#
+# APBTeam:
+# Web: http://apbteam.org/
+# Email: team AT apbteam DOT org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# }}}
+"""Eurobot 2008 table."""
+from simu.inter.drawable import Drawable
+
+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]])
+ Drawable.draw (self)
+
+if __name__ == '__main__':
+ from simu.inter.inter import Inter
+ app = Inter ()
+ Table (app.table_view)
+ app.mainloop ()