summaryrefslogtreecommitdiff
path: root/nc_files/gcmc_lib/trochoid-path.gcmc
blob: d5d0ee2f8e821759eb5fcdde5e44b4569c9198de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 * G-code meta compiler
 *
 * Copyright (C) 2014  B. Stultiens
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Trochoidal example
 * ------------------
 * Trochoidal movement for high-speed milling. A path is followed in a circular
 * pattern with given radius and increment. Afterwards, a clean cut is
 * performed to remove the residuals.
 *
 * NOTE: To take full advantage of trochoidal milling, you need to have a CNC
 * program that can look ahead to keep the speed high. For LinuxCNC that means
 * you will need the git version on branch circular-blend-arc-rc3 (or any later
 * branch thereof, until it is merges into the master branch).
 *
 * @@@--svg-toolwidth 0.5 --svg-opacity 0.25@@@
 */

/*
 * Trochoidal point calculation.
 * See: https://en.wikipedia.org/wiki/Trochoid
 */
function trochoid_point(ang, a, b)
{
	ang = to_rad(ang);	// Trochoids are defined in radians
	// The first part is the trochoid, the second part moves the first 180
	// degree point at a relative "0, 0" location so we can scale in any
	// way without having to do hard math
	return [ a * to_none(ang) - b * sin(ang), b - b * cos(ang) ] - [a*pi(), 2.0*b];
}

/*
 * Perform a move from startpoint to endpoint using a trochoidal path.
 * - Cutting at depth cutz (returns to old Z)
 * - Trochoid radius as specified
 * - Increment for each turn as specified
 */
function trochoid_move(startpoint, endpoint, cutz, radius, increment)
{
	local min_ainc = .1deg;  // avoid too long compute times (and log( value<=1))
	local min_rotations = 5; // avoid confusing appearance if too small
	local i;
	local a = increment/(2.0*pi());			// Trochoid step parameter
	local ainc = log10(to_mm(radius)) * 5.0deg;	// Steps are logarithmic based on the radius to reduce small steps
	local oldz = position()[2];
	local vec = endpoint - startpoint;		// Vector denoting path to move

	if (ainc < min_ainc) {
		error("ainc too small: ",ainc," (try: increase trochoid radius)");
		return;
	}

	// If we are not moving, it is an error
	if(length(vec) <= zero) {
		error("trochoid move is not going anywhere");
		return;
	}

	comment("-- trochoid_move at ", cutz, " from ", startpoint, " to ", endpoint, " radius=", radius, " increment=", increment, " --");
	// Calculate the number of *whole* rotations, rounded up, we need to make
	local n = 2.0rad * pi() * to_none(ceil(length(vec) / increment));
	local nrotations = n/(2.0rad * pi());
	if (nrotations < min_rotations) {
		error("too few rotations= ",nrotations," (try: decrease trochoid increment)");
		return;
	}
	if (verbose) {
		comment("debug, rotations= ",nrotations);
		comment("debug, ainc= ",ainc);
	}

	// The path may be arbitrary angled, get the angle for rotating the trochoid
	local rot = atan(vec[1], vec[0]);

	// Go to the trochoid entry-point and move to cutting deph
	goto(startpoint + rotate_xy(trochoid_point(0.0rad, a, radius), rot));
	move([-, -, cutz]);

	// Calculate each next point of the trochoid until we traversed the whole path to the endpoint
	for(i = 0.0deg; i < n; i += ainc) {
		move(startpoint + rotate_xy(trochoid_point(i, a, radius), rot));
	}

	// Return to old Z so we will not bump into stuff
	goto([-, -, oldz]);
	comment("-- trochoid_move end --");
}

/* -------------------- Main Program -------------------- */
//ngcgui: info: troichoid-path example (mm or inch per parm#1 (units) setting, !! DEFAULTS are in mm !!)
//ngcgui: umode = 1;         //, units: 1:mm, 0:inch
//ngcgui: trochoid_r = 5;    //, trochoidal radius
//ngcgui: trochoid_incr = 2; //, trochoidal increment
//ngcgui: path_scale = 25;   //, path scale (all xi,yi)
//ngcgui: xoffset =  0;      //, path x offset
//ngcgui: yoffset =  0;      //, path y offset
//ngcgui: x0 =  0;           //, path x0
//ngcgui: y0 =  1;           //, path y0
//ngcgui: x1 =  2;           //, path x1
//ngcgui: y1 =  2;           //, path y1
//ngcgui: x2 =  0;           //, path x2
//ngcgui: y2 =  4;           //, path y2
//ngcgui: x3 = -1;           //, path x3
//ngcgui: y3 =  2;           //, path y3
//ngcgui: cutdepth = -1;     //
//ngcgui: safez = 5;         // z safe
//ngcgui: x_return = 0;      // x return
//ngcgui: y_return = 0;      // y return
//ngcgui: fnormal = 300;     //, feed normal
//ngcgui: fslow = 150;       //, feed slow
//ngcgui: ffast = 3000;      //, feed fast
//ngcgui: verbose = 1;

include("ensure_units.gcmc"); //avoid preamble conflict
if (umode == 1) {
  zero = 0.0mm;
} else {
  zero = 0.0in;
}
// ngcgui entries are unitless so these additions are used
// to ensure 1) floatingpoint and 2) units per umode setting
   trochoid_r = zero + trochoid_r;
trochoid_incr = zero + trochoid_incr;
      xoffset = zero + xoffset;
      yoffset = zero + yoffset;
           x0 = zero + x0;
           y0 = zero + y0;
           x1 = zero + x1;
           y1 = zero + y1;
           x2 = zero + x2;
           y2 = zero + y2;
           x3 = zero + x3;
           y3 = zero + y3;
     cutdepth = zero + cutdepth;
        safez = zero + safez;
     x_return = zero + x_return;
     y_return = zero + y_return;
      fnormal = zero + fnormal;
        fslow = zero + fslow;
        ffast = zero + ffast;

CUTZ = cutdepth;
SAFEZ = safez;
HOME = [x_return, y_return, safez];

path = { [xoffset + x0, yoffset + y0],
         [xoffset + x1, yoffset + y1],
         [xoffset + x2, yoffset + y2],
         [xoffset + x3, yoffset + y3] };
path *= path_scale;  //path_scale is dimensionless

feedrate(fnormal);
if (verbose) {
  comment("debug, feed normal= ",fnormal);
}
goto([-, -, SAFEZ]);
move([-, -, SAFEZ]);
goto(HOME);

/* Trochoidal high-speed milling of the outline */
if (verbose) {
  comment("debug, feed fast= ",ffast);
}
feedrate(ffast);	// *Really* high-speed milling
repeat(count(path); i) {
	trochoid_move(path[i-2], path[i-1], CUTZ, trochoid_r, trochoid_incr);

}

/* Clean-cutting the object */
if  (verbose) {
  comment("debug, feed slow= ",fslow);
}
feedrate(fslow);	// "Finishing the edge" speed
pathmode(1);		// Exact path mode so we hit the corners exactly
move([-, -, CUTZ]);	// We are at the "outside" of the path, reenter cutting depth
move(path[-1]);		// The first corner
foreach(path; v) {
	move(v);	// Trace the object
}

goto([-, -, SAFEZ]);
goto(HOME);