Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - bobrobot

#1
Support / Re: plane to frame with python for prc
July 01, 2024, 10:11:12 AM
Thanks for the fast reply! I will keep working on it.

one other thing is the error :
2. Data conversion failed from Text to KUKA|prc Command.

Is there a way to put the python generated code into the CMDS of the KUKA|prc core

For instance the python outputs:
LIN: X 529.21, Y 193.84, Z 582.43, A 1.75, B 9.85, C 10.15, E1 0, E2 0, E3 0, E4 0
but the core doesn't like it as its a text instead of a KUKA|prc generated command.
Tried to put the text into the KRL code command but no luck

Thanks again!
#2
Support / plane to frame with python for prc
June 30, 2024, 08:30:38 PM
Hi Forum. Thanks in advance for your advice!!!
I am trying to get a little deeper into using python in combination with KUKA|prc for robotics :)
working with ChatGPT to create a class that takes planes and generates robot frames...
But its not going well :(

I have read that KUKA uses the Euler ZYX system to calculate the TCP orientation. This means that three rotations happen in a specific sequence to achieve the final orientation. The order is:

A rotation about the world Z axis
B rotation about the new Y axis
C rotation about the new X axis

Diving deeper to understand this I found the following site: https://www.mecademic.com/academic_articles/space-orientation-euler-angles/
Which is super interesting.

ok so i have a sample plane: O(0.00,0.00,0.00) Z(0.17,-0.17,0.97)
which when passed through the LIN motion component outputs: LIN: X 0, Y 0, Z 0, A 135.4, B 75.9, C 134.6, E1 0, E2 0, E3 0, E4 0
and when I pass through the following code generates: LIN: X 0.00, Y 0.00, Z 0.00, A 1.75, B 9.85, C 10.15, E1 0.00, E2 0.00, E3 0.00, E4 0.00
not sure whats gone wrong. any advice is appreciated!!! Thanks!!!

here is the python code (file attached):

import Rhino.Geometry as rg
import math

class PlaneProcessor:
    def __init__(self, plane):
        # Initialize with the input plane
        self.plane = plane
        self.frame = None

    def calculate_frame(self):
        # Deconstruct the plane to get its components
        origin = self.plane.Origin  # Origin point of the plane
        x_axis = self.plane.XAxis  # X-axis vector of the plane
        y_axis = self.plane.YAxis  # Y-axis vector of the plane
        z_axis = self.plane.ZAxis  # Z-axis vector of the plane

        # Construct the frame using the origin and axes
        self.frame = rg.Plane(origin, x_axis, y_axis)
   
    def get_euler_angles(self):
        if self.frame is None:
            # Ensure the frame is calculated
            self.calculate_frame()

        # Extract the axes from the frame
        x_axis = self.frame.XAxis
        y_axis = self.frame.YAxis
        z_axis = self.frame.ZAxis

        # Construct the transformation matrix from the axes
        transformation_matrix = [
            [x_axis.X, y_axis.X, z_axis.X],
            [x_axis.Y, y_axis.Y, z_axis.Y],
            [x_axis.Z, y_axis.Z, z_axis.Z]
        ]

        # Calculate Euler angles using the ZYX convention (intrinsic rotations)
        # A is the rotation around the world Z-axis
        A = math.atan2(transformation_matrix[1][0], transformation_matrix[0][0])
        # B is the rotation around the new Y-axis
        B = math.atan2(-transformation_matrix[2][0], math.sqrt(transformation_matrix[2][1] ** 2 + transformation_matrix[2][2] ** 2))
        # C is the rotation around the new X-axis
        C = math.atan2(transformation_matrix[2][1], transformation_matrix[2][2])

        # Convert the angles from radians to degrees
        A = math.degrees(A)
        B = math.degrees(B)
        C = math.degrees(C)

        # Adjust angles to ensure they are in the correct range (0-360 degrees)
        if A < 0:
            A += 360
        if B < 0:
            B += 360
        if C < 0:
            C += 360
       
        # Round angles to two decimal places
        A = round(A, 2)
        B = round(B, 2)
        C = round(C, 2)
       
        return A, B, C

    def get_kuka_frame(self):
        if self.frame is None:
            # Ensure the frame is calculated
            self.calculate_frame()
        # Get the Euler angles
        A, B, C = self.get_euler_angles()
        return self.frame.Origin, A, B, C

    def create_lin_command(self, X, Y, Z, A, B, C):
        # Generate the KUKA LIN command string
        E1, E2, E3, E4 = 0.0, 0.0, 0.0, 0.0  # External axes placeholders
        lin_command = "LIN: X {:.2f}, Y {:.2f}, Z {:.2f}, A {:.2f}, B {:.2f}, C {:.2f}, E1 {:.2f}, E2 {:.2f}, E3 {:.2f}, E4 {:.2f}".format(X, Y, Z, A, B, C, E1, E2, E3, E4)
        return lin_command

# Initialize the PlaneProcessor class with the input plane
plane_processor = PlaneProcessor(plane)

# Get the TCP pose values (X, Y, Z, A, B, C)
origin, A, B, C = plane_processor.get_kuka_frame()

# Extract X, Y, Z from the origin point
X = round(origin.X, 2)
Y = round(origin.Y, 2)
Z = round(origin.Z, 2)

# Create the LIN command
lin_command = plane_processor.create_lin_command(X, Y, Z, A, B, C)

# Output the TCP pose values and LIN command to Grasshopper
a = lin_command  # LIN command

happy Roboting!
-bob