Remap 3D Cubic Spline Interpolation code by Python

More
2 years 1 month ago #310440 by jurod
Hi, I don't know how to create something functional. My idea is as follows:
Create a Gcod remap for example G5.4/5.5 (start and end of block in gcode)
Using the project from BigJohnT from this page forum.linuxcnc.org/21-axis/30986-axis-position-logger?start=100
After creating the gcode, I would like to easily edit this code to spline using the remap code.
Original from position Logger:
Code:
G40  G80 G98  M6  T1  G43             S 20000 M3  G1 Z-100.0 F5000 G1  X583.8160   Y2785.3929   Z-80.0100  B-0.0060   C-180.6420    G1   X569.5160   Y2551.3630   Z-20.8590  B-0.0060  C-180.6420     G1   X569.5160   Y2551.3630   Z-534.4340  B-0.0060 C-180.6420    G1   X569.5160   Y2551.3630   Z-563.0960  B-0.0060 C-180.6420    G1   X587.9240   Y2551.3630   Z-562.6310  B-0.0060 C-180.6420    G1   X602.8020   Y2531.2934   Z-547.8260  B-0.0060 C-180.6420    G1   X616.4620   Y2550.4623   Z-563.0180  B-0.0060 C-180.6420    G1   X630.8120   Y2550.4623   Z-563.9780  B-0.0060 C-180.6420    G1   X601.7700   Y1631.0440   Z-563.0410  B-0.0060 C-180.6420    G1   X586.6920   Y1633.2648   Z-561.9940  B-0.0060 C-180.6420    G1   X574.5840   Y1656.0775   Z-546.8950  B-0.0060 C-180.6420    G1   X560.3560   Y1634.1061   Z-561.9290  B-0.0060 C-180.6420    G1   X545.8120   Y1634.7045   Z-562.6420  B-0.0060 C-180.6420    G1   X575.0200   Y2556.2819   Z-563.3090  B-0.0060 C-180.6420    G1   X575.0200   Y2556.2819   Z-543.9050  B-0.0060 C-180.6420    ; G1 Z-100.0 F20000 G1   X583.8160   Y2785.3929   Z-80.0100  B-0.0060 C-180.6420    M2
Edited:
Code:
G40  G80 G98  M6  T1  G43             S 20000 M3  G1 Z-100.0 F5000 G5.4    X583.8160   Y2785.3929   Z-80.0100  B-0.0060  C-180.6420        X569.5160   Y2551.3630   Z-20.8590  B-0.0060  C-180.6420             X569.5160   Y2551.3630   Z-534.4340  B-0.0060 C-180.6420        X569.5160   Y2551.3630   Z-563.0960  B-0.0060 C-180.6420        X587.9240   Y2551.3630   Z-562.6310  B-0.0060 C-180.6420        X602.8020   Y2531.2934   Z-547.8260  B-0.0060 C-180.6420        X616.4620   Y2550.4623   Z-563.0180  B-0.0060 C-180.6420        X630.8120   Y2550.4623   Z-563.9780  B-0.0060 C-180.6420        X601.7700   Y1631.0440   Z-563.0410  B-0.0060 C-180.6420        X586.6920   Y1633.2648   Z-561.9940  B-0.0060 C-180.6420        X574.5840   Y1656.0775   Z-546.8950  B-0.0060 C-180.6420        X560.3560   Y1634.1061   Z-561.9290  B-0.0060 C-180.6420        X545.8120   Y1634.7045   Z-562.6420  B-0.0060 C-180.6420        X575.0200   Y2556.2819   Z-563.3090  B-0.0060 C-180.6420    G5.5    X575.0200   Y2556.2819   Z-543.9050  B-0.0060 C-180.6420    ; G1 Z-100.0 F20000 G1   X583.8160   Y2785.3929   Z-80.0100  B-0.0060 C-180.6420    M2
From site  stackoverflow.com/questions/31543775/how...on/48085583#48085583
Example Python cede:
Code:
[code]def my_cubic_interp1d(x0, x, y): """ Interpolate a 1-D function using cubic splines. x0 : a 1d-array of floats to interpolate at x : a 1-D array of floats sorted in increasing order y : A 1-D array of floats. The length of y along the interpolation axis must be equal to the length of x. Implement a trick to generate at first step the cholesky matrice L of the tridiagonal matrice A (thus L is a bidiagonal matrice that can be solved in two distinct loops). additional ref: www.math.uh.edu/~jingqiu/math4364/spline.pdf # original function code at: https://stackoverflow.com/a/48085583/36061 This function is licenced under: Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) https://creativecommons.org/licenses/by-sa/3.0/ Original Author raphael valentin Date 3 Jan 2018 Modifications made to remove numpy dependencies: -all sub-functions by MR This function, and all sub-functions, are licenced under: Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) Mod author: Matthew Rowles Date 3 May 2021 """ def diff(lst): """ numpy.diff with default settings """ size = len(lst)-1 r = [0]*size for i in range(size): r[i] = lst[i+1] - lst[i] return r def list_searchsorted(listToInsert, insertInto): """ numpy.searchsorted with default settings """ def float_searchsorted(floatToInsert, insertInto): for i in range(len(insertInto)): if floatToInsert <= insertInto[i]: return i return len(insertInto) return [float_searchsorted(i, insertInto) for i in listToInsert] def clip(lst, min_val, max_val, inPlace = False): """ numpy.clip """ if not inPlace: lst = lst[:] for i in range(len(lst)): if lst[i] < min_val: lst[i] = min_val elif lst[i] > max_val: lst[i] = max_val return lst def subtract(a,b): """ returns a - b """ return a - b size = len(x) xdiff = diff(x) ydiff = diff(y) # allocate buffer matrices Li = [0]*size Li_1 = [0]*(size-1) z = [0]*(size) # fill diagonals Li and Li-1 and solve [L][y] = [B] Li[0] = sqrt(2*xdiff[0]) Li_1[0] = 0.0 B0 = 0.0 # natural boundary z[0] = B0 / Li[0] for i in range(1, size-1, 1): Li_1[i] = xdiff[i-1] / Li[i-1] Li[i] = sqrt(2*(xdiff[i-1]+xdiff[i]) - Li_1[i-1] * Li_1[i-1]) Bi = 6*(ydiff[i]/xdiff[i] - ydiff[i-1]/xdiff[i-1]) z[i] = (Bi - Li_1[i-1]*z[i-1])/Li[i] i = size - 1 Li_1[i-1] = xdiff[-1] / Li[i-1] Li[i] = sqrt(2*xdiff[-1] - Li_1[i-1] * Li_1[i-1]) Bi = 0.0 # natural boundary z[i] = (Bi - Li_1[i-1]*z[i-1])/Li[i] # solve [L.T][x] = [y] i = size-1 z[i] = z[i] / Li[i] for i in range(size-2, -1, -1): z[i] = (z[i] - Li_1[i-1]*z[i+1])/Li[i] # find index index = list_searchsorted(x0,x) index = clip(index, 1, size-1) xi1 = [x[num] for num in index] xi0 = [x[num-1] for num in index] yi1 = [y[num] for num in index] yi0 = [y[num-1] for num in index] zi1 = [z[num] for num in index] zi0 = [z[num-1] for num in index] hi1 = list( map(subtract, xi1, xi0) ) # calculate cubic - all element-wise multiplication f0 = [0]*len(hi1) for j in range(len(f0)): f0[j] = zi0[j]/(6*hi1[j])*(xi1[j]-x0[j])**3 + \ zi1[j]/(6*hi1[j])*(x0[j]-xi0[j])**3 + \ (yi1[j]/hi1[j] - zi1[j]*hi1[j]/6)*(x0[j]-xi0[j]) + \ (yi0[j]/hi1[j] - zi0[j]*hi1[j]/6)*(xi1[j]-x0[j]) return f0
[/code]

