Rhino Version 8 SR6 has broken my GH IronPython 2 script

Updating to this version of Rhino 8 SR6 (8.6.24101.5001, 2024-04-10) has broken an unchanged and previously working GH IronPython 2 script component.

Example attached:
Edit - code retracted

How is it broken exactly? I don’t see an error in SR 7 8.7.24113.23001.

"""
Ataraxia G-Code tool_path Visualizer scripting component
"""

__author__ = "Leo Pedersen"
__version__ = "2024.01.20"

import Grasshopper.Kernel as gh
import rhinoscriptsyntax as rs
import scriptcontext as sc

sc.doc = ghdoc
e = gh.GH_RuntimeMessageLevel.Error

arcs_centers_points = []
boolean_feed = []
float_drill_R_retract = 0.0
float_drill_Z_bottom = 0.0
int_rapid_dashes = 10
int_rapid_divisions = ((int_rapid_dashes - 1) * 2) + 1
int_T = 0
paths = []
point_current = rs.CreatePoint(point_start.X,point_start.Y,point_start.Z)
point_previous = rs.CreatePoint(point_current.X,point_current.Y,point_current.Z)
str_arc_center_mode = "incremental"
str_mode = ""


def Main():
    global curves_tool_path
    global point_tool_path_end
    process_Gcode()
    curves_tool_path = paths
    point_tool_path_end = rs.CreatePoint(point_current)

def process_Gcode():    
    for i in range(len(cut_Gcode)):
        #print("line "+str(i))         # uncomment for debugging
        str_block = str(cut_Gcode[i])
        set_mode(str_block)
        
        # substring block before comments
        str_block = str_block[:str_block.find("(")]
        if set_point_current(str_block):
            global str_mode
            #print str_mode            # uncomment for debugging
            if str_mode == "rapid":
                G00_rapid()
            elif str_mode == "feed line":
                G01_feed()
            elif str_mode.find("arc") >= 0:
                G02_G03_arc(str_block)
            elif str_mode == "drill":
                G81_drill(str_block)
            elif str_mode == "peck drill":
                G83_peck_drill(str_block)

def set_mode(str_block):
    global str_mode
    # no mode change
    if str_block.startswith("X"):
        return
    elif str_block.startswith("Y"):
        return
    elif str_block.startswith("Z"):
        return
    elif str_block.startswith("A"):
        return
    elif str_block.startswith("B"):
        return
    elif str_block.startswith("C"):
        return
    elif str_block.startswith("("):
        return
    
    # set movement mode
    elif str_block.startswith("G00"):
        str_mode = "rapid"
    elif str_block.startswith("G01"):
        str_mode =  "feed line"
    elif str_block.startswith("G02"):
        str_mode =  "feed arc clockwise"
    elif str_block.startswith("G03"):
        str_mode =  "feed arc counterclockwise"
    elif str_block.startswith("G80"):
        str_mode = ""
    elif str_block.startswith("G81"):
        str_mode = "drill"
    elif str_block.startswith("G83"):
        str_mode =  "peck drill"
    

    # tool change
    elif str_block.startswith("M06"):
        # cutter radius
        global float_cutter_diameter
        global float_cutter_radius
        int_diameter = str_block.find("Tool Change ") + 12
        int_inch = str_block.find('"')
        if int_inch != -1:
            float_cutter_diameter = float(str_block[int_diameter:int_inch])
        else:
            int_mm = str_block.find("mm")
            if int_mm != -1:
                float_cutter_diameter = float(str_block[int_diameter:int_mm]) * 0.03937
            else:
                float_cutter_diameter = 0.125               # tolken diameter for center drills etc.
        float_cutter_radius = float_cutter_diameter / 2
    
    # set arc center mode (works in Mach4 but not UCCNC)
    elif str_block.startswith("G90.1"):
        str_arc_center_mode = "absolute"
    elif str_block.startswith("G91.1"):
        str_arc_center_mode = "incremental"

