Universal_Robots_RobotiQ.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 Universal Robot with RoboDK
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 HEADER_PROG = '''#--------------- ROBOTIQ GRIPPER UTILITY
44  def RQ_2FG_Close():
45  global Position_close=255
46  global Speed_close=255
47  global Force_close=255
48  #Allocation of modbus output registers with the desired settings
49  out_reg2_close = Speed_close * 256 + Force_close
50  modbus_set_output_register("Speed_Force_Req", out_reg2_close, False)
51  modbus_set_output_register("Position_Req", Position_close, False)
52 
53  #Allow movement
54  modbus_set_output_signal("Go_to_Requested", True, False)
55  while(modbus_get_signal_status("Action_Status", False) == False):
56  sync()
57  end
58 
59  #Wait until the end of the movement
60  sleep(0.2)
61  while (not((modbus_get_signal_status("Obj_Det_Status1", False) == True) or (modbus_get_signal_status("Obj_Det_Status2", False) == True ))):
62  sleep(0.1)
63  sync()
64  end
65 
66  sleep(0.2)
67  #Status check object detection
68  global obj_detect1 = modbus_get_signal_status("Obj_Det_Status1",False)
69  global obj_detect2 = modbus_get_signal_status("Obj_Det_Status2",False)
70  if ((obj_detect1 == False) and (obj_detect2 == True)):
71  global Contact_opening = False
72  global Contact_closing = True
73  else:
74  if ((obj_detect1 == True) and (obj_detect2 == False)):
75  global Contact_opening = True
76  global Contact_closing = False
77  else:
78  global Contact_opening = False
79  global Contact_closing = False
80  end
81  end
82 
83  #Prohibit the movement
84  modbus_set_output_signal("Go_to_Requested", False, False)
85  while(modbus_get_signal_status("Action_Status", False) == True):
86  sync()
87  end
88  end
89  def RQ_2FG_Open():
90  global Position_open=0
91  global Speed_open=255
92  global Force_open=255
93  #Allocation of modbus output registers with the desired settings
94  out_reg2_open = Speed_open * 256 + Force_open
95  modbus_set_output_register("Speed_Force_Req", out_reg2_open, False)
96  modbus_set_output_register("Position_Req", Position_open, False)
97 
98  #Allow movement
99  modbus_set_output_signal("Go_to_Requested", True, False)
100  while(modbus_get_signal_status("Action_Status", False) == False):
101  sync()
102  end
103 
104  #Wait until the end of the movement
105  sleep(0.2)
106  while (not((modbus_get_signal_status("Obj_Det_Status1", False) == True) or (modbus_get_signal_status("Obj_Det_Status2", False) == True ))):
107  sleep(0.1)
108  sync()
109  end
110 
111  sleep(0.2)
112  #Status check object detection
113  global obj_detect1 = modbus_get_signal_status("Obj_Det_Status1",False)
114  global obj_detect2 = modbus_get_signal_status("Obj_Det_Status2",False)
115  if ((obj_detect1 == False) and (obj_detect2 == True)):
116  global Contact_opening = False
117  global Contact_closing = True
118  else:
119  if ((obj_detect1 == True) and (obj_detect2 == False)):
120  global Contact_opening = True
121  global Contact_closing = False
122  else:
123  global Contact_opening = False
124  global Contact_closing = False
125  end
126  end
127 
128  #Prohibit the movement
129  modbus_set_output_signal("Go_to_Requested", False, False)
130  while(modbus_get_signal_status("Action_Status", False) == True):
131  sync()
132  end
133  end
134 
135  #Activation if not activated
136  if ((modbus_get_signal_status("Gripper_Status1", False) == False) and (modbus_get_signal_status("Gripper_Status2", False) == False)):
137  modbus_set_output_signal("Activate", True, False)
138  end
139 
140  #Prohibit the movement
141  modbus_set_output_signal("Go_to_Requested", False, False)
142  while (modbus_get_signal_status("Action_Status", False) == True):
143  sync()
144  end
145 
146  #Awaiting the activation of the gripper
147  while (not(modbus_get_signal_status("Gripper_Status1", False) == True )):
148  sync()
149  end
150  while (not(modbus_get_signal_status("Gripper_Status2", False) == True )):
151  sync()
152  end
153 '''
154 
155 
156 
157 
158 # ----------------------------------------------------
159 # Import RoboDK tools
160 from robodk import *
161 
162 # ----------------------------------------------------
163 def pose_2_ur(pose):
164  """Calculate the p[x,y,z,rx,ry,rz] position for a pose target"""
165  def saturate_1(value):
166  return min(max(value,-1.0),1.0)
167 
168  angle = acos( saturate_1((pose[0,0]+pose[1,1]+pose[2,2]-1)/2) )
169  rxyz = [pose[2,1]-pose[1,2], pose[0,2]-pose[2,0], pose[1,0]-pose[0,1]]
170 
171  if angle == 0:
172  rxyz = [0,0,0]
173  else:
174  rxyz = normalize3(rxyz)
175  rxyz = mult3(rxyz, angle)
176  return [pose[0,3], pose[1,3], pose[2,3], rxyz[0], rxyz[1], rxyz[2]]
177 
178 def pose_2_str(pose):
179  """Prints a pose target"""
180  [x,y,z,w,p,r] = pose_2_ur(pose)
181  MM_2_M = 0.001
182  return ('p[%.6f, %.6f, %.6f, %.6f, %.6f, %.6f]' % (x*MM_2_M,y*MM_2_M,z*MM_2_M,w,p,r))
183 
184 def angles_2_str(angles):
185  """Prints a joint target"""
186  njoints = len(angles)
187  d2r = pi/180.0
188  if njoints == 6:
189  return ('[%.6f, %.6f, %.6f, %.6f, %.6f, %.6f]' % (angles[0]*d2r, angles[1]*d2r, angles[2]*d2r, angles[3]*d2r, angles[4]*d2r, angles[5]*d2r))
190  else:
191  return 'this post only supports 6 joints'
192 
193 # ----------------------------------------------------
194 # Object class that handles the robot instructions/syntax
195 class RobotPost(object):
196  """Robot post object"""
197  PROG_EXT = 'script' # set the program extension
198  SPEED_MS = 0.3 # default speed for linear moves in m/s
199  SPEED_RADS = 0.75 # default speed for joint moves in rad/s
200  ACCEL_MSS = 3 # default acceleration for lineaer moves in m/ss
201  ACCEL_RADSS = 1.2 # default acceleration for joint moves in rad/ss
202  BLEND_RADIUS_M = 0.001 # default blend radius in meters (corners smoothing)
203  REF_FRAME = eye(4) # default reference frame (the robot reference frame)
204  LAST_POS = None # last XYZ position
205 
206  # other variables
207  ROBOT_POST = 'unset'
208  ROBOT_NAME = 'generic'
209  PROG_FILES = []
210  MAIN_PROGNAME = 'unknown'
211 
212  PROG = ''
213  TAB = ''
214  LOG = ''
215 
216  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
217  self.ROBOT_POST = robotpost
218  self.ROBOT_NAME = robotname
219  self.nPROGS = 0
220  self.PROG = ''
221  self.LOG = ''
222 
223  def ProgStart(self, progname):
224  self.nPROGS = self.nPROGS + 1
225  self.addline('def %s():' % progname)
226  self.TAB = ' '
227  if self.nPROGS == 1:
228  self.MAIN_PROGNAME = progname
229  self.addline(HEADER_PROG)
230  self.addline('# default parameters:')
231  self.addline('global speed_ms = %.3f' % self.SPEED_MS)
232  self.addline('global speed_rads = %.3f' % self.SPEED_RADS)
233  self.addline('global accel_mss = %.3f' % self.ACCEL_MSS)
234  self.addline('global accel_radss = %.3f' % self.ACCEL_RADSS)
235  self.addline('global blend_radius_m = %.3f' % self.BLEND_RADIUS_M)
236 
237  def ProgFinish(self, progname):
238  self.TAB = ''
239  self.addline('end')
240  self.addline('')
241 
242  def ProgSave(self, folder, progname, ask_user = False, show_result = False):
243  self.addline('%s()' % self.MAIN_PROGNAME)
244  progname = progname + '.' + self.PROG_EXT
245  if ask_user or not DirExists(folder):
246  filesave = getSaveFile(folder, progname, 'Save program as...')
247  if filesave is not None:
248  filesave = filesave.name
249  else:
250  return
251  else:
252  filesave = folder + '/' + progname
253  fid = open(filesave, "w")
254  fid.write(self.PROG)
255  fid.close()
256  print('SAVED: %s\n' % filesave) # tell RoboDK the path of the saved file
257  self.PROG_FILES = filesave
258 
259  # open file with default application
260  if show_result:
261  if type(show_result) is str:
262  # Open file with provided application
263  import subprocess
264  p = subprocess.Popen([show_result, filesave])
265  elif type(show_result) is list:
266  import subprocess
267  p = subprocess.Popen(show_result + [filesave])
268  else:
269  # open file with default application
270  import os
271  os.startfile(filesave)
272  if len(self.LOG) > 0:
273  mbox('Program generation LOG:\n\n' + self.LOG)
274 
275  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
276  """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".
277  The connection parameters must be provided in the robot connection menu of RoboDK"""
278  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
279 
280  def blend_radius_check(self, pose):
281  # check that the blend radius covers 40% of the move (at most)
282  blend_radius = 'blend_radius_m';
283  current_pos = pose.Pos()
284  if self.LAST_POS is None:
285  blend_radius = '0'
286  else:
287  distance = norm(subs3(self.LAST_POS, current_pos)) # in mm
288  if 0.4*distance < self.BLEND_RADIUS_M*1000:
289  blend_radius = '%.3f' % (0.4*distance*0.001)
290  self.LAST_POS = current_pos
291  return blend_radius
292 
293  def MoveJ(self, pose, joints, conf_RLF=None):
294  """Add a joint movement"""
295  if pose is None:
296  blend_radius = "0"
297  self.LAST_POS = None
298  else:
299  blend_radius = self.blend_radius_check(pose)
300  self.addline('movej(%s,accel_radss,speed_rads,0,%s)' % (angles_2_str(joints), blend_radius))
301 
302  def MoveL(self, pose, joints, conf_RLF=None):
303  """Add a linear movement"""
304  # Movement in joint space or Cartesian space should give the same result:
305  # pose_wrt_base = self.REF_FRAME*pose
306  # self.addline('movel(%s,accel_mss,speed_ms,0,blend_radius_m)' % (pose_2_str(pose_wrt_base)))
307  if pose is None:
308  blend_radius = "0"
309  self.LAST_POS = None
310  else:
311  blend_radius = self.blend_radius_check(pose)
312  self.addline('movel(%s,accel_mss,speed_ms,0,%s)' % (angles_2_str(joints), blend_radius))
313 
314  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
315  """Add a circular movement"""
316  blend_radius = self.blend_radius_check(pose2)
317  self.addline('movec(%s,%s,accel_mss,speed_ms,%s)' % (angles_2_str(joints1),angles_2_str(joints2), blend_radius))
318 
319  def setFrame(self, pose, frame_id=None, frame_name=None):
320  """Change the robot reference frame"""
321  # the reference frame is not needed if we use joint space for joint and linear movements
322  # the reference frame is also not needed if we use cartesian moves with respect to the robot base frame
323  # the cartesian targets must be pre-multiplied by the active reference frame
324  self.REF_FRAME = pose
325  self.addline('# set_reference(%s)' % pose_2_str(pose))
326 
327  def setTool(self, pose, tool_id=None, tool_name=None):
328  """Change the robot TCP"""
329  self.addline('set_tcp(%s)' % pose_2_str(pose))
330 
331  def Pause(self, time_ms):
332  """Pause the robot program"""
333  if time_ms <= 0:
334  self.addline('halt() # reimplement this function to force stop')
335  else:
336  self.addline('sleep(%.3f)' % (time_ms*0.001))
337 
338  def setSpeed(self, speed_mms):
339  """Changes the robot speed (in mm/s)"""
340  self.SPEED_MS = speed_mms/1000.0
341  self.addline('speed_ms = %.3f' % self.SPEED_MS)
342 
343  def setAcceleration(self, accel_mmss):
344  """Changes the robot acceleration (in mm/s2)"""
345  self.ACCEL_MSS = accel_mmss/1000.0
346  self.addline('accel_mss = %.3f' % self.ACCEL_MSS)
347 
348  def setSpeedJoints(self, speed_degs):
349  """Changes the robot joint speed (in deg/s)"""
350  self.SPEED_RADS = speed_degs*pi/180
351  self.addline('speed_rads = %.3f' % self.SPEED_RADS)
352 
353  def setAccelerationJoints(self, accel_degss):
354  """Changes the robot joint acceleration (in deg/s2)"""
355  self.ACCEL_RADSS = accel_degss*pi/180
356  self.addline('accel_radss = %.3f' % self.ACCEL_RADSS)
357 
358  def setZoneData(self, zone_mm):
359  """Changes the zone data approach (makes the movement more smooth)"""
360  if zone_mm < 0:
361  zone_mm = 0
362  self.BLEND_RADIUS_M = zone_mm / 1000.0
363  self.addline('blend_radius_m = %.3f' % self.BLEND_RADIUS_M)
364 
365  def setDO(self, io_var, io_value):
366  """Sets a variable (output) to a given value"""
367  if type(io_value) != str: # set default variable value if io_value is a number
368  if io_value > 0:
369  io_value = 'True'
370  else:
371  io_value = 'False'
372 
373  if type(io_var) != str: # set default variable name if io_var is a number
374  newline = 'set_standard_digital_out(%s, %s)' % (str(io_var), io_value)
375  else:
376  newline = '%s = %s' % (io_var, io_value)
377 
378  self.addline(newline)
379 
380  def waitDI(self, io_var, io_value, timeout_ms=-1):
381  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
382  if type(io_var) != str: # set default variable name if io_var is a number
383  io_var = 'get_standard_digital_in(%s)' % str(io_var)
384  if type(io_value) != str: # set default variable value if io_value is a number
385  if io_value > 0:
386  io_value = 'True'
387  else:
388  io_value = 'False'
389 
390  # at this point, io_var and io_value must be string values
391  #if timeout_ms < 0:
392  self.addline('while (%s != %s):' % (io_var, io_value))
393  self.addline(' sync()')
394  self.addline('end')
395 
396  def RunCode(self, code, is_function_call = False):
397  """Adds code or a function call"""
398  if is_function_call:
399  code.replace(' ','_')
400  if not code.endswith(')'):
401  code = code + '()'
402  self.addline(code)
403  else:
404  #self.addline(code)
405  self.addline('# ' + code) #generate custom code as a comment
406 
407  def RunMessage(self, message, iscomment = False):
408  """Show a message on the controller screen"""
409  if iscomment:
410  self.addline('# ' + message)
411  else:
412  self.addline('popup("%s","Message",False,False,blocking=True)' % message)
413 
414 # ------------------ private ----------------------
415  def addline(self, newline):
416  """Add a program line"""
417  self.PROG = self.PROG + self.TAB + newline + '\n'
418 
419  def addlog(self, newline):
420  """Add a log message"""
421  self.LOG = self.LOG + newline + '\n'
422 
423 # -------------------------------------------------
424 # ------------ For testing purposes ---------------
425 def Pose(xyzrpw):
426  [x,y,z,r,p,w] = xyzrpw
427  a = r*math.pi/180
428  b = p*math.pi/180
429  c = w*math.pi/180
430  ca = math.cos(a)
431  sa = math.sin(a)
432  cb = math.cos(b)
433  sb = math.sin(b)
434  cc = math.cos(c)
435  sc = math.sin(c)
436  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]])
437 
438 def test_post():
439  """Test the post with a basic program"""
440 
441  robot = RobotPost('Universal Robotics', 'Generic UR robot')
442 
443  robot.ProgStart("Program")
444  robot.RunMessage("Program generated by RoboDK", True)
445  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
446  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
447  robot.setSpeed(100) # set speed to 100 mm/s
448  robot.setAcceleration(3000) # set speed to 3000 mm/ss
449  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
450  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
451  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
452  robot.RunMessage("Setting air valve 1 on")
453  robot.RunCode("TCP_On", True)
454  robot.Pause(1000)
455  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
456  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
457  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
458  robot.RunMessage("Setting air valve off")
459  robot.RunCode("TCP_Off", True)
460  robot.Pause(1000)
461  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
462  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
463  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
464  robot.ProgFinish("Program")
465  # robot.ProgSave(".","Program",True)
466  print(robot.PROG)
467  if len(robot.LOG) > 0:
468  mbox('Program generation LOG:\n\n' + robot.LOG)
469 
470  input("Press Enter to close...")
471 
472 if __name__ == "__main__":
473  """Function to call when the module is executed by itself: test"""
474  test_post()
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
def ProgSave(self, folder, progname, ask_user=False, show_result=False)


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