Denso_PAC.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 POST PROCESSOR for Robot Offline Programming to generate programs
14 # for Denso robots using RC7, RC7M controller and earlier controllers (PAC programming language)
15 # Note: Use RC8 controller (PACScript) for newer robot controllers
16 #
17 # To edit/test this POST PROCESSOR script file:
18 # Select "Program"->"Add/Edit Post Processor", then select your post or create a new one.
19 # 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.
20 # Python should be automatically installed with RoboDK
21 #
22 # You can also edit the POST PROCESSOR manually:
23 # 1- Open the *.py file with Python IDLE (right click -> Edit with IDLE)
24 # 2- Make the necessary changes
25 # 3- Run the file to open Python Shell: Run -> Run module (F5 by default)
26 # 4- The "test_post()" function is called automatically
27 # Alternatively, you can edit this file using a text editor and run it with Python
28 #
29 # To use a POST PROCESSOR file you must place the *.py file in "C:/RoboDK/Posts/"
30 # To select one POST PROCESSOR for your robot in RoboDK you must follow these steps:
31 # 1- Open the robot panel (double click a robot)
32 # 2- Select "Parameters"
33 # 3- Select "Unlock advanced options"
34 # 4- Select your post as the file name in the "Robot brand" box
35 #
36 # To delete an existing POST PROCESSOR script, simply delete this file (.py file)
37 #
38 # ----------------------------------------------------
39 # More information about RoboDK Post Processors and Offline Programming here:
40 # http://www.robodk.com/help#PostProcessor
41 # http://www.robodk.com/doc/en/PythonAPI/postprocessor.html
42 # ----------------------------------------------------
43 
44 
45 # ----------------------------------------------------
46 # Import RoboDK tools
47 from robodk import *
48 
49 # ----------------------------------------------------
50 def pose_2_str(pose):
51  """Converts a pose target to a string"""
52  [x,y,z,w,p,r] = Pose_2_Adept(pose)
53  return ('(%.3f,%.3f,%.3f,%.3f,%.3f,%.3f)' % (x,y,z,w,p,r))
54 
55 def joints_2_str(angles):
56  """Contverts a joint target to a string"""
57  return 'J(%s)' % (','.join(format(ji, ".5f") for ji in angles))
58 
59 # ----------------------------------------------------
60 # Object class that handles the robot instructions/syntax
61 class RobotPost(object):
62  """Robot post object"""
63  PROG_EXT = 'pac' # set the program extension
64  MAX_LINES_X_PROG = 1e9 # maximum number of lines per program. It will then generate multiple "pages (files)". This can be overriden by RoboDK settings.
65 
66  # other variables
67  ROBOT_POST = ''
68  ROBOT_NAME = ''
69  PROG_FILES = []
70 
71  PROG = ''
72  LOG = ''
73 
74  TAB = ''
75  SPEED_MPS = 0.1 # Speed in meters per second
76  SPEED = 10 # Speed in percentage
77  PASS = '@P' # Nothing = default = '@0' (does not work!) @P is more reliable
78  ACTIVE_TOOL = 2
79  ACTIVE_WOBJ = 3
80 
81  NO_INLINE_MOVE = True # Do not use inline moves (use variables instead)
82  HEADER_DEFINE = ''
83  P_ID = 0
84 
85  nProgs = 0
86 
87  nAxes = 6
88  AXES_TYPE = ['R','R','R','R','R','R'] # Important: This is usually set up by RoboDK automatically. Otherwise, override the __init__ procedure.
89  # 'R' for rotative axis, 'L' for linear axis, 'T' for external linear axis (linear track), 'J' for external rotative axis (turntable)
90  #AXES_TYPE = ['R','R','R','R','R','R','T','J','J'] #example of a robot with one external linear track axis and a turntable with 2 rotary axes
91  AXES_TRACK = []
92  AXES_TURNTABLE = []
93  HAS_TRACK = False
94  HAS_TURNTABLE = False
95 
96  def __init__(self, robotpost=None, robotname=None, robot_axes = 6, **kwargs):
97  self.ROBOT_POST = robotpost
98  self.ROBOT_NAME = robotname
99  self.PROG = ''
100  self.LOG = ''
101  self.nAxes = robot_axes
102  #for k,v in kwargs.iteritems(): # python2
103  for k,v in kwargs.items():
104  if k == 'lines_x_prog':
106  if k == 'axes_type':
107  self.AXES_TYPE = v
108 
109  for i in range(len(self.AXES_TYPE)):
110  if self.AXES_TYPE[i] == 'T':
111  self.AXES_TRACK.append(i)
112  self.HAS_TRACK = True
113  elif self.AXES_TYPE[i] == 'J':
114  self.AXES_TURNTABLE.append(i)
115  self.HAS_TURNTABLE = True
116 
117  def ProgStart(self, progname):
118  #self.addline('Sub Main%s()' % progname)
119  self.nProgs = self.nProgs + 1
120  if self.nProgs <= 1:
121  self.addline('PROGRAM %s' % progname)#MAIN')
122  else:
123  self.addline('PROGRAM %s' % progname)
124  self.addline('%PROGDEFS%')
125  self.TAB = ' '
126 
127  def ProgFinish(self, progname):
128  self.TAB = ''
129  self.addline("END")
130  self.addline("' End of program %s" % progname)
131 
132  def ProgSave(self, folder, progname, ask_user = False, show_result = False):
133  progname = progname + '.' + self.PROG_EXT
134  if ask_user or not DirExists(folder):
135  filesave = getSaveFile(folder, progname, 'Save program as...')
136  if filesave is not None:
137  filesave = filesave.name
138  else:
139  return
140  else:
141  filesave = folder + '/' + progname
142  fid = open(filesave, "w")
143  fid.write(self.PROG.replace('%PROGDEFS%\n', self.HEADER_DEFINE))
144  fid.close()
145  print('SAVED: %s\n' % filesave) # tell RoboDK the path of the saved file
146  self.PROG_FILES = filesave
147 
148  # open file with default application
149  if show_result:
150  if type(show_result) is str:
151  # Open file with provided application
152  import subprocess
153  p = subprocess.Popen([show_result, filesave])
154  elif type(show_result) is list:
155  import subprocess
156  p = subprocess.Popen(show_result + [filesave])
157  else:
158  # open file with default application
159  import os
160  os.startfile(filesave)
161  if len(self.LOG) > 0:
162  mbox('Program generation LOG:\n\n' + self.LOG)
163 
164  def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass):
165  """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".
166  The connection parameters must be provided in the robot connection menu of RoboDK"""
167  UploadFTP(self.PROG_FILES, robot_ip, remote_path, ftp_user, ftp_pass)
168 
169  def MoveJ(self, pose, joints, conf_RLF=None):
170  """Add a joint movement"""
171  #MOVE P, @P J(20.007, 70.475, 85.691, -137.266, 18.729, 64.496), Speed=20
172  #self.addline('MOVE P, @P %s, Speed=20' % joints_2_str(joints))
173  if self.NO_INLINE_MOVE:
174  self.P_ID = self.P_ID + 1
175  var_str = 'Pos%i' % self.P_ID
176  self.HEADER_DEFINE += self.TAB + 'DEFJNT %s = %s\n' % (var_str, joints_2_str(joints))
177  self.addline('MOVE P, %s %s' % (self.PASS, var_str))
178  else:
179  self.addline('MOVE P, %s %s' % (self.PASS, joints_2_str(joints)))
180 
181  def MoveL(self, pose, joints, conf_RLF=None):
182  """Add a linear movement"""
183  #MOVE L,@P P( -28.99, 20, 67.243, -90, -50.442, -180)
184  if self.NO_INLINE_MOVE:
185  if pose is None:
186  self.P_ID = self.P_ID + 1
187  var_str = 'Pos%i' % self.P_ID
188  self.HEADER_DEFINE += self.TAB + 'DEFJNT %s = %s\n' % (var_str, joints_2_str(joints))
189  self.addline('MOVE L, %s %s' % (self.PASS, var_str))
190  else:
191  self.P_ID = self.P_ID + 1
192  var_str = 'Pos%i' % self.P_ID
193  self.HEADER_DEFINE += self.TAB + 'DEFPOS %s = %s\n' % (var_str, pose_2_str(pose))
194  self.addline('MOVE L, %s %s' % (self.PASS, var_str))
195  else:
196  if pose is None:
197  self.addline('MOVE L, %s %s' % (self.PASS, joints_2_str(joints)))
198  else:
199  self.addline('MOVE L, %s %s' % (self.PASS, pose_2_str(pose)))
200 
201  def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None):
202  """Add a circular movement"""
203  #self.addlog('Circular move is not supported!')
204  #MOVE C, P( -25.306, 20, 68.895, -90, -49.948, -180),@[5] P( -19.256, 20, 62, -90, -50.06, -180), Speed=Mps(3)
205  if self.NO_INLINE_MOVE:
206  self.P_ID = self.P_ID + 1
207  var_str1 = 'Pos%i' % self.P_ID
208  self.HEADER_DEFINE += self.TAB + 'DEFPOS %s = %s\n' % (var_str, pose_2_str(pose1))
209  self.P_ID = self.P_ID + 1
210  var_str2 = 'Pos%i' % self.P_ID
211  self.HEADER_DEFINE += self.TAB + 'DEFPOS %s = %s\n' % (var_str, pose_2_str(pose2))
212  self.addline('MOVE C, %s,%s %s' % (var_str1, self.PASS, var_str2))
213  else:
214  self.addline('MOVE C, %s,%s %s' % (pose_2_str(pose1), self.PASS, pose_2_str(pose1)))
215 
216  def setFrame(self, pose, frame_id=None, frame_name=None):
217  """Change the robot reference frame"""
218  if frame_id is not None and frame_id > 0:
219  self.ACTIVE_TOOL = frame_id
220  self.addline('WORK %i, %s' % (self.ACTIVE_TOOL, pose_2_str(pose)))
221  self.addline('CHANGEWORK %i' % self.ACTIVE_TOOL)
222 
223  def setTool(self, pose, tool_id=None, tool_name=None):
224  """Change the robot TCP"""
225  if tool_id is not None and tool_id > 0:
226  self.ACTIVE_WOBJ = frame_id
227  self.addline('TOOL %i, %s' % (self.ACTIVE_WOBJ, pose_2_str(pose)))
228  self.addline('CHANGETOOL %i' % self.ACTIVE_WOBJ)
229 
230  def Pause(self, time_ms):
231  """Pause the robot program"""
232  if time_ms <= 0:
233  self.addline('HOLD "Program Paused"')
234  else:
235  self.addline('DELAY %.3f' % time_ms)
236 
237  def setSpeed(self, speed_mms):
238  """Changes the robot speed (in mm/s)"""
239  self.SPEED_MPS = speed_mms/1000.0
240  self.SPEED = max(min(speed_mms/2000.0, 100),1) # Speed in percentage
241  self.addline("' set speed to %.1f mm per sec" % speed_mms)
242  self.addline('SPEED %.0f' % self.SPEED)
243 
244  def setAcceleration(self, accel_mmss):
245  """Changes the robot acceleration (in mm/s2)"""
246  # Warning! Here, acceleration in mmss is considered as a percentage!
247  #accel_percentage = min(100,max(0,accel_mmss))
248  #self.addline('ACCEL %.1f, %.1f' % (accel_percentage, accel_percentage))
249  pass
250 
251  def setSpeedJoints(self, speed_degs):
252  """Changes the robot joint speed (in deg/s)"""
253  #self.addlog('setSpeedJoints not defined')
254  pass
255 
256  def setAccelerationJoints(self, accel_degss):
257  """Changes the robot joint acceleration (in deg/s2)"""
258  #self.addlog('setAccelerationJoints not defined')
259  pass
260 
261  def setZoneData(self, zone_mm):
262  """Changes the zone data approach (makes the movement more smooth)"""
263  #self.addlog('setZoneData not defined (%.1f mm)' % zone_mm)
264  # Encoder value check / pass @0 (fine), @P (approximated), @value (pulse value approximation) or @E
265  if zone_mm <=0:
266  self.PASS = '@0'
267  else:
268  self.PASS = '@P'
269  #self.PASS = '@[%i]' % zone_mm # Define zone data in pulses
270 
271 
272  def setDO(self, io_var, io_value):
273  """Sets a variable (output) to a given value"""
274  if type(io_var) != str: # set default variable name if io_var is a number
275  io_var = 'IO[%s]' % str(io_var)
276  if type(io_value) != str: # set default variable value if io_value is a number
277  if io_value > 0:
278  io_value = 'ON'
279  else:
280  io_value = 'OFF'
281 
282  # at this point, io_var and io_value must be string values
283  self.addline('OUT %s = %s' % (io_var, io_value))
284 
285  def waitDI(self, io_var, io_value, timeout_ms=-1):
286  """Waits for an input io_var to attain a given value io_value. Optionally, a timeout can be provided."""
287  if type(io_var) != str: # set default variable name if io_var is a number
288  io_var = 'IO[%s]' % str(io_var)
289  if type(io_value) != str: # set default variable value if io_value is a number
290  if io_value > 0:
291  io_value = 'ON'
292  else:
293  io_value = 'OFF'
294 
295  # at this point, io_var and io_value must be string values
296  if timeout_ms < 0:
297  self.addline('WAIT %s = %s' % (io_var, io_value))
298  else:
299  self.addline('WAIT %s = %s, %.0f' % (io_var, io_value, timeout_ms))
300 
301  def RunCode(self, code, is_function_call = False):
302  """Adds code or a function call"""
303  if is_function_call:
304  code.replace(' ','_')
305  if code.find('(') < 0:
306  code = code + '()'
307  self.addline(code)
308  else:
309  self.addline(code)
310 
311  def RunMessage(self, message, iscomment = False):
312  """Add a joint movement"""
313  if iscomment:
314  self.addline('\' ' + message)
315  else:
316  self.addline('PRINTMSG "%s", 0, "Message"' % message)
317 
318 # ------------------ private ----------------------
319  def addline(self, newline):
320  """Add a program line"""
321  self.PROG = self.PROG + self.TAB + newline + '\n'
322 
323  def addlog(self, newline):
324  """Add a log message"""
325  self.LOG = self.LOG + newline + '\n'
326 
327 # -------------------------------------------------
328 # ------------ For testing purposes ---------------
329 def Pose(xyzrpw):
330  [x,y,z,r,p,w] = xyzrpw
331  a = r*math.pi/180
332  b = p*math.pi/180
333  c = w*math.pi/180
334  ca = math.cos(a)
335  sa = math.sin(a)
336  cb = math.cos(b)
337  sb = math.sin(b)
338  cc = math.cos(c)
339  sc = math.sin(c)
340  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]])
341 
342 def test_post():
343  """Test the post with a basic program"""
344 
345  robot = RobotPost('Vplus_custom', 'Generic Adept Robot')
346 
347  robot.ProgStart("Program")
348  robot.RunMessage("Program generated by RoboDK", True)
349  robot.setFrame(Pose([807.766544, -963.699898, 41.478944, 0, 0, 0]))
350  robot.setTool(Pose([62.5, -108.253175, 100, -60, 90, 0]))
351  robot.MoveJ(Pose([200, 200, 500, 180, 0, 180]), [-46.18419, -6.77518, -20.54925, 71.38674, 49.58727, -302.54752] )
352  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
353  robot.MoveL(Pose([200, 200, 262.132034, 180, 0, -150]), [-43.73892, -3.91728, -35.77935, 58.57566, 54.11615, -253.81122] )
354  robot.RunMessage("Setting air valve 1 on")
355  robot.RunCode("TCP_On", True)
356  robot.Pause(1000)
357  robot.MoveL(Pose([200, 250, 348.734575, 180, 0, -150]), [-41.62707, -8.89064, -30.01809, 60.62329, 49.66749, -258.98418] )
358  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
359  robot.MoveL(Pose([250, 250, 191.421356, 180, 0, -150]), [-39.75778, -1.04537, -40.37883, 52.09118, 54.15317, -246.94403] )
360  robot.RunMessage("Setting air valve off")
361  robot.RunCode("TCP_Off(55)", True)
362  robot.Pause(1000)
363  robot.MoveL(Pose([250, 300, 278.023897, 180, 0, -150]), [-37.52588, -6.32628, -34.59693, 53.52525, 49.24426, -251.44677] )
364  robot.MoveL(Pose([250, 200, 278.023897, 180, 0, -150]), [-41.85389, -1.95619, -34.89154, 57.43912, 52.34162, -253.73403] )
365  robot.MoveL(Pose([250, 150, 191.421356, 180, 0, -150]), [-43.82111, 3.29703, -40.29493, 56.02402, 56.61169, -249.23532] )
366  robot.ProgFinish("Program")
367  # robot.ProgSave(".","Program",True)
368  print(robot.PROG.replace('%PROGDEFS%\n', robot.HEADER_DEFINE))
369  if len(robot.LOG) > 0:
370  mbox('Program generation LOG:\n\n' + robot.LOG)
371 
372  input("Press Enter to close...")
373 
374 if __name__ == "__main__":
375  """Function to call when the module is executed by itself: test"""
376  test_post()
def MoveL(self, pose, joints, conf_RLF=None)
Definition: Denso_PAC.py:181
def UploadFTP(program, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: robodk.py:1312
def ProgSave(self, folder, progname, ask_user=False, show_result=False)
Definition: Denso_PAC.py:132
def mbox(msg, b1='OK', b2='Cancel', frame=True, t=False, entry=None)
Definition: robodk.py:1458
def setTool(self, pose, tool_id=None, tool_name=None)
Definition: Denso_PAC.py:223
def MoveC(self, pose1, joints1, pose2, joints2, conf_RLF_1=None, conf_RLF_2=None)
Definition: Denso_PAC.py:201
def ProgSendRobot(self, robot_ip, remote_path, ftp_user, ftp_pass)
Definition: Denso_PAC.py:164
def MoveJ(self, pose, joints, conf_RLF=None)
Definition: Denso_PAC.py:169
def __init__(self, robotpost=None, robotname=None, robot_axes=6, kwargs)
Definition: Denso_PAC.py:96
def getSaveFile(strdir='C:\\', strfile='file.txt', strtitle='Save file as ...')
Definition: robodk.py:1354
def setFrame(self, pose, frame_id=None, frame_name=None)
Definition: Denso_PAC.py:216
def RunCode(self, code, is_function_call=False)
Definition: Denso_PAC.py:301
def waitDI(self, io_var, io_value, timeout_ms=-1)
Definition: Denso_PAC.py:285
def RunMessage(self, message, iscomment=False)
Definition: Denso_PAC.py:311


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