def set_point_current(str_block):
    global point_current
    global point_previous
    global float_drill_Z_bottom
    # detect position change for each axis
    bool_movement = False
    point_new = rs.CreatePoint(point_current.X,point_current.Y,point_current.Z)
    int_X_start = str_block.find("X") + 1
    if int_X_start > 0:
        bool_movement = True
        int_X_end = str_block.find(" ", int_X_start)
        point_new.X = float(str_block[int_X_start:int_X_end])
    int_Y_start = str_block.find("Y") + 1
    if int_Y_start > 0:
        bool_movement = True
        int_Y_end = str_block.find(" ", int_Y_start)
        point_new.Y = float(str_block[int_Y_start:int_Y_end])
    int_Z_start = str_block.find("Z") + 1
    if int_Z_start > 0:
        bool_movement = True
        int_Z_end = str_block.find(" ", int_Z_start)
        point_new.Z = float(str_block[int_Z_start:int_Z_end])
        """if "drill" in str_mode:
            float_drill_Z_bottom = point_new.Z
            point_new.Z = point_current.Z"""
    
    int_A_start = str_block.find("A") + 1
    if int_A_start > 0:
        bool_movement = True
    int_B_start = str_block.find("B") + 1
    if int_B_start > 0:
        bool_movement = True
    int_C_start = str_block.find("C") + 1
    if int_C_start > 0:
        bool_movement = True

    if bool_movement == False:
        return False
    else:
        point_previous = rs.CreatePoint(point_current.X,point_current.Y,point_current.Z)
        point_current = rs.CreatePoint(point_new.X,point_new.Y,point_new.Z)
        return True

def G00_rapid():
    global paths
    global point_current
    global point_previous
    if rs.PointCompare(point_previous, point_current):
        return
    else:
        # rapid line
        line = rs.AddLine(point_previous, point_current)
        paths.append(line)
        boolean_feed.append(False)
        point_previous = rs.CreatePoint(point_current.X,point_current.Y,point_current.Z)

def G01_feed():
    global paths
    global point_current
    global point_previous
    if rs.PointCompare(point_previous, point_current):
        print "Error - G01 Feed distance 0"
    else:
        line = rs.AddLine(point_previous, point_current)
        paths.append(line)
        boolean_feed.append(True)
        point_previous = rs.CreatePoint(point_current.X,point_current.Y,point_current.Z)



def G02_G03_arc(str_block):
    global paths
    global point_current
    global point_previous
    global str_arc_center_mode
    
    point_arc_start = rs.CreatePoint(point_previous.X,point_previous.Y,point_previous.Z)
    point_arc_end = rs.CreatePoint(point_current.X, point_current.Y, point_current.Z)
    
    # find arc center coordinate I
    int_I_start = str_block.find("I") + 1
    if int_I_start > 0:
        int_I_end = str_block.find(" ", int_I_start)
        float_arc_I = float(str_block[int_I_start:int_I_end])
        if str_arc_center_mode == "incremental":
            float_arc_center_X = point_arc_start.X + float_arc_I
        elif str_arc_center_mode == "absolute":
            float_arc_center_X = float_arc_I
        else:
            ghenv.Component.AddRuntimeMessage(e, "Error: arc center I undefined.")
    else:
         ghenv.Component.AddRuntimeMessage(e, "Error: can't find I coordinate for arc center point")
    
    # find arc center coordinate J
    int_J_start = str_block.find("J") + 1
    if int_J_start > 0:
        int_J_end = str_block.find(" ", int_J_start)
        float_arc_J = float(str_block[int_J_start:int_J_end])
        if str_arc_center_mode == "incremental":
            float_arc_center_Y = point_arc_start.Y + float_arc_J
        elif str_arc_center_mode == "absolute":
            float_arc_center_Y = float_arc_J
        else:
            ghenv.Component.AddRuntimeMessage(e, "Error: arc center J undefined.")
    else:
         ghenv.Component.AddRuntimeMessage(e, "Error: can't find J coordinate for arc center point")
    
    # find arc radius
    float_arc_center_Z = point_arc_start[2]
    point_arc_center = rs.CreatePoint(float_arc_center_X, float_arc_center_Y, float_arc_center_Z)
    float_arc_radius = rs.Distance(point_arc_center, point_arc_start)
    
    # find arc plane
    if str_mode == "feed arc clockwise":
        vector_plane_arc_axis_Z = [0,0,-1]
    elif str_mode == "feed arc counterclockwise":
        vector_plane_arc_axis_Z = [0,0,1]
    vector_plane_arc_axis_X = rs.VectorCreate(point_arc_start, point_arc_center)
    plane_arc_center = rs.PlaneFromNormal(point_arc_center, vector_plane_arc_axis_Z, vector_plane_arc_axis_X)
    
    # check if arc is a circle or helix 360°
    if point_arc_end.X == point_arc_start.X and point_arc_end.Y == point_arc_start.Y:
        feed_arc = rs.AddCircle(plane_arc_center,float_arc_radius)
    else:
        # create arc
        vector_arc_start = rs.VectorCreate(point_arc_start,point_arc_center)
        vector_arc_end = rs.VectorCreate(point_arc_end,point_arc_center)
        float_arc_angle = rs.VectorAngle(vector_arc_start,vector_arc_end)
        float_angle_direction = rs.VectorCrossProduct(vector_arc_start,vector_arc_end)[2]
        if float_angle_direction < 0 and str_mode == "feed arc counterclockwise":
            float_arc_angle = 360 - float_arc_angle
        elif float_angle_direction > 0 and str_mode == "feed arc clockwise":
            float_arc_angle = 360 - float_arc_angle
        feed_arc = rs.AddArc(plane_arc_center, float_arc_radius, float_arc_angle)
        
    # check if arc is helical
    if point_arc_start.Z != point_arc_end.Z:
        # check for  closed circle
        if rs.IsCurveClosed(feed_arc):
            # split circle at start
            circle_splits = rs.SplitCurve(feed_arc,0.000000001)
            feed_arc = circle_splits[1]
        
        # morph arc into helix
        # get arc control points
        points_arc = rs.CurvePoints(feed_arc)
        float_knots_arc = rs.CurveKnots(feed_arc)
        int_degree_arc = rs.CurveDegree(feed_arc)
        float_weights_arc = rs.CurveWeights(feed_arc)
        float_helix_depthZ = point_arc_end.Z - point_arc_start.Z
        int_arc_points = len(points_arc)
        int_stepsZ = int_arc_points - 1
        float_stepZ = float_helix_depthZ / int_stepsZ
        points_helix = []
        float_knots_helix = []
        float_weights_helix = []
        # distribute control points through Z axis
        for i in range(int_arc_points):
            point_helix = [points_arc[i].X, points_arc[i].Y, points_arc[i].Z + (i * float_stepZ)]
            points_helix.append(point_helix)
        feed_arc = rs.AddNurbsCurve(points_helix, float_knots_arc, int_degree_arc, float_weights_arc)
    
    paths.append(feed_arc)
    boolean_feed.append(True)
    point_previous = rs.CreatePoint(point_current.X,point_current.Y,point_current.Z)


