HIWIN_HRSS.py
Go to the documentation of this file.
1 # Copyright 2017 - RoboDK Software S.L. - http://www.robodk.com/
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
6 # Unless required by applicable law or agreed to in writing, software
7 # distributed under the License is distributed on an "AS IS" BASIS,
8 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 # See the License for the specific language governing permissions and
10 # limitations under the License.
11 
12 # ----------------------------------------------------
13 # This file is a POST PROCESSOR for Robot Offline Programming to generate programs
14 # for a HIWIN robot (HRSS: HIWIN Robot System Software)
15 #
16 # To edit/test this POST PROCESSOR script file:
17 # Select "Program"->"Add/Edit Post Processor", then select your post or create a new one.
18 # You can edit this file using any text editor or Python editor. Using a Python editor allows to quickly evaluate a sample program at the end of this file.
19 # Python should be automatically installed with RoboDK
20 #
21 # You can also edit the POST PROCESSOR manually:
22 # 1- Open the *.py file with Python IDLE (right click -> Edit with IDLE)
23 # 2- Make the necessary changes
24 # 3- Run the file to open Python Shell: Run -> Run module (F5 by default)
25 # 4- The "test_post()" function is called automatically
26 # Alternatively, you can edit this file using a text editor and run it with Python
27 #
28 # To use a POST PROCESSOR file you must place the *.py file in "C:/RoboDK/Posts/"
29 # To select one POST PROCESSOR for your robot in RoboDK you must follow these steps:
30 # 1- Open the robot panel (double click a robot)
31 # 2- Select "Parameters"
32 # 3- Select "Unlock advanced options"
33 # 4- Select your post as the file name in the "Robot brand" box
34 #
35 # To delete an existing POST PROCESSOR script, simply delete this file (.py file)
36 #
37 # ----------------------------------------------------
38 # More information about RoboDK Post Processors and Offline Programming here:
39 # http://www.robodk.com/help#PostProcessor
40 # http://www.robodk.com/doc/en/PythonAPI/postprocessor.html
41 # ----------------------------------------------------
42 
43 
44 # ----------------------------------------------------
45 # Import RoboDK tools
46 from robodk import *
47 
48 
49 HEADER = ''';[Point&S]
50 DECL E6POINT P0={A1 0.0, A2 0.0, A3 0.0, A4 0.0, A5 -90.0, A6 0.0}
51 ;NULL
52 ;[Point&E]
53 ;[Program&SV2]
54 
55 ;PTP P0 CONT Vel=100% Acc=50% TOOL[0] BASE[0]
56 '''
57 
58 # ----------------------------------------------------
59 def pose_2_str(pose):
60  """Converts a pose target to a string"""
61  #[x,y,z,w,p,r] = Pose_2_KUKA(pose)
62  #return ('X %.3f, Y %.3f, Z %.3f, A %.3f, B %.3f, C %.3f' % (x,y,z,r,p,w)) # old version had to be switched
63  [x,y,z,r,p,w] = pose_2_xyzrpw(pose)
64  return ('X %.3f,Y %.3f,Z %.3f,A %.3f,B %.3f,C %.3f' % (x,y,z,w,p,r))
65 
66 def pose_2_str_ext(pose,joints):
67  njoints = len(joints)
68  if njoints <= 6:
69  return pose_2_str(pose)
70  else:
71  extaxes = ''
72  for i in range(njoints-6):
73  extaxes = extaxes + (',E%i %.5f' % (i+1, joints[i+6]))
74  return pose_2_str(pose) + extaxes
75 
76 def angles_2_str(angles):
77  """Prints a joint target"""
78  str = ''
79  data = ['A1','A2','A3','A4','A5','A6','E1','E2','E3','E4','E5','E6']
80  for i in range(len(angles)):
81  str = str + ('%s %.5f,' % (data[i], angles[i]))
82  str = str[:-1]
83  return str
84 
85 def get_safe_name(varname):
86  """Get a safe program name"""
87  for c in r' -[]/\;,><&*:%=+@!#^|?^':
88  varname = varname.replace(c,'_')
89  if len(varname) <= 0:
90  varname = 'Program'
91  if varname[0].isdigit():
92  varname = 'P' + varname
93  return varname
94 
95 # ----------------------------------------------------
96 # Object class that handles the robot instructions/syntax
97 class RobotPost(object):
98  """Robot post object"""
99  PROG_EXT = 'hrb' # set the program extension
100  MAX_LINES_X_PROG = 5000 # maximum number of lines per program. It will then generate multiple "pages (files)"
101  INCLUDE_SUB_PROGRAMS = False
102 
103  # other variables
104  ROBOT_POST = ''
105  ROBOT_NAME = ''
106 
107  # Multiple program files variables
108  PROG_NAME = 'unknown' # single program name
109  PROG_NAMES = []
110  PROG_FILES = []
111  PROG_LIST = []
112  nLines = 0
113  nProgs = 0
114 
115  PROG = ''
116  LOG = ''
117  nAxes = 6
118  APO_VALUE = 1
119  C_DIS = ' CONT'#' C_DIS'
120  C_PTP = ' CONT'#' C_PTP'
121  SPEED_MMS = 1000
122  SPEED_PERCENT = 50;
123  ID_TOOL = 0
124  ID_BASE = 0
125 
126 
127 
128  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
129  self.ROBOT_POST = robotpost
130  self.ROBOT_NAME = robotname
131  self.PROG = ''
132  self.LOG = ''
133  self.nAxes = robot_axes
134  for k,v in kwargs.items():
135  if k == 'lines_x_prog':
137 
138  def ProgStart(self, progname, new_page = False):
139  progname_i = progname
140  if new_page:
141  nPages = len(self.PROG_LIST)
142  if nPages == 0:
143  progname_i = progname
144  else:
145  progname_i = "%s%i" % (self.PROG_NAME, nPages)
146 
147  else:
148  self.PROG_NAME = progname
149  self.nProgs = self.nProgs + 1
150  self.PROG_NAMES = []
151  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
152  return
153 
154  self.PROG_NAMES.append(progname_i)
155 
156  self.addline('; Program: %s' % progname_i)
157  if not new_page:
158  self.PROG = self.PROG + HEADER
159  #if self.nAxes > 6:
160  # self.addline('$ACT_EX_AX = %i' % (self.nAxes-6))
161 
162  def ProgFinish(self, progname, new_page = False):
163  if new_page:
164  self.PROG = self.PROG + "\n;[Program&E]\n"
165  self.PROG_LIST.append(self.PROG)
166  self.PROG = ''
167  self.nLines = 0
168  elif self.nProgs <= 1 or self.INCLUDE_SUB_PROGRAMS:
169  self.PROG = self.PROG + "\n;[Program&E]\n"
170 
171  def progsave(self, folder, progname, ask_user = False, show_result = False):
172  progname = progname + '.' + self.PROG_EXT
173  if ask_user or not DirExists(folder):
174  filesave = getSaveFile(folder, progname, 'Save program as...')
175  if filesave is not None:
176  filesave = filesave.name
177  else:
178  return
179  else:
180  filesave = folder + '/' + progname
181  fid = open(filesave, "w")
182  fid.write(self.PROG)
183  fid.close()
184  print('SAVED: %s\n' % filesave) # tell RoboDK the path of the saved file
185  self.PROG_FILES.append(filesave)
186 
187  # open file with default application
188  if show_result:
189  if type(show_result) is str:
190  # Open file with provided application
191  import subprocess
192  p = subprocess.Popen([show_result, filesave])
193  elif type(show_result) is list:
194  import subprocess
195  p = subprocess.Popen(show_result + [filesave])
196  else:
197  # open file with default application
198  import os
199 
200  os.startfile(filesave)
201  if len(self.LOG) > 0:
202  mbox('Program generation LOG:\n\n' + self.LOG)
203 
204  def ProgSave(self, folder, progname, ask_user = False, show_result = False):
205  if len(self.PROG_LIST) >= 1:
206  if self.nLines > 0:
207  self.PROG_LIST.append(self.PROG)
208  self.PROG = ''
209  self.nLines = 0
210 
211  npages = len(self.PROG_LIST)
212  progname_main = progname + "Main"
213  mainprog = "Program: %s\n" % progname_main
214  #mainprog += "EXT BAS (BAS_COMMAND :IN,REAL :IN )"
215  #for i in range(npages):
216  # self.PROG = self.PROG_LIST[i]
217  # mainprog += "EXT %s()\n" % self.PROG_NAMES[i]
218 
219  for i in range(npages):
220  self.PROG = self.PROG_LIST[i]
221  mainprog += "%s\n" % self.PROG_NAMES[i]
222 
223  self.PROG = mainprog
224  self.progsave(folder, progname_main, ask_user, show_result)
225  self.LOG = ''
226  if len(self.PROG_FILES) == 0:
227  # cancelled by user
228  return
229 
230  first_file = self.PROG_FILES[0]
231  folder_user = getFileDir(first_file)
232  # progname_user = getFileName(self.FILE_SAVED)
233 
234  for i in range(npages):
235  self.PROG = self.PROG_LIST[i]
236  self.progsave(folder_user, self.PROG_NAMES[i], False, show_result)
237 
238  else:
239  self.progsave(folder, progname, ask_user, show_result)
240 
241  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
242  """Send a program to the robot using the provided parameters. This method is executed right after ProgSave if we selected the option "Send Program to Robot".
243  The connection parameters must be provided in the robot connection menu of RoboDK"""
244  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
245 
246  def MoveJ(self, pose, joints, conf_RLF=None):
247  """Add a joint movement"""
248  self.addline('PTP {' + angles_2_str(joints) + '}' + self.C_PTP + ' Vel=%i%% TOOL[%i] BASE[%i]' % (self.SPEED_PERCENT,self.ID_TOOL,self.ID_BASE))
249  #PTP P1 CONT Vel=100% Acc=50% TOOL[0] BASE[0]
250 
251  def MoveL(self, pose, joints, conf_RLF=None):
252  """Add a linear movement"""
253  self.addline('LIN {' + pose_2_str_ext(pose,joints) + '}' + self.C_DIS + ' Vel=%.1fmm/s TOOL[%i] BASE[%i]' % (self.SPEED_MMS,self.ID_TOOL,self.ID_BASE))
254 
255  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
256  """Add a circular movement"""
257  self.addline('CIRC {' + pose_2_str_ext(pose1,joints1) + '}{' + pose_2_str_ext(pose2,joints2) + '}' + self.C_DIS + ' Vel=%.1fmm/s TOOL[%i] BASE[%i]' % (self.SPEED_MMS,self.ID_TOOL,self.ID_BASE))
258 
259  def setFrame(self, pose, frame_id=None, frame_name=None):
260  """Change the robot reference frame"""
261  if frame_id is None or frame_id < 1:
262  frame_id = 1
263  frame_name = get_safe_name(frame_name)
264  self.ID_BASE = frame_id
265  self.addline('FRAME ' + frame_name + '={' + pose_2_str(pose) + '}')
266  self.addline('SET_BASE ' + str(frame_id))
267  self.addline('SET_BASE ' + frame_name)
268 
269  def setTool(self, pose, tool_id=None, tool_name=None):
270  """Change the robot TCP"""
271  if tool_id is None or tool_id < 1:
272  tool_id = 0
273  tool_name = get_safe_name(tool_name)
274  self.ID_TOOL = tool_id
275  self.addline('FRAME ' + tool_name + '={' + pose_2_str(pose) + '}')
276  self.addline('SET_TOOL ' + str(tool_id))
277  self.addline('SET_TOOL ' + tool_name)
278 
279  def Pause(self, time_ms):
280  """Pause the robot program"""
281  if time_ms <= 0:
282  self.addline('HALT')
283  else:
284  self.addline('WAIT SEC %.3f' % (time_ms*0.001))
285 
286  def setSpeed(self, speed_mms):
287  """Changes the robot speed (in mm/s)"""
288  self.SPEED_MMS = speed_mms
289  self.addline('; SPEED = %.5f mm/s' % (speed_mms))
290 
291  def setAcceleration(self, accel_mmss):
292  """Changes the current robot acceleration"""
293  self.addline('; ACCELERATION = %.5f' % (accel_mmss/1000.0))
294 
295  def setSpeedJoints(self, speed_degs):
296  """Changes the robot joint speed (in deg/s)"""
297  self.addline('; JOINT SPEED = %.5f deg/s' % speed_degs)
298  self.SPEED_PERCENT = max(0,min(100,100*speed_degs/300.0))
299 
300  def setAccelerationJoints(self, accel_degss):
301  """Changes the robot joint acceleration (in deg/s2)"""
302  self.addline('; JOINT ACCELERATION = %.5f deg/s2' % accel_degss)
303 
304  def setZoneData(self, zone_mm):
305  """Changes the zone data approach (makes the movement more smooth)"""
306  self.APO_VALUE = zone_mm
307  if zone_mm >= 0:
308  self.addline('CPTP = %.3f' % zone_mm)
309  self.addline('CLIN = %.3f' % zone_mm)
310  self.C_DIS = ' C_LIN'
311  self.C_PTP = ' C_PTP'
312  else:
313  self.C_DIS = ' CONT'
314  self.C_PTP = ' CONT'
315 
316  def setDO(self, io_var, io_value):
317  """Sets a variable (output) to a given value"""
318  if type(io_var) != str: # set default variable name if io_var is a number
319  io_var = '$DO[%s]' % str(io_var)
320  if type(io_value) != str: # set default variable value if io_value is a number
321  if io_value > 0:
322  io_value = 'TRUE'
323  else:
324  io_value = 'FALSE'
325 
326  # at this point, io_var and io_value must be string values
327  self.addline('%s=%s' % (io_var, io_value))
328 
329  def waitDI(self, io_var, io_value, timeout_ms=-1):
330  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
331  if type(io_var) != str: # set default variable name if io_var is a number
332  io_var = '$DI[%s]' % str(io_var)
333  if type(io_value) != str: # set default variable value if io_value is a number
334  if io_value > 0:
335  io_value = 'TRUE'
336  else:
337  io_value = 'FALSE'
338 
339  # at this point, io_var and io_value must be string values
340  #if timeout_ms < 0:
341  self.addline('WHILE %s!=%s' % (io_var, io_value))
342  self.addline(' WAIT SEC 0.1')
343  self.addline('ENDWHILE')
344 
345  #else:
346 
347  def RunCode(self, code, is_function_call = False):
348  """Adds code or a function call"""
349  if is_function_call:
350  code.replace(' ','_')
351  if code.endswith('()'):
352  code = code[:-2]
353  self.addline(code)
354  else:
355  self.addline(code)
356 
357  def RunMessage(self, message, iscomment = False):
358  """Add a joint movement"""
359  if iscomment:
360  self.addline('; ' + message)
361  else:
362  self.addline('; Display message: ' + message)
363 
364 # ------------------ private ----------------------
365  def addline(self, newline):
366  """Add a program line"""
367  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
368  return
369 
370  if self.nLines > self.MAX_LINES_X_PROG:
371  self.nLines = 0
372  self.ProgFinish(self.PROG_NAME, True)
373  self.ProgStart(self.PROG_NAME, True)
374 
375  self.PROG = self.PROG + newline + '\n'
376  self.nLines = self.nLines + 1
377 
378  def addlog(self, newline):
379  """Add a log message"""
380  if self.nProgs > 1 and not self.INCLUDE_SUB_PROGRAMS:
381  return
382 
383  self.LOG = self.LOG + newline + '\n'
384 
385 # -------------------------------------------------
386 # ------------ For testing purposes ---------------
387 def Pose(xyzrpw):
388  [x,y,z,r,p,w] = xyzrpw
389  a = r*math.pi/180
390  b = p*math.pi/180
391  c = w*math.pi/180
392  ca = math.cos(a)
393  sa = math.sin(a)
394  cb = math.cos(b)
395  sb = math.sin(b)
396  cc = math.cos(c)
397  sc = math.sin(c)
398  return Mat([[cb*ca, ca*sc*sb - cc*sa, sc*sa + cc*ca*sb, x],[cb*sa, cc*ca + sc*sb*sa, cc*sb*sa - ca*sc, y],[-sb, cb*sc, cc*cb, z],[0,0,0,1]])
399 
400 def test_post():
401  """Test the post with a basic program"""
402 
403  robot = RobotPost('Kuka_custom', 'Generic Kuka')
404 
405  robot.ProgStart("Program")
406  robot.RunMessage("Program generated by RoboDK", True)
407  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
408  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
409  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
410  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
411  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
412  robot.RunMessage("Setting air valve 1 on")
413  robot.RunCode("TCP_On", True)
414  robot.Pause(1000)
415  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
416  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
417  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
418  robot.RunMessage("Setting air valve off")
419  robot.RunCode("TCP_Off", True)
420  robot.Pause(1000)
421  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
422  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
423  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
424  robot.ProgFinish("Program")
425  # robot.ProgSave(".","Program",True)
426  print(robot.PROG)
427  if len(robot.LOG) > 0:
428  mbox('Program generation LOG:\n\n' + robot.LOG)
429 
430  input("Press Enter to close...")
431 
432 if __name__ == "__main__":
433  """Function to call when the module is executed by itself: test"""
434  test_post()
def ProgStart(self, progname, new_page=False)
Definition: HIWIN_HRSS.py:138
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: HIWIN_HRSS.py:246
def MoveL(self, pose, joints, conf_RLF=None)
Definition: HIWIN_HRSS.py:251
def ProgFinish(self, progname, new_page=False)
Definition: HIWIN_HRSS.py:162
def setTool(self, pose, tool_id=None, tool_name=None)
Definition: HIWIN_HRSS.py:269
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: HIWIN_HRSS.py:128
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: HIWIN_HRSS.py:259
def RunCode(self, code, is_function_call=False)
Definition: HIWIN_HRSS.py:347
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: HIWIN_HRSS.py:329
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: HIWIN_HRSS.py:204
def progsave(self, folder, progname, ask_user=False, show_result=False)
Definition: HIWIN_HRSS.py:171
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: HIWIN_HRSS.py:255
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: HIWIN_HRSS.py:241
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def RunMessage(self, message, iscomment=False)
Definition: HIWIN_HRSS.py:357


ros_robodk_post_processors
Author(s): Victor Lamoine - Institut Maupertuis
autogenerated on Sun Jun 7 2020 03:50:22