Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5

ABB Positioner Cartesian Move Discrepancy

#1
I have an ABB IRB2600-12/1.85 6 axis robot arm with an ABB IRBPA750 2 axis positioner table. The TCP and table are calibrated in both RoboDK and on the robot pendent.

To test the coordinated motion of the system, I have the robot TCP following a point on the table as the table rotates +/-90 and tilts +/-90. When I generate a program as joint moves, the simulated RoboDK behavior matches the actual behavior of the robot. However, when I generate the program to use linear moves, the actual behavior deviates. The TCP drifts in the Y (~10mm) and Z (~80mm). The discrepancy between the MoveJ and MoveL behaviors suggests a base frame error. However, given the 10 and 80 mm shifts in Y and Z, I don't know where this offset is occurring (numbers are too big to be an offset of the mechanical unit but too small to match flange to calibration offsets).

Please help identify the cause of this discrepancy between the MoveJ and MoveL based programs.

In addition to the first question, there is a (related) question about user and object frames of the wobjdata. The RoboDK post outputs a wobjdata as follows:
Code:
PERS wobjdata STN1Flange := [FALSE, FALSE, "STN1", [[0.000,0.000,0.000],[1.00000000,0.00000000,0.00000000,0.00000000]],[[0,0,0],[1,0,0,0]]];

Where robhold = false (robot is not holding work object), ufprog = false (moveable user coordinate system) and ufmec =  user frame mechanical unit is named STN1, uframe = user frame as pulled from robot machining project/program with respect to the robot flange, and oframe = object frame is set to all zeros. 

Reading the ABB RAPID manual, wobjdata should be defined as [FALSE, FALSE, "STN1", [uframe],[oframe]] where the user frame is the base frame of the positioner holding the workpiece (this is what the manual says, but in practice it appears to be the reference frame of the flange) and the object frame should be the reference frame with respect to the flange. When I output a program with respect to a reference frame (e.g. a toolpath along a part), RoboDK changes the user frame of wobjdata, not the object frame. 

For example the RoboDK output is:
PERS wobjdata Adjustment := [FALSE, FALSE, "STN1", [[-217.173,-113.601,51.955], 0.99999749,0.00133557,0.00027939,0.00177687]],[[0,0,0],[1,0,0,0]]];

But, I think ABB is looking for:
PERS wobjdata Adjustment := [FALSE, FALSE, "STN1", [[0,0,0],[1,0,0,0]], [[-217.173,-113.601,51.955], 0.99999749,0.00133557,0.00027939,0.00177687]] ]; 

Can you please clarify how object frames are defined in RoboDK?


Attached Files
.rdk   ABB Cell_BuildTable mk24_clean.rdk (Size: 4.27 MB / Downloads: 45)
#2
Since you have a turntable and the coordinate system of the part is attached to your turntable I believe you should use something like this for your ABB controller:
Code:
PERS wobjdata Adjustment := [FALSE, FALSE, "Mechanical_Unit_Name", [[0,0,0],[1,0,0,0]], [[-217.173,-113.601,51.955],[1,0,0,0]] ];
This is the default output of RoboDK, however, you should update the name of your mechanical unit for the turntable (not the robot). I believe this should be different from STN1. Maybe more like T6003 or IRBP_L.

Having the pose data in the uframe or the oframe fields should not make a difference. It should be on one or the other one. ABB accounts for the combination of both.
#3
(08-23-2024, 11:46 AM)Albert Wrote: Since you have a turntable and the coordinate system of the part is attached to your turntable I believe you should use something like this for your ABB controller:
Code:
PERS wobjdata Adjustment := [FALSE, FALSE, "Mechanical_Unit_Name", [[0,0,0],[1,0,0,0]], [[-217.173,-113.601,51.955],[1,0,0,0]] ];
This is the default output of RoboDK, however, you should update the name of your mechanical unit for the turntable (not the robot). I believe this should be different from STN1. Maybe more like T6003 or IRBP_L.

