TkMobileRobotSimulator.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 # -*- Python -*-
00004 
00005 # @brief 2D mobile robot on tk canvas
00006 # @date $Date$
00007 # @author Norkai Ando <n-ando@aist.go.jp>
00008 #
00009 # Copyright (C) 2007
00010 #     Noriaki Ando
00011 #     Task-intelligence Research Group,
00012 #     Intelligent Systems Research Institute,
00013 #     National Institute of
00014 #         Advanced Industrial Science and Technology (AIST), Japan
00015 #     All rights reserved.
00016 #
00017 # $Id$
00018 #
00019 
00020 # $Log$
00021 #
00022 
00023 #from Tkinter import *
00024 from Tix import *
00025 import time
00026 import math
00027 
00028 # Import RTM module
00029 import RTC
00030 import OpenRTM_aist
00031 # This module's spesification
00032 # <rtc-template block="module_spec">
00033 tkmobilerobotsimulator_spec = ["implementation_id", "TkMobileRobotSimulator", 
00034                                "type_name",         "TkMobileRobotSimulator", 
00035                                "description",       "sample component for Python and Tkinter", 
00036                                "version",           "1.0", 
00037                                "vendor",            "Noriaki Ando, AIST", 
00038                                "category",          "example", 
00039                                "activity_type",     "DataFlowComponent", 
00040                                "max_instance",      "10", 
00041                                "language",          "Python", 
00042                                "lang_type",         "SCRIPT",
00043                                ""]
00044 # </rtc-template>
00045 
00046 
00047 class TkMobileRobotSimulator(OpenRTM_aist.DataFlowComponentBase):
00048   def __init__(self, manager):
00049     OpenRTM_aist.DataFlowComponentBase.__init__(self, manager)
00050         
00051     self.pos = []
00052     self.vel = []
00053     return
00054 
00055   def onInitialize(self):
00056     self._d_vel = RTC.TimedFloatSeq(RTC.Time(0,0),[])
00057     self._velIn = OpenRTM_aist.InPort("vel", self._d_vel)
00058         
00059     self._d_pos = RTC.TimedFloatSeq(RTC.Time(0,0),[])
00060     self._posOut = OpenRTM_aist.OutPort("pos", self._d_pos)
00061         
00062     # Set InPort buffers
00063     self.addInPort("vel",self._velIn)
00064     self.addOutPort("pos",self._posOut)
00065 
00066     # Bind variables and configuration variable
00067     return RTC.RTC_OK
00068 
00069   def onShutdown(self, ec_id):
00070     return RTC.RTC_OK
00071 
00072   def onDeactivated(self, ec_id):
00073     self.pos = []
00074     self.vel = []
00075     return RTC.RTC_OK
00076 
00077   def onExecute(self, ec_id):
00078     if self._velIn.isNew():
00079       self.vel = self._velIn.read().data
00080     self._d_pos.data = self.pos
00081     self._posOut.write()
00082     time.sleep(0.01)
00083     return RTC.RTC_OK
00084 
00085   def get_velocity(self):
00086     return self.vel
00087 
00088   def set_position(self, pos):
00089     self.pos = pos
00090 
00091 
00092 class ToggleItem:
00093   def __init__(self):
00094     self.active = True
00095     return
00096 
00097   def __del__(self):
00098     self.delete()
00099     return
00100 
00101   def activate(self):
00102     self.active = True
00103     self.draw()
00104     return
00105 
00106   def deactivate(self):
00107     self.active = False
00108     self.delete()
00109     return
00110 
00111   def toggle(self):
00112     if self.active:
00113       self.deactivate()
00114     else:
00115       self.activate()
00116     return
00117 
00118 class CanvasText(ToggleItem):
00119   def __init__(self, canvas, text, x, y):
00120     ToggleItem.__init__(self)
00121     self.canvas = canvas
00122     self.id = self.canvas.create_text(x, y, text=text)
00123     self.text = text
00124     self.x = x
00125     self.y = y
00126     self.draw_text(x, y, text)
00127     return
00128 
00129   def draw(self):
00130     if self.active == False: return
00131     self.delete()
00132     self.id = self.canvas.create_text(self.x, self.y, text=self.text)
00133     return
00134 
00135   def draw_text(self, x, y, text):
00136     self.x = x
00137     self.y = y
00138     self.text = text
00139     self.draw()
00140     return
00141     
00142   def delete(self):
00143     self.canvas.delete(self.id)
00144     return
00145 
00146 class RobotTitle(ToggleItem):
00147   def __init__(self, simulator, robot, name, r):
00148     ToggleItem.__init__(self)
00149     self.canvas = simulator.get_canvas()
00150     self.trans = simulator.get_translation()
00151     self.robot = robot
00152     self.name = name
00153     self.r = r
00154     self.id_circle = None
00155     self.id_line0 = None
00156     self.id_line1 = None
00157     self.id_name = None
00158     self.id_pos = None
00159     self.llength = 50
00160     return
00161 
00162   def draw(self):
00163     if self.active == False: return
00164     self.delete()
00165     rx, ry, rt = self.robot.get_pos()
00166         
00167     tmp_x0 = - self.r
00168     tmp_y0 = - self.r
00169     tmp_x1 =   self.r
00170     tmp_y1 =   self.r
00171     x0, y0 = self.trans(tmp_x0, tmp_y0, rx, ry, 0)
00172     x1, y1 = self.trans(tmp_x1, tmp_y1, rx, ry, 0)
00173 
00174     self.id_circle = self.canvas.create_oval(x0, y0, x1, y1,
00175                                              width=2,
00176                                              fill="", outline="#aaaaaa")
00177     r =  (x1 - x0)/2
00178     xo = x0 + r
00179     yo = y0 - r
00180     
00181     lx0 = xo + (r / math.sqrt(2))
00182     ly0 = yo - (r / math.sqrt(2))
00183     lx1 = lx0 + self.llength
00184     ly1 = ly0 - self.llength
00185 
00186     self.id_line0 = self.canvas.create_line(lx0, ly0, lx1, ly1,
00187                                             fill="#777777")
00188     self.id_line1 = self.canvas.create_line(lx1, ly1, lx1 + 120, ly1,
00189                                             fill="#777777")
00190     self.id_name = self.canvas.create_text(lx1+120, ly1-8,
00191                                            anchor=E, text=self.name)
00192     pos_text = '(%5.2f, %5.2f, %5.2f)' % (rx, ry, (rt*180/math.pi)%360)
00193     self.id_pos = self.canvas.create_text(lx1+120, ly1+8,
00194                                           anchor=E, text=pos_text)
00195     return
00196 
00197 
00198   def delete(self):
00199     if self.id_circle != None:
00200       self.canvas.delete(self.id_circle)
00201     if self.id_line0 != None:
00202       self.canvas.delete(self.id_line0)
00203     if self.id_line1 != None:
00204       self.canvas.delete(self.id_line1)
00205     if self.id_name != None:
00206       self.canvas.delete(self.id_name)
00207     if self.id_pos != None:
00208       self.canvas.delete(self.id_pos)
00209     return
00210 
00211 
00212 class CanvasGrid(ToggleItem):
00213   def __init__(self, canvas, x0, y0, width, height, pitch, color, linewd):
00214     ToggleItem.__init__(self)
00215     self.canvas = canvas
00216     self.x0 = x0
00217     self.y0 = y0
00218     self.width = width
00219     self.height = height
00220     self.pitch = pitch
00221     self.color = color
00222     self.linewd = linewd
00223     self.idx = []
00224     self.idy = []
00225 
00226     self.draw()
00227     return
00228 
00229 
00230   def draw(self):
00231     if self.active == False: return
00232     self.delete()
00233 
00234     x_start = int(self.x0 % self.pitch)
00235     x_num   = int((self.width - x_start) / self.pitch) + 1
00236     for x in range(x_num):
00237       x0 = x_start + self.pitch * x
00238       id = self.canvas.create_line(x0, 0, x0, self.height,
00239                                    fill=self.color, width=self.linewd)
00240       self.idx.append(id)
00241 
00242     y_start = int(self.y0 % self.pitch)
00243     y_num   = int((self.height - y_start) / self.pitch) + 1
00244     for y in range(y_num):
00245       y0 = y_start + self.pitch * y
00246       id = self.canvas.create_line(0, y0, self.width, y0,
00247                                    fill=self.color, width=self.linewd)
00248       self.idy.append(id)
00249 
00250     for i in self.idx:
00251       self.canvas.tag_lower(i)
00252     for i in self.idy:
00253       self.canvas.tag_lower(i)
00254     return
00255 
00256 
00257   def delete(self):
00258     for i in self.idx:
00259       self.canvas.delete(i)
00260     for i in self.idy:
00261       self.canvas.delete(i)
00262     return
00263 
00264 
00265   def set_pitch(self, pitch):
00266     self.pitch = pitch
00267     self.draw()
00268     return
00269 
00270 
00271 class CanvasAxis(ToggleItem):
00272   def __init__(self, canvas, width, height):
00273     ToggleItem.__init__(self)
00274     self.x0 = width/2
00275     self.y0 = height/2
00276     self.width = width
00277     self.height = height
00278     self.canvas = canvas
00279     self.id = [None] * 4
00280     self.draw()
00281     return
00282 
00283 
00284   def draw(self):
00285     if self.active == False: return
00286     self.delete()
00287     self.id[0] = self.canvas.create_line(0, self.height/2, 
00288                                          self.width, self.height/2)
00289     self.id[1] = self.canvas.create_text(self.width - 10,
00290                                          self.height/2 + 10,
00291                                          text="x")
00292     self.id[2] = self.canvas.create_line(self.width/2, 0, 
00293                                          self.width/2, self.height)
00294     self.id[3] = self.canvas.create_text(self.width/2 + 10,
00295                                          + 10, text="y")
00296     
00297     return
00298 
00299   def delete(self):
00300     for i in self.id:
00301       self.canvas.delete(i)
00302     return
00303 
00304 
00305 
00306 class SimulatedObject:
00307   def __init__(self, simulator):
00308     self.simulator = simulator
00309     self.tick = simulator.get_tick()
00310     self.canvas = simulator.get_canvas()
00311     self.trans = simulator.get_translation()
00312     return
00313 
00314   def translate(self, x, y, dx, dy, dth):
00315     return self.trans(x, y, dx, dy, dth)
00316 
00317   def get_tick(self):
00318     return self.simulator.get_tick()
00319 
00320 
00321 import tkSimpleDialog
00322 
00323 class PropertyDialog:
00324   def __init__(self):
00325     # robot's profile
00326     self.name = ""
00327     self.type = ""
00328     self.description = ""
00329     self.vendor = ""
00330     # robot's parameter/input/output
00331     self.param = []
00332     self.input = []
00333     self.output = []
00334     # max length of label text
00335     self.label_len = 0
00336     # max length of unit text
00337     self.unit_len = 0
00338 
00339     self.apply_param  = None
00340     self.apply_input  = None
00341     self.reset_output = None
00342     return
00343 
00344   def set_profile(self, name, type, description, vendor):
00345     self.name = name
00346     self.type = type
00347     self.description = description
00348     self.vendor =vendor
00349     return
00350 
00351   def append_parameter(self, label, variable, unit):
00352     self.param.append({"label":label, "var":variable, "unit":unit})
00353     self.label_len = max(len(label), self.label_len)
00354     self.unit_len  = max(len(unit), self.unit_len)
00355     return
00356 
00357   def append_input(self, label, variable, unit):
00358     self.input.append({"label":label, "var":variable, "unit":unit})
00359     self.label_len = max(len(label), self.label_len)
00360     self.unit_len  = max(len(unit), self.unit_len)
00361     return
00362 
00363   def append_output(self, label, variable, unit):
00364     self.output.append({"label":label, "var":variable, "unit":unit})
00365     self.label_len = max(len(label), self.label_len)
00366     self.unit_len  = max(len(unit), self.unit_len)
00367     return
00368 
00369   def set_apply_param(self, func):
00370     self.apply_param = func
00371     return
00372 
00373   def set_apply_input(self, func):
00374     self.apply_input = func
00375     return
00376 
00377   def set_reset_output(self, func):
00378     self.reset_output = func
00379     return
00380 
00381   def pack(self):
00382     f = Toplevel()
00383     self.toplevel = f
00384     f.title(self.name)
00385     w0 = LabelFrame(f, label="Robot's Profile",
00386                     options="frame.anchor w frame.justify left")
00387     prof_frame = w0.subwidget('frame')
00388     self.profile_label(prof_frame)
00389 
00390     w1 = LabelFrame(f, label="Robot's Parameters")
00391     param_frame = w1.subwidget('frame')
00392     self.label_entries(param_frame, self.param)
00393     if self.apply_param != None:
00394       self.button(param_frame, "Apply", self.apply_param)
00395 
00396     w2 = LabelFrame(f, label="Robot's Input Values")
00397     input_frame = w2.subwidget('frame')
00398     self.label_entries(input_frame, self.input)
00399     if self.apply_input != None:
00400       self.button(input_frame, "Set", self.apply_input)
00401 
00402     w3 = LabelFrame(f, label="Robot's Output Values")
00403     output_frame = w3.subwidget('frame')
00404     self.label_entries(output_frame, self.output)
00405     if self.reset_output != None:
00406       self.button(output_frame, "Reset", self.reset_output)
00407 
00408 
00409     for w in [w0, w1, w2, w3]:
00410       w.pack(side=TOP, anchor=W, fill=X)
00411     self.button(f, "OK", self.on_ok)
00412 
00413     return
00414 
00415   def on_ok(self):
00416     self.toplevel.destroy()
00417     return
00418 
00419 
00420   def button(self, master, label, func):
00421     bt = Button(master, text=label, command=func, width=10,
00422                 padx=3, pady=3)
00423     bt.pack(side=TOP, padx=5, pady=5)
00424     return
00425 
00426 
00427   def profile_label(self, master):
00428     t = ["Robot's name: ", "Robot's type: ", "Description: ", "Vendor: "]
00429     for i in range(len(t)):
00430       Label(master, text=t[i], anchor=W).grid(row=i, sticky=W,
00431                                               padx=3, pady=3)
00432     l = [self.name, self.type, self.description, self.vendor]
00433     for i in range(len(l)):
00434       Label(master, text=l[i], anchor=W).grid(row=i, column=1, sticky=W,
00435                                               padx=3, pady=3)
00436     return
00437 
00438         
00439   def label_entry(self, master, label0, var, label1):
00440     f = Frame(master)
00441     l0 = Label(f, text=label0, width=self.label_len, justify=LEFT, anchor=W)
00442     e = Entry(f, width=7, textvariable=var,
00443               justify=RIGHT, relief=GROOVE, bd=2)
00444     l1 = Label(f, text=label1, width=self.unit_len, justify=LEFT, anchor=W)
00445     for w in [l0, e, l1]:
00446       w.pack(side=LEFT, anchor=W, padx=3, pady=3)
00447     return f
00448 
00449   def label_entries(self, f, props):
00450     for p in props:
00451       self.label_entry(f, p["label"], p["var"], p["unit"]).pack(side=TOP)
00452     return
00453 
00454 
00455 
00456 class DiffMobileModel:
00457   def __init__(self, radius, wheeld, pos = (0, 0, math.pi/2), dt=0.1):
00458     self.radius = radius
00459     self.wheeld = wheeld
00460     self.dt = dt
00461     self.pre_x = pos[0]
00462     self.pre_y = pos[1]
00463     self.pre_t = pos[2]
00464     self.pre_x_dot = 0
00465     self.pre_y_dot = 0
00466     self.pre_t_dot = 0
00467     return
00468 
00469 
00470   def set_wheel_radius(self, radius):
00471     # wheel radius [m]
00472     self.radius = radius
00473     return
00474 
00475 
00476   def set_wheel_distance(self, distance):
00477     # distance between wheels [m]
00478     self.wheeld = distance
00479     return
00480 
00481   
00482   def set_time_tick(self, tick):
00483     # time tick for simulation [sec]
00484     self.dt = tick
00485     return
00486 
00487 
00488   def set_pos(self, pos = (0, 0, math.pi/2)):
00489     # x:     pos[0] [m]
00490     # y:     pos[1] [m]
00491     # theta: pos[2] [rad]
00492     self.pre_x = pos[0]
00493     self.pre_y = pos[1]
00494     self.pre_t = pos[2]
00495     return
00496 
00497 
00498   def get_pos(self):
00499     return self.pre_x, self.pre_y, self.pre_t
00500 
00501   def control(self, w1, w2):
00502     # w1: [rad/s]
00503     # w2: [rad/s]
00504     x_dot = self.radius * (w1 + w2) * math.cos(self.pre_t)
00505     y_dot = self.radius * (w1 + w2) * math.sin(self.pre_t)
00506     t_dot = self.radius * (-w1 + w2) / self.wheeld
00507 
00508     x     = (self.dt * (self.pre_x_dot + x_dot) / 2) + self.pre_x
00509     y     = (self.dt * (self.pre_y_dot + y_dot) / 2) + self.pre_y
00510     theta = (self.dt * (self.pre_t_dot + t_dot) / 2) + self.pre_t
00511 
00512     self.pre_x = x
00513     self.pre_y = y
00514     self.pre_t = theta
00515 
00516     self.pre_x_dot = x_dot
00517     self.pre_y_dot = y_dot
00518     self.pre_t_dot = t_dot
00519     
00520     return x, y, theta
00521 
00522 
00523 
00524 class DDMobileRobot(SimulatedObject):
00525   count = 0
00526   def __init__(self, simulator, radius=2, wheeld=20,
00527                pos = (0, 0, math.pi/2)):
00528     SimulatedObject.__init__(self, simulator)
00529     self.tick = self.get_tick()
00530     self.model = DiffMobileModel(radius, wheeld, pos, self.tick)
00531     self.fig = [[10, 0], [5, 10], [-10, 10], [-10, -10], [5, -10]]
00532     self.id = None
00533     self.wl = 0.0
00534     self.wr = 0.0
00535     self.name = "DDMobileRobot" + str(self.__class__.count)
00536     self.__class__.count += 1 
00537     self.comp = OpenRTM_aist.Manager.instance().createComponent("TkMobileRobotSimulator")
00538 
00539     # properties
00540     self.rentry = StringVar()
00541     self.rentry.set(radius)
00542     self.dentry = StringVar()
00543     self.dentry.set(wheeld)
00544     # input variables
00545     self.wlentry = StringVar()
00546     self.wrentry = StringVar()
00547     # output variables
00548     self.xentry = StringVar()
00549     self.yentry = StringVar()
00550     self.tentry = StringVar()
00551     return
00552 
00553 
00554   def __del__(self):
00555     try:
00556       self.comp.exit()
00557       del self.comp
00558     except:
00559       pass
00560     self.delete()
00561     return
00562 
00563 
00564   def get_name(self):
00565     return self.name
00566 
00567 
00568   def set_pos(self, (x, y, th)):
00569     self.model.set_pos((x, y, th))
00570     return
00571 
00572 
00573   def get_pos(self):
00574     return self.model.get_pos()
00575 
00576 
00577   def set_wheel_velocity(self, wl, wr):
00578     self.wl = wl
00579     self.wr = wr
00580     self.wlentry.set('%5.2f'%self.wl)
00581     self.wrentry.set('%5.2f'%self.wr)
00582     return
00583 
00584 
00585   def on_update(self):
00586     self.model.set_time_tick(self.get_tick())
00587     v = self.comp.get_velocity()
00588     if len(v) == 2:
00589       self.set_wheel_velocity(v[0], v[1])
00590     self.x, self.y, self.th = self.model.control(self.wl, self.wr)
00591     self.th_deg = (self.th * 180 / math.pi) % 360
00592     self.comp.set_position((self.x, self.y, self.th_deg))
00593     self.xentry.set('%5.2f'%self.x)
00594     self.yentry.set('%5.2f'%self.y)
00595     self.tentry.set('%5.2f'%self.th_deg)
00596     self.draw()
00597     return
00598         
00599 
00600   def draw(self):
00601     # converting actual coordinate system into display coordinate
00602     # system, and drawing figures
00603     robotfig = []
00604     for pos in self.fig:
00605       robotfig.append(self.translate(pos[0], pos[1],
00606                                        self.x, self.y, self.th))
00607     if self.id != None:
00608       self.canvas.delete(self.id)
00609     self.id = self.canvas.create_polygon(robotfig, 
00610                                          fill="#00aa00",
00611                                          outline="#eeeeee")
00612     return
00613 
00614 
00615   def delete(self):
00616     if self.id != None:
00617       self.canvas.delete(self.id)
00618     return
00619 
00620 
00621   def property_page(self):
00622     p = PropertyDialog()
00623     p.set_profile(self.name, "DDMobileRobot",
00624                   "Differential Drive Mobile Robot", "AIST")
00625     p.append_parameter("Wheel radius r: ", self.rentry, "[m]")
00626     p.append_parameter("Wheel distance d: ", self.dentry, "[m]")
00627     p.append_input("Angular velocity (LEFT)  wl: ", self.wlentry, "[rad/s]")
00628     p.append_input("Angular velocity (RIGHT) wr: ", self.wrentry, "[rad/s]")
00629     p.append_output("Robot position x : ", self.xentry, "[m]")
00630     p.append_output("Robot position y : ", self.yentry, "[m]")
00631     p.append_output("Robot position th: ", self.tentry, "[deg]")
00632     p.set_apply_param(self.on_apply_param)
00633     p.set_apply_input(self.on_apply_input)
00634     p.set_reset_output(self.on_reset_output)
00635     p.pack()
00636     return
00637 
00638 
00639   def on_reset_output(self):
00640     self.set_pos((0.0, 0.0, math.pi/2))
00641     return
00642 
00643 
00644   def on_apply_param(self):
00645     r = float(self.rentry.get())
00646     d = float(self.dentry.get())
00647     self.model.set_wheel_radius(r)
00648     self.model.set_wheel_distance(d)
00649     return
00650 
00651 
00652   def on_apply_input(self):
00653     self.wl = float(self.wlentry.get())
00654     self.wr = float(self.wrentry.get())
00655     return
00656 
00657 
00658 
00659 
00660 class TkMobileRobot(Frame):
00661   def __init__(self, master=None, width=800, height=600):
00662     Frame.__init__(self, master)
00663 
00664     # canvas properties
00665     self.width = width
00666     self.height = height
00667     # zero of canvas
00668     self.x0 = width/2
00669     self.y0 = height/2
00670 
00671     self.wd = 150
00672 
00673     self.robots = {}
00674 
00675     self.robot = None
00676     self.postext = None
00677 
00678     self.scale = 1.0
00679     self.scale_var = DoubleVar()
00680     self.scale_var.set(self.scale)
00681 
00682     self.grid_pitch = 50
00683 
00684     self.tick = 0.1
00685     self.default_tick = 0.1
00686     self.tickscale_var = DoubleVar()
00687     self.tickscale_var.set(self.tick)
00688 
00689     self.axis_check = StringVar()
00690     self.axis_check.set("on")
00691     self.grid_check = StringVar()
00692     self.grid_check.set("on")
00693     self.rname_check = StringVar()
00694     self.rname_check.set("on")
00695     self.rnames = {}
00696 
00697     self.robot_kind_var = StringVar()
00698     self.robot_factory = {"DDMobileRobot": DDMobileRobot}
00699 
00700 
00701 
00702     self.init()
00703     self.pack()
00704 
00705 
00706     self.after(20, self.on_update)
00707     return
00708 
00709   def init(self):
00710     self.canvas = Canvas(self, bg="#eeeeee",
00711                          width = self.width, height = self.height)
00712     self.canvas.pack(side=LEFT)
00713 
00714     self.can_grid = CanvasGrid(self.canvas, self.x0, self.y0,
00715                                self.width, self.height, self.grid_pitch,
00716                                "#aaaaaa", 1)
00717     self.can_axis = CanvasAxis(self.canvas, self.width, self.height)
00718 
00719     self.frame = Frame(self)
00720     self.frame.pack(side=LEFT)
00721 
00722     # Screen control
00723     self.scrctrl_frame = Frame(self.frame, width=self.wd, height=300,
00724                                relief=GROOVE, bd=2)
00725     self.scrctrl_frame.pack(side=TOP, fill=X)
00726     self.create_scale(self.scrctrl_frame)
00727     self.create_checkbutton(self.scrctrl_frame)
00728 
00729     # Robot manager
00730     self.robomgr_frame = Frame(self.frame, width=self.wd, height=300,
00731                                relief=GROOVE, bd=2)
00732     self.robomgr_frame.pack(side=TOP)
00733     self.create_robotcreator(self.robomgr_frame)
00734     self.create_robotlist(self.robomgr_frame)
00735     return
00736 
00737 
00738   def on_update(self):
00739     for o in self.robots.keys():
00740       self.robots[o].on_update()
00741     for r in self.rnames.keys():
00742       self.rnames[r].draw()
00743     self.after(20, self.on_update)
00744     return
00745 
00746 
00747   def get_tick(self):
00748     return self.tick
00749 
00750 
00751   def get_canvas(self):
00752     return self.canvas
00753 
00754 
00755   def get_translation(self):
00756     return self.real_to_canvas
00757 
00758 
00759   #------------------------------------------------------------
00760   # Scale control set
00761   def create_scale(self, frame):
00762     dummy = Frame(frame, width=self.wd)
00763     dummy.pack(side=TOP)
00764     sl = Scale(frame, from_=0, to=10, resolution=0.01,
00765                label="Scale Factor", command=self.on_scale,
00766                variable=self.scale_var, orient=HORIZONTAL)
00767     bt = Button(frame, text="Reset Scale", command=self.reset_scale)
00768     sl.pack(side=TOP, fill=X)
00769     bt.pack(side=TOP, fill=X)
00770 
00771     sl = Scale(frame, from_=0.001, to=1, resolution=0.001,
00772                label="Time tick [s]", command=self.on_tickchange,
00773                variable=self.tickscale_var, orient=HORIZONTAL)
00774     bt = Button(frame, text="Reset Tick", command=self.reset_tickscale)
00775     sl.pack(side=TOP, fill=X)
00776     bt.pack(side=TOP, fill=X)
00777     return
00778 
00779 
00780   def on_scale(self, val):
00781     v =  float(val)
00782     if v == 0.0:
00783       pitch = 0
00784     else:
00785       pitch = self.grid_pitch/v
00786       self.scale = v
00787     self.can_grid.set_pitch(pitch)
00788     return
00789         
00790 
00791   def reset_scale(self):
00792     self.scale_var.set(1.)
00793     pitch = self.grid_pitch/1.0
00794     self.scale = 1.0
00795     self.can_grid.set_pitch(pitch)
00796     return
00797 
00798 
00799   def on_tickchange(self, val):
00800     v =  self.tickscale_var.get()
00801     if v == 0.0:
00802       self.tick = 0
00803     else:
00804       self.tick = v
00805     return
00806         
00807   def reset_tickscale(self):
00808     self.tick = self.default_tick
00809     self.tickscale_var.set(self.default_tick)
00810     return
00811   # end of Scale widget set
00812   #------------------------------------------------------------
00813 
00814   #------------------------------------------------------------
00815   # Canvas control set
00816   def create_checkbutton(self, frame):
00817     axis = Checkbutton(frame, text="Axis",
00818                        onvalue="on", offvalue="off",
00819                        justify=LEFT, anchor=W,
00820                        variable=self.axis_check,
00821                        command=self.can_axis.toggle)
00822     grid = Checkbutton(frame, text="Grid",
00823                        onvalue="on", offvalue="off",
00824                        justify=LEFT, anchor=W,
00825                        variable=self.grid_check,
00826                        command=self.can_grid.toggle)
00827     rname = Checkbutton(frame, text="Robots' name",
00828                         onvalue="on", offvalue="off",
00829                         justify=LEFT, anchor=W,
00830                         variable=self.rname_check,
00831                         command=self.on_rname_toggle)
00832     for w in [axis, grid, rname]:
00833       w.pack(side=TOP, anchor=W, fill=X)
00834     return
00835 
00836 
00837   def on_rname_toggle(self):
00838     for r in self.rnames.keys():
00839       self.rnames[r].toggle()
00840     return
00841 
00842 
00843   # end of Canvas control set
00844   #------------------------------------------------------------
00845 
00846 
00847   #------------------------------------------------------------
00848   # Robot creator control set
00849   def create_robotcreator(self, frame):
00850     lb = Label(frame, text="Robot Type", anchor=W, justify=LEFT)
00851 
00852     om = OptionMenu(frame, label="Type: ", variable=self.robot_kind_var)
00853     for opt in self.robot_factory.keys():
00854       om.add_command(opt, label=opt)
00855     self.robot_kind_var.set(self.robot_factory.keys()[0])
00856 
00857     creater = Button(frame, text="Create", command=self.create_robot)
00858     deleter = Button(frame, text="Delete", command=self.delete_robot)
00859 
00860     om.pack(side=TOP, fill=X)
00861     creater.pack(side=TOP, fill=X)
00862     deleter.pack(side=TOP, fill=X)
00863     return
00864 
00865 
00866   def create_robotlist(self, frame):
00867     f = Frame(frame, width=self.wd, height=200)
00868     f.pack(side=TOP, fill=BOTH, expand=1)
00869     ys = Scrollbar(f, orient = VERTICAL)
00870     ys.grid(row = 0, column=1, sticky = N+S)
00871     xs = Scrollbar(f, orient = HORIZONTAL)
00872     xs.grid(row = 1, column=0, sticky = E+W)
00873 
00874     self.rlistbox = Listbox(f,
00875                             xscrollcommand = xs.set,
00876                             yscrollcommand = ys.set,
00877                             selectmode = 'single',
00878                             setgrid = TRUE,
00879                             height=20)
00880     self.rlistbox.grid(row = 0, column = 0, sticky = N+S+E+W,)
00881     xs['command']=self.rlistbox.xview
00882     ys['command']=self.rlistbox.yview
00883     self.rlistbox.bind("<Double-Button-1>", self.on_clickrlistbox)
00884     return
00885 
00886 
00887   def on_clickrlistbox(self, event):
00888     index = self.rlistbox.curselection()
00889     if len(index) > 0:
00890       robot_name  = self.rlistbox.get(index[0])
00891       self.robots[robot_name].property_page()
00892     return
00893 
00894 
00895   def create_robot(self):
00896     kind = self.robot_kind_var.get()
00897     robot = self.robot_factory[kind](self)
00898 
00899     self.rlistbox.insert(END, robot.get_name())
00900     self.rnames[robot.get_name()] = RobotTitle(self,
00901                                                robot,
00902                                                robot.get_name(),
00903                                                20)
00904     self.robots[robot.get_name()] = robot
00905     return
00906 
00907 
00908   def delete_robot(self):
00909     index = self.rlistbox.curselection()
00910     if len(index) > 0:
00911       robot_name  = self.rlistbox.get(index[0])
00912       r = self.rnames.pop(robot_name)
00913       del(r)
00914       r = self.robots.pop(robot_name)
00915       del(r)
00916     self.rlistbox.delete(index)
00917     return
00918 
00919   # end of Robot creator control set
00920   #------------------------------------------------------------
00921 
00922 
00923   #------------------------------------------------------------
00924   # 
00925   def real_to_canvas(self, x, y, dx, dy, dt):
00926     # Simulator coordinate system -> display coordinate system
00927     # x, y: original position
00928     # dx, dy, dt: translation and rotation vector
00929     # translation and rotation
00930     x_tmp = (math.cos(dt) * x - math.sin(dt) * y + dx)/self.scale
00931     y_tmp = (math.sin(dt) * x + math.cos(dt) * y + dy)/self.scale
00932     # align to canvas coordinate system (origin is center and y+ is upward)
00933     xo =  x_tmp  + self.x0
00934     yo = -y_tmp + self.y0
00935     return xo, yo
00936 
00937 
00938 def TkMobileRobotSimulatorInit(manager):
00939   profile = OpenRTM_aist.Properties(defaults_str=tkmobilerobotsimulator_spec)
00940   manager.registerFactory(profile,
00941                           TkMobileRobotSimulator,
00942                           OpenRTM_aist.Delete)
00943   return
00944 
00945 
00946 def main():
00947   m = TkMobileRobot(Tk())
00948   m.master.title("Tk Mobile Robot Simulator")
00949   mgr = OpenRTM_aist.Manager.init(sys.argv)
00950   mgr.activateManager()
00951   profile = OpenRTM_aist.Properties(defaults_str=tkmobilerobotsimulator_spec)
00952   mgr.registerFactory(profile, TkMobileRobotSimulator, OpenRTM_aist.Delete)
00953   mgr.runManager(True)
00954   m.mainloop()
00955 
00956 if  __name__ == '__main__':
00957   main()


openrtm_aist_python
Author(s): Shinji Kurihara
autogenerated on Thu Aug 27 2015 14:17:28