WUT Velma robot API
velma_workspace.py
Go to the documentation of this file.
1 
4 
5 # Copyright (c) 2021, Robot Control and Pattern Recognition Group,
6 # Institute of Control and Computation Engineering
7 # Warsaw University of Technology
8 #
9 # All rights reserved.
10 #
11 # Redistribution and use in source and binary forms, with or without
12 # modification, are permitted provided that the following conditions are met:
13 # * Redistributions of source code must retain the above copyright
14 # notice, this list of conditions and the following disclaimer.
15 # * Redistributions in binary form must reproduce the above copyright
16 # notice, this list of conditions and the following disclaimer in the
17 # documentation and/or other materials provided with the distribution.
18 # * Neither the name of the Warsaw University of Technology nor the
19 # names of its contributors may be used to endorse or promote products
20 # derived from this software without specific prior written permission.
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 # DISCLAIMED. IN NO EVENT SHALL <COPYright HOLDER> BE LIABLE FOR ANY
26 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #
33 # Author: Dawid Seredynski
34 #
35 
36 import rospkg
37 import math
38 import numpy as np
39 import random
40 from velma_kinematics.velma_ik_geom import KinematicsSolverLWR4, KinematicsSolverVelma
41 
43  def __init__(self):
44  self.__cell_size = None
45  self.__x_min = None
46  self.__x_max = None
47  self.__y_min = None
48  self.__y_max = None
49  self.__z_min = None
50  self.__z_max = None
51  self.__x_cells = None
52  self.__y_cells = None
53  self.__z_cells = None
54  self.__ws_matrix = None
55 
56  def __getCellIdx(self, v, v_min, cells):
57  idx = int(math.floor((v-v_min)/self.__cell_size))
58  if idx < 0 or idx >= cells:
59  return None
60  # else:
61  return idx
62 
63  def getCellIdxX(self, v):
64  return self.__getCellIdx(v, self.__x_min, self.__x_cells)
65 
66  def getCellIdxY(self, v):
67  return self.__getCellIdx(v, self.__y_min, self.__y_cells)
68 
69  def getCellIdxZ(self, v):
70  return self.__getCellIdx(v, self.__z_min, self.__z_cells)
71 
72  def getCellIdx(self, pt):
73  ix = self.getCellIdxX(pt.x())
74  iy = self.getCellIdxY(pt.y())
75  iz = self.getCellIdxZ(pt.z())
76  if ix is None or iy is None or iz is None:
77  return None
78  # else:
79  return (ix, iy, iz)
80 
81  def __getCellCenter(self, idx, v_min, cells):
82  if idx is None or idx < 0 or idx >= cells:
83  return None
84  return v_min + (idx+0.5)*self.__cell_size
85 
86  def getCellCenterX(self, idx):
87  return self.__getCellCenter(idx, self.__x_min, self.__x_cells)
88 
89  def getCellCenterY(self, idx):
90  return self.__getCellCenter(idx, self.__y_min, self.__y_cells)
91 
92  def getCellCenterZ(self, idx):
93  return self.__getCellCenter(idx, self.__z_min, self.__z_cells)
94 
95  @staticmethod
96  def generate():
97  result = LWRWorkspace()
98 
99  # Parameters
100  samples_count = 2000000
101  lim_dist = 0.2
102  result.__cell_size = 0.08
103 
104  solv = KinematicsSolverLWR4()
105 
106  q_lim = [ [-2.96, 2.96],
107  [-2.09, -0.2, 0.2, 2.09],
108  [-2.96, 2.96],
109  [-2.095, -0.2, 0.2, 2.095],
110  [-2.96, 2.96],
111  [-2.09, -0.2, 0.2, 2.09],
112  [-2.96, 2.96] ]
113 
114  pt_list = []
115  x_min = 1000
116  x_max = -1000
117  y_min = 1000
118  y_max = -1000
119  z_min = 1000
120  z_max = -1000
121  for idx in range(samples_count):
122  q = []
123  for q_idx in range(7):
124  q.append( random.uniform(q_lim[q_idx][0]+lim_dist, q_lim[q_idx][-1]-lim_dist) )
125  T_AB_E = solv.calculateFk( q )
126  pt_list.append(T_AB_E.p)
127  x_min = min(x_min, T_AB_E.p.x())
128  x_max = max(x_max, T_AB_E.p.x())
129  y_min = min(y_min, T_AB_E.p.y())
130  y_max = max(y_max, T_AB_E.p.y())
131  z_min = min(z_min, T_AB_E.p.z())
132  z_max = max(z_max, T_AB_E.p.z())
133  if idx%1000 == 0:
134  print('generated samples: {} / {}'.format(idx, samples_count))
135 
136  result.__x_min = x_min
137  result.__x_max = x_max
138  result.__y_min = y_min
139  result.__y_max = y_max
140  result.__z_min = z_min
141  result.__z_max = z_max
142 
143  result.__x_cells = int(math.ceil((result.__x_max - result.__x_min) / result.__cell_size))
144  result.__y_cells = int(math.ceil((result.__y_max - result.__y_min) / result.__cell_size))
145  result.__z_cells = int(math.ceil((result.__z_max - result.__z_min) / result.__cell_size))
146 
147  print('ranges: ({}, {}), ({}, {}), ({}, {})'.format(result.__x_min, result.__x_max,
148  result.__y_min, result.__y_max, result.__z_min, result.__z_max))
149  print('cells: {}, {}, {}, total: {}'.format(result.__x_cells, result.__y_cells,
150  result.__z_cells, result.__x_cells*result.__y_cells*result.__z_cells))
151  result.__ws_matrix = np.zeros( (result.__x_cells, result.__y_cells, result.__z_cells) )
152 
153  for pt in pt_list:
154  x_idx = result.getCellIdxX(pt.x())
155  y_idx = result.getCellIdxY(pt.y())
156  z_idx = result.getCellIdxZ(pt.z())
157  if x_idx is None or y_idx is None or z_idx is None:
158  print('could not calculate cell idx: {}'.format((x_idx, y_idx, z_idx)))
159  result.__ws_matrix[x_idx, y_idx, z_idx] += 1
160 
161  max_hits = np.max(result.__ws_matrix)
162  print('max hits: {}'.format(max_hits))
163  result.__ws_matrix = result.__ws_matrix / max_hits
164 
165  return result
166 
167  def save(self, parameters_filename, matrix_filename):
168  np.save(matrix_filename, self.__ws_matrix)
169  ws_params = np.array( [self.__x_min, self.__x_max, self.__y_min, self.__y_max,
170  self.__z_min, self.__z_max, self.__cell_size] )
171  np.save(parameters_filename, ws_params)
172 
173  @staticmethod
174  def load(parameters_filename=None, matrix_filename=None):
175  if parameters_filename is None or matrix_filename is None:
176  rospack = rospkg.RosPack()
177  ws_data_path = rospack.get_path('velma_kinematics') + '/data/workspace/'
178  parameters_filename = ws_data_path + 'lwr_ws_param.npy'
179  matrix_filename = ws_data_path + 'lwr_ws.npy'
180 
181  result = LWRWorkspace()
182  ws_params = np.load(parameters_filename)
183  result.__ws_matrix = np.load(matrix_filename)
184  result.__x_min, result.__x_max, result.__y_min, result.__y_max,\
185  result.__z_min, result.__z_max, result.__cell_size = ws_params.tolist()
186  result.__x_cells = int(math.ceil((result.__x_max - result.__x_min) / result.__cell_size))
187  result.__y_cells = int(math.ceil((result.__y_max - result.__y_min) / result.__cell_size))
188  result.__z_cells = int(math.ceil((result.__z_max - result.__z_min) / result.__cell_size))
189 
190  return result
191 
192  def getCellsX(self):
193  return self.__x_cells
194 
195  def getCellsY(self):
196  return self.__y_cells
197 
198  def getCellsZ(self):
199  return self.__z_cells
200 
201  def getCellValue(self, ix, iy=None, iz=None):
202  try:
203  ix, iy, iz = ix
204  assert iy is None
205  assert iz is None
206  except:
207  pass
208  if ix is None or ix < 0 or ix >= self.__x_cells:
209  return 0.0
210  if iy is None or iy < 0 or iy >= self.__y_cells:
211  return 0.0
212  if iz is None or iz < 0 or iz >= self.__z_cells:
213  return 0.0
214  return self.__ws_matrix[ix,iy,iz]
215 
216  def getCellSize(self):
217  return self.__cell_size
218 
220  def __init__(self):
221  self.__cell_size = None
222  self.__x_min = None
223  self.__x_max = None
224  self.__y_min = None
225  self.__y_max = None
226  self.__z_min = None
227  self.__z_max = None
228  self.__x_cells = None
229  self.__y_cells = None
230  self.__z_cells = None
231  self.__ws_matrix = None
232 
233  def __getCellIdx(self, v, v_min, cells):
234  idx = int(math.floor((v-v_min)/self.__cell_size))
235  if idx < 0 or idx >= cells:
236  return None
237  # else:
238  return idx
239 
240  def getCellIdxX(self, v):
241  return self.__getCellIdx(v, self.__x_min, self.__x_cells)
242 
243  def getCellIdxY(self, v):
244  return self.__getCellIdx(v, self.__y_min, self.__y_cells)
245 
246  def getCellIdxZ(self, v):
247  return self.__getCellIdx(v, self.__z_min, self.__z_cells)
248 
249  def getCellIdx(self, pt):
250  ix = self.getCellIdxX(pt.x())
251  iy = self.getCellIdxY(pt.y())
252  iz = self.getCellIdxZ(pt.z())
253  if ix is None or iy is None or iz is None:
254  return None
255  # else:
256  return (ix, iy, iz)
257 
258  def __getCellCenter(self, idx, v_min, cells):
259  if idx is None or idx < 0 or idx >= cells:
260  return None
261  return v_min + (idx+0.5)*self.__cell_size
262 
263  def getCellCenterX(self, idx):
264  return self.__getCellCenter(idx, self.__x_min, self.__x_cells)
265 
266  def getCellCenterY(self, idx):
267  return self.__getCellCenter(idx, self.__y_min, self.__y_cells)
268 
269  def getCellCenterZ(self, idx):
270  return self.__getCellCenter(idx, self.__z_min, self.__z_cells)
271 
272  @staticmethod
273  def generate():
274  result = VelmaWorkspace()
275 
276  # Parameters
277  samples_count = 20000000
278  lim_dist = 0.2
279  result.__cell_size = 0.1
280 
281  solv = KinematicsSolverVelma()
282 
283  q_lim = [ [-2.96, 2.96],
284  [-2.09, -0.2, 0.2, 2.09],
285  [-2.96, 2.96],
286  [-2.095, -0.2, 0.2, 2.095],
287  [-2.96, 2.96],
288  [-2.09, -0.2, 0.2, 2.09],
289  [-2.96, 2.96] ]
290 
291  pt_list = []
292  x_min = 1000
293  x_max = -1000
294  y_min = 1000
295  y_max = -1000
296  z_min = 1000
297  z_max = -1000
298  for idx in range(samples_count):
299  q = []
300  for q_idx in range(7):
301  q.append( random.uniform(q_lim[q_idx][0]+lim_dist, q_lim[q_idx][-1]-lim_dist) )
302  torso_angle = random.uniform( -1.56, 1.56)
303  T_B_E = solv.getArmFk( 'right', torso_angle, q )
304  pt_list.append(T_B_E.p)
305  x_min = min(x_min, T_B_E.p.x())
306  x_max = max(x_max, T_B_E.p.x())
307  y_min = min(y_min, T_B_E.p.y())
308  y_max = max(y_max, T_B_E.p.y())
309  z_min = min(z_min, T_B_E.p.z())
310  z_max = max(z_max, T_B_E.p.z())
311  if idx%1000 == 0:
312  print('generated samples: {} / {}'.format(idx, samples_count))
313 
314  result.__x_min = x_min
315  result.__x_max = x_max
316  result.__y_min = y_min
317  result.__y_max = y_max
318  result.__z_min = z_min
319  result.__z_max = z_max
320 
321  result.__x_cells = int(math.ceil((result.__x_max - result.__x_min) / result.__cell_size))
322  result.__y_cells = int(math.ceil((result.__y_max - result.__y_min) / result.__cell_size))
323  result.__z_cells = int(math.ceil((result.__z_max - result.__z_min) / result.__cell_size))
324 
325  print('ranges: ({}, {}), ({}, {}), ({}, {})'.format(result.__x_min, result.__x_max,
326  result.__y_min, result.__y_max, result.__z_min, result.__z_max))
327  print('cells: {}, {}, {}, total: {}'.format(result.__x_cells, result.__y_cells,
328  result.__z_cells, result.__x_cells*result.__y_cells*result.__z_cells))
329  result.__ws_matrix = np.zeros( (result.__x_cells, result.__y_cells, result.__z_cells) )
330 
331  for pt in pt_list:
332  x_idx = result.getCellIdxX(pt.x())
333  y_idx = result.getCellIdxY(pt.y())
334  z_idx = result.getCellIdxZ(pt.z())
335  if x_idx is None or y_idx is None or z_idx is None:
336  print('could not calculate cell idx: {}'.format((x_idx, y_idx, z_idx)))
337  result.__ws_matrix[x_idx, y_idx, z_idx] += 1
338 
339  max_hits = np.max(result.__ws_matrix)
340  print('max hits: {}'.format(max_hits))
341  result.__ws_matrix = result.__ws_matrix / max_hits
342 
343  return result
344 
345  def save(self, parameters_filename, matrix_filename):
346  np.save(matrix_filename, self.__ws_matrix)
347  ws_params = np.array( [self.__x_min, self.__x_max, self.__y_min, self.__y_max,
348  self.__z_min, self.__z_max, self.__cell_size] )
349  np.save(parameters_filename, ws_params)
350 
351  @staticmethod
352  def load(parameters_filename=None, matrix_filename=None):
353  if parameters_filename is None or matrix_filename is None:
354  rospack = rospkg.RosPack()
355  ws_data_path = rospack.get_path('velma_kinematics') + '/data/workspace/'
356  parameters_filename = ws_data_path + 'velma_ws_param.npy'
357  matrix_filename = ws_data_path + 'velma_ws.npy'
358 
359  result = VelmaWorkspace()
360  ws_params = np.load(parameters_filename)
361  result.__ws_matrix = np.load(matrix_filename)
362  result.__x_min, result.__x_max, result.__y_min, result.__y_max,\
363  result.__z_min, result.__z_max, result.__cell_size = ws_params.tolist()
364  result.__x_cells = int(math.ceil((result.__x_max - result.__x_min) / result.__cell_size))
365  result.__y_cells = int(math.ceil((result.__y_max - result.__y_min) / result.__cell_size))
366  result.__z_cells = int(math.ceil((result.__z_max - result.__z_min) / result.__cell_size))
367 
368  return result
369 
370  def getCellsX(self):
371  return self.__x_cells
372 
373  def getCellsY(self):
374  return self.__y_cells
375 
376  def getCellsZ(self):
377  return self.__z_cells
378 
379  def __interpretCellIdx(self, ix, iy, iz):
380  try:
381  ix, iy, iz = ix
382  assert iy is None
383  assert iz is None
384  except:
385  pass
386  if ix is None or ix < 0 or ix >= self.__x_cells:
387  return None, None, None
388  if iy is None or iy < 0 or iy >= self.__y_cells:
389  return None, None, None
390  if iz is None or iz < 0 or iz >= self.__z_cells:
391  return None, None, None
392  return ix, iy, iz
393 
394  def getCellValueRight(self, ix, iy=None, iz=None):
395  ix, iy, iz = self.__interpretCellIdx(ix, iy, iz)
396  if ix is None:
397  return 0.0
398  # else:
399  return self.__ws_matrix[ix,iy,iz]
400 
401  def getCellValueLeft(self, ix, iy=None, iz=None):
402  ix, iy, iz = self.__interpretCellIdx(ix, iy, iz)
403  if ix is None:
404  return 0.0
405  # else:
406  return self.__ws_matrix[ix,self.__y_cells-1-iy,iz]
407 
408  def getCellValue(self, ix, iy=None, iz=None):
409  ix, iy, iz = self.__interpretCellIdx(ix, iy, iz)
410  if ix is None:
411  return 0.0
412  # else:
413  return (self.__ws_matrix[ix,iy,iz] + self.__ws_matrix[ix,self.__y_cells-1-iy,iz]) / 2.0
414 
415  def getCellValueSide(self, side_str, ix, iy=None, iz=None):
416  if side_str == 'left':
417  return self.getCellValueLeft(ix, iy, iz)
418  elif side_str == 'right':
419  return self.getCellValueRight(ix, iy, iz)
420  elif side_str == 'any' or side_str == 'both':
421  return self.getCellValue(ix, iy, iz)
422  # else:
423  raise Exception('Wrong value for "side": "{}"'.format(side_str))
424 
425  def getCellSize(self):
426  return self.__cell_size
def __getCellCenter(self, idx, v_min, cells)
def getCellValue(self, ix, iy=None, iz=None)
def save(self, parameters_filename, matrix_filename)
def getCellValue(self, ix, iy=None, iz=None)
def load(parameters_filename=None, matrix_filename=None)
def getCellValueRight(self, ix, iy=None, iz=None)
Kinematics solver (FK, IK) for WUT Velma robot.
Kinematics solver (FK, IK) for Kuka LWR 4+.
def load(parameters_filename=None, matrix_filename=None)
def save(self, parameters_filename, matrix_filename)
def getCellValueLeft(self, ix, iy=None, iz=None)
def getCellValueSide(self, side_str, ix, iy=None, iz=None)