Having the pose data in the uframe or the oframe fields should not make a difference. It should be on one or the other one. ABB accounts for the combination of both.

I agree that the wobjdata should be defined as you suggest. However, RoboDK outputs the adjustment frame in the uframe, not the oframe (e.g. as the first frame, not the second). 

I have updated my station to include identical sets of targets in a frame identical to the flange and at an arbitrary offset with respect to the flange (frame 11, [    18.812915,  177.425007,  -155.525247,    -0.000000,    0.000000,    -0.000000 ] WRT flange). 

Here is the output from the STN1 Flange targets:
Code:
%%%
  VERSION:1
  LANGUAGE:ENGLISH
%%%
MODULE MOD_TurnTableSTN1

    ! -------------------------------
    ! Define customized variables here
    ! ...

    ! Tool variables:
    PERS tooldata toolRDK := [TRUE,[[346.602,7.309,63.820],[1.00000000,0.00000000,0.00000000,0.00000000]],[1,[0,0,20],[1,0,0,0],0,0,0.005]];

    ! Reference variables:
    PERS wobjdata RobotBase := [FALSE, FALSE, "STN1", [[0.000,0.000,0.000],[1.00000000,0.00000000,0.00000000,0.00000000]],[[0,0,0],[1,0,0,0]]];

    PROC MainRDK_TTSTN1()
        toolRDK := Thermoset;
        ActUnit STN1;
        ConfJ \On;
        ConfL \Off;
        ! Program generated by RoboDK v5.7.1 for ABB IRB 2600-12/1.85 on 23/08/2024 09:22:25
        ! Using nominal kinematics.
        MoveAbsJ [[-0.494447,77.820500,-29.746400,-0.203510,-48.049600,-0.048169],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        MoveL [[450.308,10.817,23.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[-1,0,-1,1],[9E+09,-0.001100,-90.000000,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,22.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,24.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[0,-1,0,1],[9E+09,-0.001100,90.000000,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,22.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,21.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[0,0,-2,1],[9E+09,-90.000000,-0.008300,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,22.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,20.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[-1,-1,1,1],[9E+09,90.000000,-0.008300,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
        MoveL [[450.308,10.817,22.351],[0.70634177,-0.00409424,0.70785494,0.00243430],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=RobotBase;
        WaitTime 0.500;
    ENDPROC

ENDMODULE

Here is the code generated for the identical targets placed in Frame11:
Code:
%%%
  VERSION:1
  LANGUAGE:ENGLISH
%%%
MODULE MOD_TurnTableFrame11

    ! -------------------------------
    ! Define customized variables here
    ! ...

    ! Tool variables:
    PERS tooldata toolRDK := [TRUE,[[346.602,7.309,63.820],[1.00000000,0.00000000,0.00000000,0.00000000]],[1,[0,0,20],[1,0,0,0],0,0,0.005]];

    ! Reference variables:
    PERS wobjdata Frame11 := [FALSE, FALSE, "STN1", [[18.813,177.425,-155.525],[1.00000000,0.00000000,0.00000000,0.00000000]],[[0,0,0],[1,0,0,0]]];

    PROC MainRDK_TTFrame11()
        toolRDK := Thermoset;
        ActUnit STN1;
        ConfJ \On;
        ConfL \Off;
        ! Program generated by RoboDK v5.7.1 for ABB IRB 2600-12/1.85 on 23/08/2024 09:22:27
        ! Using nominal kinematics.
        MoveAbsJ [[-0.494451,77.820500,-29.746400,-0.203503,-48.049600,-0.048153],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        MoveL [[431.495,-166.608,178.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[-1,0,-1,1],[9E+09,-0.001100,-90.000000,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,177.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,179.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[0,-1,0,1],[9E+09,-0.001100,90.000000,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,177.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,176.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[0,0,-2,1],[9E+09,-90.000000,-0.008300,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,177.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,179.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[0,-1,0,1],[9E+09,-0.001100,90.000000,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
        MoveL [[431.495,-166.608,177.876],[0.70634173,-0.00409420,0.70785498,0.00243434],[-1,-1,-1,1],[9E+09,-0.001116,-0.008340,9E+09,9E+09,9E+09]],v100,z1,toolRDK \WObj:=Frame11;
        WaitTime 0.500;
    ENDPROC

ENDMODULE

When I run TurnTableSTN1, the robot is close to the desired targets (offset in Y and Z per the MoveL vs MoveJ discrepancy). When I run TurnTableFrame11, the robot misses its targets by approximately the offset defined in the TurnTableFrame11 uframe. When I manually adjust TurnTableFrame11 to put the Frame11 offset from uframe to oframe, it behaves the same as TurnTableSTN1. RoboDK is not outputting the adjustment frames into the oframe as designed. Please advise on how to fix.

   
shows the -90 rotation of the TurnTableSTN1 program (first MoveL of program) comparing the programmed position (top) to actual position (bottom, read in from controller). Note the significant vertical offset.

   
shows the -90 rotation of the TurnTableFrame11 program (first MoveL of program) comparing the programmed position (top) to actual position (bottom, read in from controller). Note the significant offset in Y and small offset in Z.

The manually adjust oframe program produces the same result as TurnTableSTN1.

These images show the need to get the oframe set correctly (adjust my RoboDK output) and the MoveL discrepancy of my station (TurnTableSTN1 offset from programmed position). 


Please also comment on the discrepancy between the MoveJ and MoveL. I don't understand what frame is misaligned to cause such a discrepancy. The good alignment when running MoveJ suggests the cell is accurately modeled and calibrated, and suggests a frame error somewhere.


Attached Files
.rdk   ABB Cell_BuildTable mk24_clean.rdk (Size: 4.27 MB / Downloads: 32)
#4
I believe that setting the pose in the oframe or the uframe should show the same behavior as long as the other one is the identity.

However, if you want to output the frame in the oframe instead of the uframe you can customize the setFrame function of your post processor as shown in the attached sample code (note the comment called: Custom edit to output the frame offset on the oframe instead of the uframe).
Code:
    def setFrame(self, pose, frame_id=None, frame_name=None):
        """Change the robot reference frame"""
        if frame_name is not None:
            if pose == eye(4):
                self.WOBJDATA = "RobotBase"
            else:
                self.WOBJDATA = FilterName(frame_name, 'w', (set(RESERVED_NAMES) - set(self.FRAME_LIST)), self.CHARACTER_LIMIT)
        set_data = ''
        if self.HAS_TURNTABLE:
            if self.TURNTABLE_IGNORE and self.FR_EXTERNAL_POSE is not None:
                pose = self.FR_EXTERNAL_POSE * pose
                set_data = '%s := [FALSE, TRUE, "", [%s],[[0,0,0],[1,0,0,0]]];' % (self.WOBJDATA, pose_2_str(pose))
            else:
                # set_data = '%s := [FALSE, FALSE, "%s", [%s],[[0,0,0],[1,0,0,0]]];' % (self.WOBJDATA, self.MECHANICAL_UNIT_NAME, pose_2_str(pose))
                # Custom edit to output the frame offset on the oframe instead of the uframe
                set_data = '%s := [FALSE, FALSE, "%s", [[0,0,0],[1,0,0,0]],[%s]];' % (self.WOBJDATA, self.MECHANICAL_UNIT_NAME, pose_2_str(pose))
        else:
            set_data = '%s := [FALSE, TRUE, "", [%s],[[0,0,0],[1,0,0,0]]];' % (self.WOBJDATA, pose_2_str(pose))
        if self.WOBJDATA in self.FRAME_LIST:
            self.addline(set_data)
        else:
            self.FRAME_LIST.append(self.WOBJDATA)
            self.FRAME_DEF.append(ONETAB + 'PERS wobjdata %s' % set_data)
It is better if you can contact us by email to get the source code of the full post processor.
  




Users browsing this thread:
1 Guest(s)