I'm not a python programmer. Is it possible to make something similar work?

Please Log in or Create an account to join the conversation.

More
2 years 1 month ago - 2 years 1 month ago #310461 by Aciera
I cannot comment on the example python code.
A python remap can certainly parse a file of logged point coordinates, do calculations on those points and then output the results as, say, a list of G1 X.. Y.. Z.. moves and write these into a ngc subroutine that is called later in the gcode.
The issue with python is the time it takes to do all these things so if you expect to be able to do something like this:

G01 X.. Y.. Z.. F...
G5.4 ...

and expect this to blend without pause then that is likely not possible because of the lag inherent to python. However if you can pause gcode execution for the time it takes the python script to do its thing then I don't see a problem.

In a python remap controlling the read-ahead is VERY important. The first thing you want to do is stop the read-ahead before it ingests the python remap. Hence there won't be any blending between the Gcode before the remap and the remap itself.
Last edit: 2 years 1 month ago by Aciera.

Please Log in or Create an account to join the conversation.

More
2 years 1 month ago #310467 by Todd Zuercher
I don't think the way to do this is with a g-code remap. Seems to me it should be job of a file filter that reads and translates the g-code file on loading. That is perfectly acceptable as a python script, or even a bash sed script. Then the time to process is only at file loading and it doesn't get in the way of the running realtime code.

Please Log in or Create an account to join the conversation.

More
2 years 1 month ago #310502 by jurod
You are probably right. I didn't realize the delay in the code, but that's not a bug. It can be a few seconds.
The method according to Todd is also a solution.
I'm not sure which way to go.
I don't know how to work well in Python (only a couple of basic simple things and editing)
Is there anyone who would help me with this problem?

Please Log in or Create an account to join the conversation.

More
2 years 1 month ago - 2 years 1 month ago #310503 by Aciera
If you don't need to log the points and calculate the interpolation in the same gcode then a filter is likely easier. The other thing is that your python script is for a planar curve (eg XY) but you want to interpolate in 3D. I'm not familiar with cubic interpolation for a 3d curve so I'm not sure if it would require interpolating XY and XZ separately and then combine the two.
If you had a clear description of how to calculate the way points for the interpolated curve (even if it's just in words) I might be able to put something together but I don't have the time to research the math right now.
Last edit: 2 years 1 month ago by Aciera.

Please Log in or Create an account to join the conversation.

More
2 years 1 month ago #310504 by Aciera
There was a fairly long discussion about 3d splines/clothoids here:
forum.linuxcnc.org/38-general-linuxcnc-q...lib?start=500#305223

Please Log in or Create an account to join the conversation.

Time to create page: 0.128 seconds
Powered by Kunena Forum