def G81_drill(str_block):
    global float_cutter_radius
    global float_drill_R_retract
    global float_drill_Z_bottom
    global paths
    global point_current
    global point_previous
    global str_mode
    
    # rapid to position at retract height
    int_R_start = str_block.find("R") + 1
    if int_R_start > 0:
        int_R_end = str_block.find(" ", int_R_start)
        float_drill_R_retract = float(str_block[int_R_start:int_R_end])
    float_drill_Z_bottom = point_current.Z
    point_current.Z = float_drill_R_retract
    G00_rapid()
    
    # drill feed to bottom
    point_current.Z = float_drill_Z_bottom
    G01_feed()
    plane_circle = rs.PlaneFromNormal(point_current, [0,0,1])
    paths.append(rs.AddCircle(plane_circle, float_cutter_radius))
    boolean_feed.append(True)
    
    # drill rapid retract
    point_current.Z = float_drill_R_retract
    G00_rapid()


def G83_peck_drill(str_block):
    global float_cutter_radius
    global float_drill_R_retract
    global float_drill_Z_bottom
    global float_Q_peck
    global paths
    global point_current
    global point_previous
    global str_mode
    
    #drill rapid to position at retract height
    int_R_start = str_block.find("R") + 1
    if int_R_start > 0:
        int_R_end = str_block.find(" ", int_R_start)
        float_drill_R_retract = float(str_block[int_R_start:int_R_end])
    float_drill_Z_bottom = point_current.Z
    point_current.Z = float_drill_R_retract
    G00_rapid()
    
    # drill pecking
    int_Q_start = str_block.find("Q") + 1
    if int_Q_start > 0:
        int_Q_end = str_block.find(" ", int_Q_start)
        float_Q_peck = float(str_block[int_Q_start:int_Q_end])
    while point_current.Z >= (float_drill_Z_bottom + float_Q_peck):
        point_current.Z = point_current.Z - float_Q_peck
        G01_feed()
        plane_circle = rs.PlaneFromNormal(point_current, [0,0,1])
        paths.append(rs.AddCircle(plane_circle, float_cutter_radius))
        boolean_feed.append(True)
    point_current.Z = float_drill_Z_bottom
    G01_feed()
    plane_circle = rs.PlaneFromNormal(point_current, [0,0,1])
    paths.append(rs.AddCircle(plane_circle, float_cutter_radius))
    boolean_feed.append(True)

    # drill rapid retract
    point_current.Z = float_drill_R_retract
    G00_rapid()



Main()

It’s broken in SR6.

Screen Shot 2024-05-01 at 10.58.56 AM

Thanks for testing it in the SR7 release candidate James.

I’ll have to work in the SR7 release candidates until SR7 becomes the current release.

1 Like

Hi @LeoPedersen ,
Can you try not to internalize the values for the “point_start” input. So just add an actual point to this point_start input. Does warning about type conversion happen again? How does the warning message look like in that case?

Hi @djordje there is no change when I add a point to the point_start input. Error is identical.

I see. Sorry then for the dumb suggestion.