Following the documents on creating the post processor, I was able to change the reference frames to be relative to the linear track. By enabling "Export External Axes Pose" and transforming the poses to be relative to the linear rail. Since the poses seems to be relative to the rail already. All I needed to do was take it out of the turntable's relative transform.
Code:
def setFrame(self, pose, frame_id, frame_name, *args, **kwargs):
"""Defines a new reference frame with respect to the robot base frame."""
# Taken from RoboDK's Post-Processor example where they are changing the relative pose of a movel
# Reference: https://robodk.com/doc/en/PythonAPI/postprocessor.html#post-processor-example
if self._PoseTrack or self._PoseTurntable:
if self.POSE_TURNTABLE and self.POSE_RAIL:
# Making Positioner relative pose to be relative to the Rail
pose = self.POSE_TURNTABLE * self._PoseTurntable * pose
elif self.POSE_TURNTABLE and self.POSE_RAIL:
# The first frame that gets created doesn't provide the _PoseTrack nor _PoseTurntable.
# So we're only checking if the POSE_TURNTABLE and POSE_RAIL was provided in the constructor
# to get the frame's pose relative to the rail.
frame_item = self.RDK.Item(frame_name, robolink.ITEM_TYPE_FRAME)
pose = frame_item.PoseWrt(self.rail_base)
self._frame_pose = pose
self._frame_id = frame_id
self._frame_name = frame_name
# Convert the pose to KUKA's FRAME format
frame_str = self.pose_2_str(pose)
# Add the line to set the base directly
self.addline('; ---- Setting reference: %s ----' % frame_name)
self.addline('$BASE = {FRAME: %s}' % frame_str)
self.addline('; --------------------------')
However, for some reason the first frame that gets created, doesn't provide the turntable or linear track poses.
Code:
r.RunMessage(r"""Program generated by RoboDK v5.8.0 for KUKA KR 20 R3100 1 on 31/03/2025 10:49:45""",True)
r.RunMessage(r"""Using nominal kinematics.""",True)
r.RunMessage(r"""INIT_PARAMS_START""",True)
r.RunMessage(r"""F8094 - M12127 - O1110""",True)
r.setZoneData(1.000)
r.setSpeed(30.000)
r.setFrame(p(159.352,89.885,-2604.75,-90,0,90),-1,r"""Part6279 Frame""")
r.setTool(p(19,-0.4,466.7,0,-40,0),3,r"""Fronius_Short 3""")
Setting another frame at the end of the program:
Code:
r._PoseTrack=p(-2400.000000,0.000000,0.000000,0.000000,0.000000,0.000000)
r._PoseTurntable=p(0.000000,0.000000,1280.000000,0.000000,90.000000,0.000000)
r.setFrame(p(-13.648,-106.115,-2604.75,90,0,-180),-1,r"""Action12127 Frame""")
Because of this I needed to get the frame and rail items directly from robodk to get the relative pose. Is there a reason why the first frame doesn't provide the poses? Or is there a better way of doing this?
Code:
def __init__(self, robotpost='', robotname='', robot_axes=6, *args, **kwargs):
# Optional constructor parameters (added later, backward compatibility)
self.AXES_TYPE = None # Optional, type of each axes of the robot ('R': Robot rotative, 'T': Robot translation, 'J': Ext. axis rotative, 'L': Ext. axis linear) (provided by RoboDK in the constructor)
self.NATIVE_NAME = robotname # Optional, native/original name of the robot (provided by RoboDK in the constructor)
self.IP_COM = None # Optional, IP address of the robot ("Connect" tab in RoboDK) (provided by RoboDK in the constructor)
self.API_PORT = None # Optional, RoboDK API port to the RoboDK instance (provided by RoboDK in the constructor)
self.PROG_PTR = None # Optional, RoboDK Item pointer to the program generated (provided by RoboDK in the constructor)
self.ROBOT_PTR = None # Optional, RoboDK Item pointer to the robot associated with the program generated (provided by RoboDK in the constructor)
self.POSE_TURNTABLE = None # Optional, offset pose of the synchronized turn table (provided by RoboDK in the constructor)
self.POSE_RAIL = None # Optional, offset pose of the synchronized linear rail (provided by RoboDK in the constructor)
self.MAX_LINES_X_PROG = None # Optional, maximum number of lines per program (to generate multiple files). This setting can be overridden in RoboDK (Tools-Options-Program) (provided by RoboDK in the constructor)
self.PULSES_X_DEG = None # Optional, pulses per degree (provided in the robot parameters of RoboDK) (provided by RoboDK in the constructor)
# Optional constructor parameters, you may or may not use those
for k, v in kwargs.items():
if k == 'axes_type':
self.AXES_TYPE = v
elif k == 'native_name':
self.NATIVE_NAME = v
elif k == 'ip_com':
self.IP_COM = v
elif k == 'api_port':
self.API_PORT = v
elif k == 'prog_ptr':
self.PROG_PTR = v
elif k == 'robot_ptr':
self.ROBOT_PTR = v
elif k == 'pose_turntable':
self.POSE_TURNTABLE = v
elif k == 'pose_rail':
self.POSE_RAIL = v
elif k == 'lines_x_prog':
self.MAX_LINES_X_PROG = v
elif k == 'pulses_x_deg':
self.PULSES_X_DEG = v
# Optional TEMP parameter (depends on RoboDK settings)
self._TargetName = None # Optional, target name (Tools->Options->Program->Export target names) (provided by RoboDK in the TEMP file)
self._TargetNameVia = None # Optional, intermediary target name (MoveC) (Tools->Options->Program->Export target names) (provided by RoboDK in the TEMP file)
self._PoseTrack = None # Optional, current pose of the synchronized linear axis (Tools->Options->Program->Export external axes poses) (provided by RoboDK in the TEMP file)
self._PoseTurntable = None # Optional, current pose of the synchronized turn table (Tools->Options->Program->Export external axes poses) (provided by RoboDK in the TEMP file)
self.RDK = robolink.Robolink()
robot_item = self.RDK.Item(robotname, robolink.ITEM_TYPE_ROBOT)
if self.POSE_TURNTABLE and self.POSE_RAIL:
links = robot_item.getLinks()
self.rail_base = links[0].Parent()