TkLRFViewer.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # -*- Python -*-
4 #
5 # @brief LRFViewer component
6 # @date $Date$
7 # @author Norkai Ando <n-ando@aist.go.jp>
8 #
9 # Copyright (C) 2008
10 # Noriaki Ando
11 # Task-intelligence Research Group,
12 # Intelligent Systems Research Institute,
13 # National Institute of
14 # Advanced Industrial Science and Technology (AIST), Japan
15 # All rights reserved.
16 #
17 # $Id$
18 #
19 
20 # $Log$
21 #
22 
23 from Tix import *
24 import time
25 import math
26 
27 # Import RTM module
28 import RTC
29 import OpenRTM_aist
30 # This module's spesification
31 # <rtc-template block="module_spec">
32 lrfviewer_spec = ["implementation_id", "LRFViewer",
33  "type_name", "LRFViewer",
34  "description", "Laser Range Finder Viewer component",
35  "version", "1.0",
36  "vendor", "Noriaki Ando, AIST",
37  "category", "example",
38  "activity_type", "DataFlowComponent",
39  "max_instance", "1",
40  "language", "Python",
41  "lang_type", "SCRIPT",
42  ""]
43 # </rtc-template>
44 
45 
46 #------------------------------------------------------------
47 # LRFViewer component
48 #
49 #------------------------------------------------------------
51  def __init__(self, manager):
52  OpenRTM_aist.DataFlowComponentBase.__init__(self, manager)
53 
54  self.range_data = []
55  self.start_point = 0
56  self.end_point = 768
57  self.angular_res = 0.0
58  return
59 
60  def onInitialize(self):
61  _pose3D = RTC.Pose3D(RTC.Point3D(0.0, 0.0, 0.0),
62  RTC.Orientation3D(0.0, 0.0, 0.0))
63  _size3D = RTC.Size3D(0.0, 0.0, 0.0)
64  _geometry3D = RTC.Geometry3D(_pose3D, _size3D)
65  _rangerConfig = RTC.RangerConfig(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
66  self._d_rangeData = RTC.RangeData(RTC.Time(0,0),
67  [],
68  RTC.RangerGeometry(_geometry3D, []),
69  _rangerConfig)
70 
71  self._rangeDataIn = OpenRTM_aist.InPort("range_data", self._d_rangeData)
72  self.addInPort("range_data", self._rangeDataIn)
73 
74  return RTC.RTC_OK
75 
76  def onShutdown(self, ec_id):
77  return RTC.RTC_OK
78 
79  def onDeactivated(self, ec_id):
80  self.range_data = []
81  self.start_point = 0
82  self.end_point = 768
83  return RTC.RTC_OK
84 
85  def onExecute(self, ec_id):
86  if self._rangeDataIn.isNew():
87  _rangeData = self._rangeDataIn.read()
88  self.range_data = _rangeData.ranges
89  self.start_point = _rangeData.config.minAngle
90  self.end_point = _rangeData.config.maxAngle
91  self.angular_res = _rangeData.config.angularRes
92  time.sleep(0.01)
93  return RTC.RTC_OK
94 
95  def get_range_data(self):
96  return self.range_data
97 
98  def get_start_point(self):
99  return self.start_point
100 
101  def get_end_point(self):
102  return self.end_point
103 
104  def get_angular_res(self):
105  return self.angular_res
106 
107 
109  def __init__(self):
110  self.active = True
111  return
112 
113  def __del__(self):
114  self.delete()
115  return
116 
117  def activate(self):
118  self.active = True
119  self.draw()
120  return
121 
122  def deactivate(self):
123  self.active = False
124  self.delete()
125  return
126 
127  def toggle(self):
128  if self.active:
129  self.deactivate()
130  else:
131  self.activate()
132  return
133 
134 
136  def __init__(self, canvas, text, x, y):
137  ToggleItem.__init__(self)
138  self.canvas = canvas
139  self.id = self.canvas.create_text(x, y, text=text)
140  self.text = text
141  self.x = x
142  self.y = y
143  self.draw_text(x, y, text)
144  return
145 
146  def draw(self):
147  if self.active == False: return
148  self.delete()
149  self.id = self.canvas.create_text(self.x, self.y, text=self.text)
150  return
151 
152  def draw_text(self, x, y, text):
153  self.x = x
154  self.y = y
155  self.text = text
156  self.draw()
157  return
158 
159  def delete(self):
160  self.canvas.delete(self.id)
161  return
162 
164  def __init__(self, canvas, x0, y0, width, height, pitch, color, linewd):
165  ToggleItem.__init__(self)
166  self.canvas = canvas
167  self.x0 = x0
168  self.y0 = y0
169  self.width = width
170  self.height = height
171  self.pitch = pitch
172  self.color = color
173  self.linewd = linewd
174  self.idx = []
175  self.idy = []
176 
177  self.draw()
178  return
179 
180  def draw(self):
181  if self.active == False: return
182  self.delete()
183 
184  x_start = int(self.x0 % self.pitch)
185  x_num = int((self.width - x_start) / self.pitch) + 1
186  for x in range(x_num):
187  x0 = x_start + self.pitch * x
188  id = self.canvas.create_line(x0, 0, x0, self.height,
189  fill=self.color, width=self.linewd)
190  self.idx.append(id)
191 
192  y_start = int(self.y0 % self.pitch)
193  y_num = int((self.height - y_start) / self.pitch) + 1
194  for y in range(y_num):
195  y0 = y_start + self.pitch * y
196  id = self.canvas.create_line(0, y0, self.width, y0,
197  fill=self.color, width=self.linewd)
198  self.idy.append(id)
199 
200  for i in self.idx:
201  self.canvas.tag_lower(i)
202  for i in self.idy:
203  self.canvas.tag_lower(i)
204 
205  return
206 
207  def delete(self):
208  for i in self.idx:
209  self.canvas.delete(i)
210  for i in self.idy:
211  self.canvas.delete(i)
212  return
213 
214  def set_pitch(self, pitch):
215  if pitch != 0:
216  self.pitch = pitch
217 
218  self.draw()
219  return
220 
221 
223  def __init__(self, canvas, width, height, color="#ffffff", linewd=1):
224  ToggleItem.__init__(self)
225  self.x0 = width/2
226  self.y0 = height/2
227  self.width = width
228  self.height = height
229  self.color = color
230  self.linewd = linewd
231  self.canvas = canvas
232  self.id = [None] * 4
233  self.draw()
234  return
235 
236  def draw(self):
237  if self.active == False: return
238  self.delete()
239  self.id[0] = self.canvas.create_line(0, self.height/2,
240  self.width, self.height/2,
241  fill = self.color,
242  width = self.linewd)
243  self.id[1] = self.canvas.create_text(self.width - 10,
244  self.height/2 + 10,
245  text="x",
246  fill = self.color,
247  font="courier 12")
248  self.id[2] = self.canvas.create_line(self.width/2, 0,
249  self.width/2, self.height,
250  fill = self.color,
251  width = self.linewd)
252  self.id[3] = self.canvas.create_text(self.width/2 + 10,
253  + 10, text="y",
254  fill = self.color,
255  font="courier 12")
256 
257  return
258 
259  def delete(self):
260  for i in self.id:
261  self.canvas.delete(i)
262  return
263 
264 
266  def __init__(self, simulator):
267  self.simulator = simulator
268  self.tick = simulator.get_tick()
269  self.canvas = simulator.get_canvas()
270  self.trans = simulator.get_translation()
271  return
272 
273  def translate(self, x, y, dx, dy, dth):
274  return self.trans(x, y, dx, dy, dth)
275 
276  def get_tick(self):
277  return self.simulator.get_tick()
278 
279 
280 #------------------------------------------------------------
281 # LRFrange range data drawing
282 #
283 #------------------------------------------------------------
285  def __init__(self, simulator,
286  line_color="#ff0000", fill_color="#ff0000", linewd=1):
287  ScaledObject.__init__(self, simulator)
288  self.fill_color = fill_color
289  self.line_color = line_color
290  self.default_fill_color = fill_color
291  self.default_line_color = line_color
292  self.linewd = linewd
293  self.rdata = []
294  self.pre_data = []
295  self.poly_id = None
296  self.source = None
297 
298  # URG parameter
299  self.beg_angle = -45
300  self.end_angle = 225
301  self.angle_per_step = 360.0 / 1024.0
302  self.valid_beg_angle = 44 * 360.0 / 1024.0
304  self.offset_step = 0
305 
306  self.threshold = 0.0
307  self.sfilter = 0.0
308  self.tfilter = 0.0
309 
310  self.threshold_check = BooleanVar()
311  self.threshold_check.set(True)
312  self.tfilter_check = BooleanVar()
313  self.tfilter_check.set(True)
314  self.sfilter_check = BooleanVar()
315  self.sfilter_check.set(True)
316 
317  self.threshold_var = DoubleVar()
318  self.threshold_var.set(self.threshold)
319  self.tfilter_var = DoubleVar()
320  self.tfilter_var.set(self.tfilter)
321  self.sfilter_var = DoubleVar()
322  self.sfilter_var.set(self.sfilter)
323 
324  self.update()
325  return
326 
327  def create_ctrl(self, frame):
328  self.lrf_fill_check = StringVar()
329  self.lrf_fill_check.set("on")
330  self.lrf_line_check = StringVar()
331  self.lrf_line_check.set("on")
332 
333  text = Label(frame, text="LRF range area", anchor=W, justify=LEFT)
334  # "Line" check box
335  line = Checkbutton(frame, text="Line",
336  onvalue="on", offvalue="off",
337  justify=LEFT, anchor=W,
338  variable=self.lrf_line_check,
339  command=self.line_toggle)
340  # "Fill" check box
341  fill = Checkbutton(frame, text="Fill",
342  onvalue="on", offvalue="off",
343  justify=LEFT, anchor=W,
344  variable=self.lrf_fill_check,
345  command=self.fill_toggle)
346  # Threshold (check box/scale)
347  thresh = Checkbutton(frame, text="Threshold",
348  onvalue=True, offvalue=False,
349  justify=LEFT, anchor=W,
350  variable=self.threshold_check)
351  thresh_scale = Scale(frame, from_=0, to=100, resolution=0.1,
352  label="Threshold", command=self.on_threshold,
353  variable=self.threshold_var, orient=HORIZONTAL)
354  # Time-Filter (check box/scale)
355  tfilter = Checkbutton(frame, text="Filter(Time)",
356  onvalue=True, offvalue=False,
357  justify=LEFT, anchor=W,
358  variable=self.tfilter_check)
359  tfilter_scale = Scale(frame, from_=0, to=1, resolution=0.01,
360  label="Filter", command=self.on_tfilter,
361  variable=self.tfilter_var, orient=HORIZONTAL)
362  # Spacial-Filter (check box/scale)
363  sfilter = Checkbutton(frame, text="Filter(Spacial)",
364  onvalue=True, offvalue=False,
365  justify=LEFT, anchor=W,
366  variable=self.sfilter_check)
367  sfilter_scale = Scale(frame, from_=0, to=1, resolution=0.01,
368  label="Filter", command=self.on_sfilter,
369  variable=self.sfilter_var, orient=HORIZONTAL)
370 
371  for w in [text, line, fill, thresh, thresh_scale,
372  tfilter, tfilter_scale, sfilter, sfilter_scale]:
373  w.pack(side=TOP, anchor=W, fill=X)
374  return
375 
376  def on_threshold(self, var):
377  self.threshold = self.threshold_var.get()
378  return
379 
380  def on_sfilter(self, var):
381  self.sfilter = self.sfilter_var.get()
382  return
383 
384  def on_tfilter(self, var):
385  self.tfilter = self.tfilter_var.get()
386  return
387 
388  def line_toggle(self):
389  if self.lrf_line_check.get() == "on":
390  self.line_color = self.default_line_color
391  else:
392  self.line_color = ""
393  return
394 
395  def fill_toggle(self):
396  if self.lrf_fill_check.get() == "on":
397  self.fill_color = self.default_fill_color
398  else:
399  self.fill_color = ""
400  return
401 
402  def set_data_source(self, source):
403  self.source = source
404  return
405 
406  def set_value(self, data):
407  self.rdata = data
408  return
409 
410  def draw(self):
411  self.delete()
412  rpos = []
413  rpos.append(self.translate(0, 0, 0, 0, 0))
414  rpos.append(self.range_to_pos(self.rdata))
415  self.poly_id = self.canvas.create_polygon(rpos,
416  width = self.linewd,
417  outline = self.line_color,
418  fill = self.fill_color,
419  smooth = 1,
420  splinesteps = 5)
421  return
422 
423  def range_to_pos(self, data):
424  pos = []
425  pre_d = 0
426 
427  tfilter = self.tfilter_check.get()
428  sfilter = self.sfilter_check.get()
429  thresh = self.threshold_check.get()
430 
431  # Time-Filter
432  if tfilter and len(data) == len(self.pre_data):
433  for (n, d) in enumerate(data):
434  k_t = self.tfilter
435  data[n] = self.pre_data[n] * k_t + d * (1 - k_t)
436 
437  # Spacial Filter
438  for (n, d) in enumerate(data):
439  # Threshold
440  if thresh and d < self.threshold:
441  d = 10000 #pre_d
442 
443  if sfilter:
444  k_s = self.sfilter
445  d = pre_d * k_s + d * (1 - k_s)
446  pre_d = d
447 
448  # n: step number
449  # d: length data
450  #deg = (n + self.offset_step) * self.angle_per_step + self.beg_angle
451  #th = deg * math.pi / 180
452  th = (n + self.offset_step) * self.angle_per_step + self.beg_angle
453  x = d * math.cos(th)
454  y = d * math.sin(th)
455  pos.append(self.translate(x, y, 0, 0, 0))
456  self.pre_data = data
457  return pos
458 
459  def delete(self):
460  if self.poly_id != None:
461  self.canvas.delete(self.poly_id)
462  return
463 
464  def update(self):
465  if self.source != None:
466  rdata = self.source.get_range_data()
467  if len(rdata) != 0:
468  self.rdata = rdata
469 
470  res = self.source.get_angular_res()
471  if res:
472  self.angle_per_step = res
473 
474  beg_angle = self.source.get_start_point()
475  if beg_angle:
476  self.beg_angle = beg_angle
477 
478  end_angle = self.source.get_end_point()
479  if end_angle:
480  self.end_angle = end_angle
481 
482  else:
483  pass
484  self.draw()
485 
486 
487 
488 #------------------------------------------------------------
489 # TkLRFViewer main windows class
490 #
491 #------------------------------------------------------------
492 class TkLRFViewer(Frame):
493  def __init__(self, master=None, width=480, height=480):
494  Frame.__init__(self, master)
495 
496  # canvas properties
497  self.width = width
498  self.height = height
499  # zero of canvas
500  self.x0 = width/2
501  self.y0 = height/2
502 
503  self.wd = 150
504 
505  self.robots = {}
506 
507  self.robot = None
508  self.postext = None
509 
510  self.scale = 1.0
511  self.scale_var = DoubleVar()
512  self.scale_var.set(self.scale)
513 
514  self.grid_pitch = 50
515 
516  self.tick = 0.1
517  self.default_tick = 0.1
518  self.tickscale_var = DoubleVar()
519  self.tickscale_var.set(self.tick)
520 
521  self.axis_check = StringVar()
522  self.axis_check.set("on")
523  self.grid_check = StringVar()
524  self.grid_check.set("on")
525  self.rnames = {}
526 
527 
528  self.init()
529  self.pack()
530 
531 
532  self.after(20, self.on_update)
533  return
534 
535  def init(self):
536  self.canvas = Canvas(self, bg="#000000",
537  width = self.width, height = self.height)
538  self.canvas.pack(side=LEFT)
539 
540  self.can_grid = CanvasGrid(self.canvas, self.x0, self.y0,
541  self.width, self.height, self.grid_pitch,
542  "#aaaaaa", 1)
543  self.can_axis = CanvasAxis(self.canvas, self.width, self.height,
544  "#ffffff", 1)
545 
546  self.frame = Frame(self)
547  self.frame.pack(side=LEFT)
548 
549  # Screen control
550  self.scrctrl_frame = Frame(self.frame, width=self.wd, height=300,
551  relief=GROOVE, bd=2)
552  self.scrctrl_frame.pack(side=TOP, fill=X)
553  self.create_scale(self.scrctrl_frame)
555 
556 
557  self.lrfctrl_frame = Frame(self.frame, width=self.wd, height=300,
558  relief=GROOVE, bd=2)
559  self.lrfctrl_frame.pack(side=TOP, fill=X)
560  self.lrf = LRFrange(self)
561  self.lrf.create_ctrl(self.lrfctrl_frame)
562 
563  return
564 
565 
566 
567  def on_update(self):
568  self.lrf.update()
569  self.after(20, self.on_update)
570  return
571 
572  def get_tick(self):
573  return self.tick
574 
575  def get_canvas(self):
576  return self.canvas
577 
578  def get_translation(self):
579  return self.real_to_canvas
580 
581 
582  #------------------------------------------------------------
583  # Scale control set
584  def create_scale(self, frame):
585  dummy = Frame(frame, width=self.wd)
586  dummy.pack(side=TOP)
587  sl = Scale(frame, from_=0, to=10, resolution=0.01,
588  label="Scale Factor", command=self.on_scale,
589  variable=self.scale_var, orient=HORIZONTAL)
590  bt = Button(frame, text="Reset Scale", command=self.reset_scale)
591  sl.pack(side=TOP, fill=X)
592  bt.pack(side=TOP, fill=X)
593  return
594 
595  def on_scale(self, val):
596  v = float(val)
597  if v == 0.0:
598  pitch = 0
599  else:
600  pitch = self.grid_pitch/v
601  self.scale = v
602  self.can_grid.set_pitch(pitch)
603  return
604 
605  def reset_scale(self):
606  self.scale_var.set(1.)
607  pitch = self.grid_pitch/1.0
608  self.scale = 1.0
609  self.can_grid.set_pitch(pitch)
610  return
611 
612  def on_tickchange(self, val):
613  v = self.tickscale_var.get()
614  if v == 0.0:
615  self.tick = 0
616  else:
617  self.tick = v
618  return
619 
620  def reset_tickscale(self):
621  self.tick = self.default_tick
622  self.tickscale_var.set(self.default_tick)
623 
624  # end of Scale widget set
625  #------------------------------------------------------------
626 
627  #------------------------------------------------------------
628  # Canvas control set
629  def create_checkbutton(self, frame):
630  axis = Checkbutton(frame, text="Axis",
631  onvalue="on", offvalue="off",
632  justify=LEFT, anchor=W,
633  variable=self.axis_check,
634  command=self.can_axis.toggle)
635  grid = Checkbutton(frame, text="Grid",
636  onvalue="on", offvalue="off",
637  justify=LEFT, anchor=W,
638  variable=self.grid_check,
639  command=self.can_grid.toggle)
640  for w in [axis, grid]:
641  w.pack(side=TOP, anchor=W, fill=X)
642 
643  def on_rname_toggle(self):
644  for r in self.rnames.keys():
645  self.rnames[r].toggle()
646  return
647 
648  # end of Canvas control set
649  #------------------------------------------------------------
650 
651  #------------------------------------------------------------
652  #
653  def real_to_canvas(self, x, y, dx, dy, dt):
654  # Simulator coordinate system -> display coordinate system
655  # x, y: original position
656  # dx, dy, dt: translation and rotation vector
657  # translation and rotation
658  x_tmp = (math.cos(dt) * x - math.sin(dt) * y + dx)/self.scale
659  y_tmp = (math.sin(dt) * x + math.cos(dt) * y + dy)/self.scale
660  # align to canvas coordinate system (origin is center and y+ is upward)
661  xo = x_tmp + self.x0
662  yo = -y_tmp + self.y0
663  return xo, yo
664 
665 import threading
666 
667 class test_data_creator(threading.Thread):
668  def __init__(self, lrf, step = 681):
669  threading.Thread.__init__(self)
670  import time
671  self.lrf = lrf
672  self.step = step
673  self.flag = True
674  return
675 
676  def stop(self):
677  self.flag = False
678  return
679 
680  def run(self):
681  import random
682  data = [0] * 681
683  pre = 0
684  while self.flag:
685  for i in range(681):
686  if i % 5 == 0:
687  data[i] = pre * 0.9 + random.randint(0, 255) * 0.1
688  pre = data[i]
689  else:
690  data[i] = pre
691  pre = data[i]
692  self.lrf.set_value(data)
693  time.sleep(0.1)
694 
695  return
696 
697 def main():
698  m = TkLRFViewer(Tk())
699  m.master.title("Laser Range Finder Viewer")
700 
701  mgr = OpenRTM_aist.Manager.init(sys.argv)
702  mgr.activateManager()
703  profile = OpenRTM_aist.Properties(defaults_str=lrfviewer_spec)
704  mgr.registerFactory(profile, LRFViewer, OpenRTM_aist.Delete)
705  mgr.runManager(True)
706  lrf_rtc = mgr.createComponent("LRFViewer")
707  m.lrf.set_data_source(lrf_rtc)
708  m.mainloop()
709  mgr.shutdown()
710 
711 
712 if __name__ == '__main__': main()
The Properties class represents a persistent set of properties.
Definition: Properties.py:83
def __init__(self, simulator, line_color="#ff0000", fill_color="#ff0000", linewd=1)
Definition: TkLRFViewer.py:286
def __init__(self, canvas, width, height, color="#ffffff", linewd=1)
Definition: TkLRFViewer.py:223
def addInPort(self, name, inport)
Definition: RTObject.py:2721
def __init__(self, master=None, width=480, height=480)
Definition: TkLRFViewer.py:493
InPort template class.
Definition: InPort.py:58
def __init__(self, canvas, x0, y0, width, height, pitch, color, linewd)
Definition: TkLRFViewer.py:164


openrtm_aist_python
Author(s): Shinji Kurihara
autogenerated on Thu Jun 6 2019 19:11:35