00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 from Tix import *
00024 import time
00025 import math
00026
00027
00028 import RTC
00029 import OpenRTM_aist
00030
00031
00032 lrfviewer_spec = ["implementation_id", "LRFViewer",
00033 "type_name", "LRFViewer",
00034 "description", "Laser Range Finder Viewer component",
00035 "version", "1.0",
00036 "vendor", "Noriaki Ando, AIST",
00037 "category", "example",
00038 "activity_type", "DataFlowComponent",
00039 "max_instance", "1",
00040 "language", "Python",
00041 "lang_type", "SCRIPT",
00042 ""]
00043
00044
00045
00046
00047
00048
00049
00050 class LRFViewer(OpenRTM_aist.DataFlowComponentBase):
00051 def __init__(self, manager):
00052 OpenRTM_aist.DataFlowComponentBase.__init__(self, manager)
00053
00054 self.range_data = []
00055 self.start_point = 0
00056 self.end_point = 768
00057 self.angular_res = 0.0
00058 return
00059
00060 def onInitialize(self):
00061 _pose3D = RTC.Pose3D(RTC.Point3D(0.0, 0.0, 0.0),
00062 RTC.Orientation3D(0.0, 0.0, 0.0))
00063 _size3D = RTC.Size3D(0.0, 0.0, 0.0)
00064 _geometry3D = RTC.Geometry3D(_pose3D, _size3D)
00065 _rangerConfig = RTC.RangerConfig(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
00066 self._d_rangeData = RTC.RangeData(RTC.Time(0,0),
00067 [],
00068 RTC.RangerGeometry(_geometry3D, []),
00069 _rangerConfig)
00070
00071 self._rangeDataIn = OpenRTM_aist.InPort("range_data", self._d_rangeData)
00072 self.addInPort("range_data", self._rangeDataIn)
00073
00074 return RTC.RTC_OK
00075
00076 def onShutdown(self, ec_id):
00077 return RTC.RTC_OK
00078
00079 def onDeactivated(self, ec_id):
00080 self.range_data = []
00081 self.start_point = 0
00082 self.end_point = 768
00083 return RTC.RTC_OK
00084
00085 def onExecute(self, ec_id):
00086 if self._rangeDataIn.isNew():
00087 _rangeData = self._rangeDataIn.read()
00088 self.range_data = _rangeData.ranges
00089 self.start_point = _rangeData.config.minAngle
00090 self.end_point = _rangeData.config.maxAngle
00091 self.angular_res = _rangeData.config.angularRes
00092 time.sleep(0.01)
00093 return RTC.RTC_OK
00094
00095 def get_range_data(self):
00096 return self.range_data
00097
00098 def get_start_point(self):
00099 return self.start_point
00100
00101 def get_end_point(self):
00102 return self.end_point
00103
00104 def get_angular_res(self):
00105 return self.angular_res
00106
00107
00108 class ToggleItem:
00109 def __init__(self):
00110 self.active = True
00111 return
00112
00113 def __del__(self):
00114 self.delete()
00115 return
00116
00117 def activate(self):
00118 self.active = True
00119 self.draw()
00120 return
00121
00122 def deactivate(self):
00123 self.active = False
00124 self.delete()
00125 return
00126
00127 def toggle(self):
00128 if self.active:
00129 self.deactivate()
00130 else:
00131 self.activate()
00132 return
00133
00134
00135 class CanvasText(ToggleItem):
00136 def __init__(self, canvas, text, x, y):
00137 ToggleItem.__init__(self)
00138 self.canvas = canvas
00139 self.id = self.canvas.create_text(x, y, text=text)
00140 self.text = text
00141 self.x = x
00142 self.y = y
00143 self.draw_text(x, y, text)
00144 return
00145
00146 def draw(self):
00147 if self.active == False: return
00148 self.delete()
00149 self.id = self.canvas.create_text(self.x, self.y, text=self.text)
00150 return
00151
00152 def draw_text(self, x, y, text):
00153 self.x = x
00154 self.y = y
00155 self.text = text
00156 self.draw()
00157 return
00158
00159 def delete(self):
00160 self.canvas.delete(self.id)
00161 return
00162
00163 class CanvasGrid(ToggleItem):
00164 def __init__(self, canvas, x0, y0, width, height, pitch, color, linewd):
00165 ToggleItem.__init__(self)
00166 self.canvas = canvas
00167 self.x0 = x0
00168 self.y0 = y0
00169 self.width = width
00170 self.height = height
00171 self.pitch = pitch
00172 self.color = color
00173 self.linewd = linewd
00174 self.idx = []
00175 self.idy = []
00176
00177 self.draw()
00178 return
00179
00180 def draw(self):
00181 if self.active == False: return
00182 self.delete()
00183
00184 x_start = int(self.x0 % self.pitch)
00185 x_num = int((self.width - x_start) / self.pitch) + 1
00186 for x in range(x_num):
00187 x0 = x_start + self.pitch * x
00188 id = self.canvas.create_line(x0, 0, x0, self.height,
00189 fill=self.color, width=self.linewd)
00190 self.idx.append(id)
00191
00192 y_start = int(self.y0 % self.pitch)
00193 y_num = int((self.height - y_start) / self.pitch) + 1
00194 for y in range(y_num):
00195 y0 = y_start + self.pitch * y
00196 id = self.canvas.create_line(0, y0, self.width, y0,
00197 fill=self.color, width=self.linewd)
00198 self.idy.append(id)
00199
00200 for i in self.idx:
00201 self.canvas.tag_lower(i)
00202 for i in self.idy:
00203 self.canvas.tag_lower(i)
00204
00205 return
00206
00207 def delete(self):
00208 for i in self.idx:
00209 self.canvas.delete(i)
00210 for i in self.idy:
00211 self.canvas.delete(i)
00212 return
00213
00214 def set_pitch(self, pitch):
00215 if pitch != 0:
00216 self.pitch = pitch
00217
00218 self.draw()
00219 return
00220
00221
00222 class CanvasAxis(ToggleItem):
00223 def __init__(self, canvas, width, height, color="#ffffff", linewd=1):
00224 ToggleItem.__init__(self)
00225 self.x0 = width/2
00226 self.y0 = height/2
00227 self.width = width
00228 self.height = height
00229 self.color = color
00230 self.linewd = linewd
00231 self.canvas = canvas
00232 self.id = [None] * 4
00233 self.draw()
00234 return
00235
00236 def draw(self):
00237 if self.active == False: return
00238 self.delete()
00239 self.id[0] = self.canvas.create_line(0, self.height/2,
00240 self.width, self.height/2,
00241 fill = self.color,
00242 width = self.linewd)
00243 self.id[1] = self.canvas.create_text(self.width - 10,
00244 self.height/2 + 10,
00245 text="x",
00246 fill = self.color,
00247 font="courier 12")
00248 self.id[2] = self.canvas.create_line(self.width/2, 0,
00249 self.width/2, self.height,
00250 fill = self.color,
00251 width = self.linewd)
00252 self.id[3] = self.canvas.create_text(self.width/2 + 10,
00253 + 10, text="y",
00254 fill = self.color,
00255 font="courier 12")
00256
00257 return
00258
00259 def delete(self):
00260 for i in self.id:
00261 self.canvas.delete(i)
00262 return
00263
00264
00265 class ScaledObject:
00266 def __init__(self, simulator):
00267 self.simulator = simulator
00268 self.tick = simulator.get_tick()
00269 self.canvas = simulator.get_canvas()
00270 self.trans = simulator.get_translation()
00271 return
00272
00273 def translate(self, x, y, dx, dy, dth):
00274 return self.trans(x, y, dx, dy, dth)
00275
00276 def get_tick(self):
00277 return self.simulator.get_tick()
00278
00279
00280
00281
00282
00283
00284 class LRFrange(ScaledObject):
00285 def __init__(self, simulator,
00286 line_color="#ff0000", fill_color="#ff0000", linewd=1):
00287 ScaledObject.__init__(self, simulator)
00288 self.fill_color = fill_color
00289 self.line_color = line_color
00290 self.default_fill_color = fill_color
00291 self.default_line_color = line_color
00292 self.linewd = linewd
00293 self.rdata = []
00294 self.pre_data = []
00295 self.poly_id = None
00296 self.source = None
00297
00298
00299 self.beg_angle = -45
00300 self.end_angle = 225
00301 self.angle_per_step = 360.0 / 1024.0
00302 self.valid_beg_angle = 44 * 360.0 / 1024.0
00303 self.valid_end_angle = self.valid_beg_angle + 725 * self.angle_per_step
00304 self.offset_step = 0
00305
00306 self.threshold = 0.0
00307 self.sfilter = 0.0
00308 self.tfilter = 0.0
00309
00310 self.threshold_check = BooleanVar()
00311 self.threshold_check.set(True)
00312 self.tfilter_check = BooleanVar()
00313 self.tfilter_check.set(True)
00314 self.sfilter_check = BooleanVar()
00315 self.sfilter_check.set(True)
00316
00317 self.threshold_var = DoubleVar()
00318 self.threshold_var.set(self.threshold)
00319 self.tfilter_var = DoubleVar()
00320 self.tfilter_var.set(self.tfilter)
00321 self.sfilter_var = DoubleVar()
00322 self.sfilter_var.set(self.sfilter)
00323
00324 self.update()
00325 return
00326
00327 def create_ctrl(self, frame):
00328 self.lrf_fill_check = StringVar()
00329 self.lrf_fill_check.set("on")
00330 self.lrf_line_check = StringVar()
00331 self.lrf_line_check.set("on")
00332
00333 text = Label(frame, text="LRF range area", anchor=W, justify=LEFT)
00334
00335 line = Checkbutton(frame, text="Line",
00336 onvalue="on", offvalue="off",
00337 justify=LEFT, anchor=W,
00338 variable=self.lrf_line_check,
00339 command=self.line_toggle)
00340
00341 fill = Checkbutton(frame, text="Fill",
00342 onvalue="on", offvalue="off",
00343 justify=LEFT, anchor=W,
00344 variable=self.lrf_fill_check,
00345 command=self.fill_toggle)
00346
00347 thresh = Checkbutton(frame, text="Threshold",
00348 onvalue=True, offvalue=False,
00349 justify=LEFT, anchor=W,
00350 variable=self.threshold_check)
00351 thresh_scale = Scale(frame, from_=0, to=100, resolution=0.1,
00352 label="Threshold", command=self.on_threshold,
00353 variable=self.threshold_var, orient=HORIZONTAL)
00354
00355 tfilter = Checkbutton(frame, text="Filter(Time)",
00356 onvalue=True, offvalue=False,
00357 justify=LEFT, anchor=W,
00358 variable=self.tfilter_check)
00359 tfilter_scale = Scale(frame, from_=0, to=1, resolution=0.01,
00360 label="Filter", command=self.on_tfilter,
00361 variable=self.tfilter_var, orient=HORIZONTAL)
00362
00363 sfilter = Checkbutton(frame, text="Filter(Spacial)",
00364 onvalue=True, offvalue=False,
00365 justify=LEFT, anchor=W,
00366 variable=self.sfilter_check)
00367 sfilter_scale = Scale(frame, from_=0, to=1, resolution=0.01,
00368 label="Filter", command=self.on_sfilter,
00369 variable=self.sfilter_var, orient=HORIZONTAL)
00370
00371 for w in [text, line, fill, thresh, thresh_scale,
00372 tfilter, tfilter_scale, sfilter, sfilter_scale]:
00373 w.pack(side=TOP, anchor=W, fill=X)
00374 return
00375
00376 def on_threshold(self, var):
00377 self.threshold = self.threshold_var.get()
00378 return
00379
00380 def on_sfilter(self, var):
00381 self.sfilter = self.sfilter_var.get()
00382 return
00383
00384 def on_tfilter(self, var):
00385 self.tfilter = self.tfilter_var.get()
00386 return
00387
00388 def line_toggle(self):
00389 if self.lrf_line_check.get() == "on":
00390 self.line_color = self.default_line_color
00391 else:
00392 self.line_color = ""
00393 return
00394
00395 def fill_toggle(self):
00396 if self.lrf_fill_check.get() == "on":
00397 self.fill_color = self.default_fill_color
00398 else:
00399 self.fill_color = ""
00400 return
00401
00402 def set_data_source(self, source):
00403 self.source = source
00404 return
00405
00406 def set_value(self, data):
00407 self.rdata = data
00408 return
00409
00410 def draw(self):
00411 self.delete()
00412 rpos = []
00413 rpos.append(self.translate(0, 0, 0, 0, 0))
00414 rpos.append(self.range_to_pos(self.rdata))
00415 self.poly_id = self.canvas.create_polygon(rpos,
00416 width = self.linewd,
00417 outline = self.line_color,
00418 fill = self.fill_color,
00419 smooth = 1,
00420 splinesteps = 5)
00421 return
00422
00423 def range_to_pos(self, data):
00424 pos = []
00425 pre_d = 0
00426
00427 tfilter = self.tfilter_check.get()
00428 sfilter = self.sfilter_check.get()
00429 thresh = self.threshold_check.get()
00430
00431
00432 if tfilter and len(data) == len(self.pre_data):
00433 for (n, d) in enumerate(data):
00434 k_t = self.tfilter
00435 data[n] = self.pre_data[n] * k_t + d * (1 - k_t)
00436
00437
00438 for (n, d) in enumerate(data):
00439
00440 if thresh and d < self.threshold:
00441 d = 10000
00442
00443 if sfilter:
00444 k_s = self.sfilter
00445 d = pre_d * k_s + d * (1 - k_s)
00446 pre_d = d
00447
00448
00449
00450
00451
00452 th = (n + self.offset_step) * self.angle_per_step + self.beg_angle
00453 x = d * math.cos(th)
00454 y = d * math.sin(th)
00455 pos.append(self.translate(x, y, 0, 0, 0))
00456 self.pre_data = data
00457 return pos
00458
00459 def delete(self):
00460 if self.poly_id != None:
00461 self.canvas.delete(self.poly_id)
00462 return
00463
00464 def update(self):
00465 if self.source != None:
00466 rdata = self.source.get_range_data()
00467 if len(rdata) != 0:
00468 self.rdata = rdata
00469
00470 res = self.source.get_angular_res()
00471 if res:
00472 self.angle_per_step = res
00473
00474 beg_angle = self.source.get_start_point()
00475 if beg_angle:
00476 self.beg_angle = beg_angle
00477
00478 end_angle = self.source.get_end_point()
00479 if end_angle:
00480 self.end_angle = end_angle
00481
00482 else:
00483 pass
00484 self.draw()
00485
00486
00487
00488
00489
00490
00491
00492 class TkLRFViewer(Frame):
00493 def __init__(self, master=None, width=480, height=480):
00494 Frame.__init__(self, master)
00495
00496
00497 self.width = width
00498 self.height = height
00499
00500 self.x0 = width/2
00501 self.y0 = height/2
00502
00503 self.wd = 150
00504
00505 self.robots = {}
00506
00507 self.robot = None
00508 self.postext = None
00509
00510 self.scale = 1.0
00511 self.scale_var = DoubleVar()
00512 self.scale_var.set(self.scale)
00513
00514 self.grid_pitch = 50
00515
00516 self.tick = 0.1
00517 self.default_tick = 0.1
00518 self.tickscale_var = DoubleVar()
00519 self.tickscale_var.set(self.tick)
00520
00521 self.axis_check = StringVar()
00522 self.axis_check.set("on")
00523 self.grid_check = StringVar()
00524 self.grid_check.set("on")
00525 self.rnames = {}
00526
00527
00528 self.init()
00529 self.pack()
00530
00531
00532 self.after(20, self.on_update)
00533 return
00534
00535 def init(self):
00536 self.canvas = Canvas(self, bg="#000000",
00537 width = self.width, height = self.height)
00538 self.canvas.pack(side=LEFT)
00539
00540 self.can_grid = CanvasGrid(self.canvas, self.x0, self.y0,
00541 self.width, self.height, self.grid_pitch,
00542 "#aaaaaa", 1)
00543 self.can_axis = CanvasAxis(self.canvas, self.width, self.height,
00544 "#ffffff", 1)
00545
00546 self.frame = Frame(self)
00547 self.frame.pack(side=LEFT)
00548
00549
00550 self.scrctrl_frame = Frame(self.frame, width=self.wd, height=300,
00551 relief=GROOVE, bd=2)
00552 self.scrctrl_frame.pack(side=TOP, fill=X)
00553 self.create_scale(self.scrctrl_frame)
00554 self.create_checkbutton(self.scrctrl_frame)
00555
00556
00557 self.lrfctrl_frame = Frame(self.frame, width=self.wd, height=300,
00558 relief=GROOVE, bd=2)
00559 self.lrfctrl_frame.pack(side=TOP, fill=X)
00560 self.lrf = LRFrange(self)
00561 self.lrf.create_ctrl(self.lrfctrl_frame)
00562
00563 return
00564
00565
00566
00567 def on_update(self):
00568 self.lrf.update()
00569 self.after(20, self.on_update)
00570 return
00571
00572 def get_tick(self):
00573 return self.tick
00574
00575 def get_canvas(self):
00576 return self.canvas
00577
00578 def get_translation(self):
00579 return self.real_to_canvas
00580
00581
00582
00583
00584 def create_scale(self, frame):
00585 dummy = Frame(frame, width=self.wd)
00586 dummy.pack(side=TOP)
00587 sl = Scale(frame, from_=0, to=10, resolution=0.01,
00588 label="Scale Factor", command=self.on_scale,
00589 variable=self.scale_var, orient=HORIZONTAL)
00590 bt = Button(frame, text="Reset Scale", command=self.reset_scale)
00591 sl.pack(side=TOP, fill=X)
00592 bt.pack(side=TOP, fill=X)
00593 return
00594
00595 def on_scale(self, val):
00596 v = float(val)
00597 if v == 0.0:
00598 pitch = 0
00599 else:
00600 pitch = self.grid_pitch/v
00601 self.scale = v
00602 self.can_grid.set_pitch(pitch)
00603 return
00604
00605 def reset_scale(self):
00606 self.scale_var.set(1.)
00607 pitch = self.grid_pitch/1.0
00608 self.scale = 1.0
00609 self.can_grid.set_pitch(pitch)
00610 return
00611
00612 def on_tickchange(self, val):
00613 v = self.tickscale_var.get()
00614 if v == 0.0:
00615 self.tick = 0
00616 else:
00617 self.tick = v
00618 return
00619
00620 def reset_tickscale(self):
00621 self.tick = self.default_tick
00622 self.tickscale_var.set(self.default_tick)
00623
00624
00625
00626
00627
00628
00629 def create_checkbutton(self, frame):
00630 axis = Checkbutton(frame, text="Axis",
00631 onvalue="on", offvalue="off",
00632 justify=LEFT, anchor=W,
00633 variable=self.axis_check,
00634 command=self.can_axis.toggle)
00635 grid = Checkbutton(frame, text="Grid",
00636 onvalue="on", offvalue="off",
00637 justify=LEFT, anchor=W,
00638 variable=self.grid_check,
00639 command=self.can_grid.toggle)
00640 for w in [axis, grid]:
00641 w.pack(side=TOP, anchor=W, fill=X)
00642
00643 def on_rname_toggle(self):
00644 for r in self.rnames.keys():
00645 self.rnames[r].toggle()
00646 return
00647
00648
00649
00650
00651
00652
00653 def real_to_canvas(self, x, y, dx, dy, dt):
00654
00655
00656
00657
00658 x_tmp = (math.cos(dt) * x - math.sin(dt) * y + dx)/self.scale
00659 y_tmp = (math.sin(dt) * x + math.cos(dt) * y + dy)/self.scale
00660
00661 xo = x_tmp + self.x0
00662 yo = -y_tmp + self.y0
00663 return xo, yo
00664
00665 import threading
00666
00667 class test_data_creator(threading.Thread):
00668 def __init__(self, lrf, step = 681):
00669 threading.Thread.__init__(self)
00670 import time
00671 self.lrf = lrf
00672 self.step = step
00673 self.flag = True
00674 return
00675
00676 def stop(self):
00677 self.flag = False
00678 return
00679
00680 def run(self):
00681 import random
00682 data = [0] * 681
00683 pre = 0
00684 while self.flag:
00685 for i in range(681):
00686 if i % 5 == 0:
00687 data[i] = pre * 0.9 + random.randint(0, 255) * 0.1
00688 pre = data[i]
00689 else:
00690 data[i] = pre
00691 pre = data[i]
00692 self.lrf.set_value(data)
00693 time.sleep(0.1)
00694
00695 return
00696
00697 def main():
00698 m = TkLRFViewer(Tk())
00699 m.master.title("Laser Range Finder Viewer")
00700
00701 mgr = OpenRTM_aist.Manager.init(sys.argv)
00702 mgr.activateManager()
00703 profile = OpenRTM_aist.Properties(defaults_str=lrfviewer_spec)
00704 mgr.registerFactory(profile, LRFViewer, OpenRTM_aist.Delete)
00705 mgr.runManager(True)
00706 lrf_rtc = mgr.createComponent("LRFViewer")
00707 m.lrf.set_data_source(lrf_rtc)
00708 m.mainloop()
00709 mgr.shutdown()
00710
00711
00712 if __name__ == '__main__': main()