ソースを参照

Move plan_arc next to prepare_move

Scott Lahteine 10年前
コミット
e83eac312e
1個のファイルの変更142行の追加142行の削除
  1. 142
    142
      Marlin/Marlin_main.cpp

+ 142
- 142
Marlin/Marlin_main.cpp ファイルの表示

@@ -1888,148 +1888,6 @@ inline void gcode_G0_G1() {
1888 1888
 }
1889 1889
 
1890 1890
 /**
1891
- * Plan an arc in 2 dimensions
1892
- *
1893
- * The arc is approximated by generating many small linear segments.
1894
- * The length of each segment is configured in MM_PER_ARC_SEGMENT (Default 1mm)
1895
- * Arcs should only be made relatively large (over 5mm), as larger arcs with
1896
- * larger segments will tend to be more efficient. Your slicer should have
1897
- * options for G2/G3 arc generation. In future these options may be GCode tunable.
1898
- */
1899
-void plan_arc(
1900
-  float target[NUM_AXIS], // Destination position
1901
-  float *offset,          // Center of rotation relative to current_position
1902
-  uint8_t clockwise       // Clockwise?
1903
-) {
1904
-
1905
-  float radius = hypot(offset[X_AXIS], offset[Y_AXIS]),
1906
-        center_axis0 = current_position[X_AXIS] + offset[X_AXIS],
1907
-        center_axis1 = current_position[Y_AXIS] + offset[Y_AXIS],
1908
-        linear_travel = target[Z_AXIS] - current_position[Z_AXIS],
1909
-        extruder_travel = target[E_AXIS] - current_position[E_AXIS],
1910
-        r_axis0 = -offset[X_AXIS],  // Radius vector from center to current location
1911
-        r_axis1 = -offset[Y_AXIS],
1912
-        rt_axis0 = target[X_AXIS] - center_axis0,
1913
-        rt_axis1 = target[Y_AXIS] - center_axis1;
1914
-  
1915
-  // CCW angle of rotation between position and target from the circle center. Only one atan2() trig computation required.
1916
-  float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
1917
-  if (angular_travel < 0) { angular_travel += RADIANS(360); }
1918
-  if (clockwise) { angular_travel -= RADIANS(360); }
1919
-  
1920
-  // Make a circle if the angular rotation is 0
1921
-  if (current_position[X_AXIS] == target[X_AXIS] && current_position[Y_AXIS] == target[Y_AXIS] && angular_travel == 0)
1922
-    angular_travel += RADIANS(360);
1923
-  
1924
-  float mm_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
1925
-  if (mm_of_travel < 0.001) { return; }
1926
-  uint16_t segments = floor(mm_of_travel / MM_PER_ARC_SEGMENT);
1927
-  if (segments == 0) segments = 1;
1928
-  
1929
-  float theta_per_segment = angular_travel/segments;
1930
-  float linear_per_segment = linear_travel/segments;
1931
-  float extruder_per_segment = extruder_travel/segments;
1932
-  
1933
-  /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
1934
-     and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
1935
-         r_T = [cos(phi) -sin(phi);
1936
-                sin(phi)  cos(phi] * r ;
1937
-     
1938
-     For arc generation, the center of the circle is the axis of rotation and the radius vector is 
1939
-     defined from the circle center to the initial position. Each line segment is formed by successive
1940
-     vector rotations. This requires only two cos() and sin() computations to form the rotation
1941
-     matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
1942
-     all double numbers are single precision on the Arduino. (True double precision will not have
1943
-     round off issues for CNC applications.) Single precision error can accumulate to be greater than
1944
-     tool precision in some cases. Therefore, arc path correction is implemented. 
1945
-
1946
-     Small angle approximation may be used to reduce computation overhead further. This approximation
1947
-     holds for everything, but very small circles and large MM_PER_ARC_SEGMENT values. In other words,
1948
-     theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
1949
-     to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for 
1950
-     numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
1951
-     issue for CNC machines with the single precision Arduino calculations.
1952
-     
1953
-     This approximation also allows plan_arc to immediately insert a line segment into the planner 
1954
-     without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
1955
-     a correction, the planner should have caught up to the lag caused by the initial plan_arc overhead. 
1956
-     This is important when there are successive arc motions. 
1957
-  */
1958
-  // Vector rotation matrix values
1959
-  float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
1960
-  float sin_T = theta_per_segment;
1961
-  
1962
-  float arc_target[NUM_AXIS];
1963
-  float sin_Ti;
1964
-  float cos_Ti;
1965
-  float r_axisi;
1966
-  uint16_t i;
1967
-  int8_t count = 0;
1968
-
1969
-  // Initialize the linear axis
1970
-  arc_target[Z_AXIS] = current_position[Z_AXIS];
1971
-  
1972
-  // Initialize the extruder axis
1973
-  arc_target[E_AXIS] = current_position[E_AXIS];
1974
-
1975
-  float feed_rate = feedrate*feedrate_multiplier/60/100.0;
1976
-
1977
-  for (i = 1; i < segments; i++) { // Increment (segments-1)
1978
-
1979
-    if (count < N_ARC_CORRECTION) {
1980
-      // Apply vector rotation matrix to previous r_axis0 / 1
1981
-      r_axisi = r_axis0*sin_T + r_axis1*cos_T;
1982
-      r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
1983
-      r_axis1 = r_axisi;
1984
-      count++;
1985
-    }
1986
-    else {
1987
-      // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
1988
-      // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
1989
-      cos_Ti = cos(i*theta_per_segment);
1990
-      sin_Ti = sin(i*theta_per_segment);
1991
-      r_axis0 = -offset[X_AXIS]*cos_Ti + offset[Y_AXIS]*sin_Ti;
1992
-      r_axis1 = -offset[X_AXIS]*sin_Ti - offset[Y_AXIS]*cos_Ti;
1993
-      count = 0;
1994
-    }
1995
-
1996
-    // Update arc_target location
1997
-    arc_target[X_AXIS] = center_axis0 + r_axis0;
1998
-    arc_target[Y_AXIS] = center_axis1 + r_axis1;
1999
-    arc_target[Z_AXIS] += linear_per_segment;
2000
-    arc_target[E_AXIS] += extruder_per_segment;
2001
-
2002
-    clamp_to_software_endstops(arc_target);
2003
-
2004
-    #if defined(DELTA) || defined(SCARA)
2005
-      calculate_delta(arc_target);
2006
-      #ifdef ENABLE_AUTO_BED_LEVELING
2007
-        adjust_delta(arc_target);
2008
-      #endif
2009
-      plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], arc_target[E_AXIS], feed_rate, active_extruder);
2010
-    #else
2011
-      plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, active_extruder);
2012
-    #endif
2013
-  }
2014
-
2015
-  // Ensure last segment arrives at target location.
2016
-  #if defined(DELTA) || defined(SCARA)
2017
-    calculate_delta(target);
2018
-    #ifdef ENABLE_AUTO_BED_LEVELING
2019
-      adjust_delta(target);
2020
-    #endif
2021
-    plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], target[E_AXIS], feed_rate, active_extruder);
2022
-  #else
2023
-    plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, active_extruder);
2024
-  #endif
2025
-
2026
-  // As far as the parser is concerned, the position is now == target. In reality the
2027
-  // motion control system might still be processing the action and the real tool position
2028
-  // in any intermediate location.
2029
-  set_current_to_destination();
2030
-}
2031
-
2032
-/**
2033 1891
  * G2: Clockwise Arc
2034 1892
  * G3: Counterclockwise Arc
2035 1893
  */
@@ -6229,6 +6087,148 @@ void prepare_move() {
6229 6087
   set_current_to_destination();
6230 6088
 }
6231 6089
 
6090
+/**
6091
+ * Plan an arc in 2 dimensions
6092
+ *
6093
+ * The arc is approximated by generating many small linear segments.
6094
+ * The length of each segment is configured in MM_PER_ARC_SEGMENT (Default 1mm)
6095
+ * Arcs should only be made relatively large (over 5mm), as larger arcs with
6096
+ * larger segments will tend to be more efficient. Your slicer should have
6097
+ * options for G2/G3 arc generation. In future these options may be GCode tunable.
6098
+ */
6099
+void plan_arc(
6100
+  float target[NUM_AXIS], // Destination position
6101
+  float *offset,          // Center of rotation relative to current_position
6102
+  uint8_t clockwise       // Clockwise?
6103
+) {
6104
+
6105
+  float radius = hypot(offset[X_AXIS], offset[Y_AXIS]),
6106
+        center_axis0 = current_position[X_AXIS] + offset[X_AXIS],
6107
+        center_axis1 = current_position[Y_AXIS] + offset[Y_AXIS],
6108
+        linear_travel = target[Z_AXIS] - current_position[Z_AXIS],
6109
+        extruder_travel = target[E_AXIS] - current_position[E_AXIS],
6110
+        r_axis0 = -offset[X_AXIS],  // Radius vector from center to current location
6111
+        r_axis1 = -offset[Y_AXIS],
6112
+        rt_axis0 = target[X_AXIS] - center_axis0,
6113
+        rt_axis1 = target[Y_AXIS] - center_axis1;
6114
+  
6115
+  // CCW angle of rotation between position and target from the circle center. Only one atan2() trig computation required.
6116
+  float angular_travel = atan2(r_axis0*rt_axis1-r_axis1*rt_axis0, r_axis0*rt_axis0+r_axis1*rt_axis1);
6117
+  if (angular_travel < 0) { angular_travel += RADIANS(360); }
6118
+  if (clockwise) { angular_travel -= RADIANS(360); }
6119
+  
6120
+  // Make a circle if the angular rotation is 0
6121
+  if (current_position[X_AXIS] == target[X_AXIS] && current_position[Y_AXIS] == target[Y_AXIS] && angular_travel == 0)
6122
+    angular_travel += RADIANS(360);
6123
+  
6124
+  float mm_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
6125
+  if (mm_of_travel < 0.001) { return; }
6126
+  uint16_t segments = floor(mm_of_travel / MM_PER_ARC_SEGMENT);
6127
+  if (segments == 0) segments = 1;
6128
+  
6129
+  float theta_per_segment = angular_travel/segments;
6130
+  float linear_per_segment = linear_travel/segments;
6131
+  float extruder_per_segment = extruder_travel/segments;
6132
+  
6133
+  /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
6134
+     and phi is the angle of rotation. Based on the solution approach by Jens Geisler.
6135
+         r_T = [cos(phi) -sin(phi);
6136
+                sin(phi)  cos(phi] * r ;
6137
+     
6138
+     For arc generation, the center of the circle is the axis of rotation and the radius vector is 
6139
+     defined from the circle center to the initial position. Each line segment is formed by successive
6140
+     vector rotations. This requires only two cos() and sin() computations to form the rotation
6141
+     matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
6142
+     all double numbers are single precision on the Arduino. (True double precision will not have
6143
+     round off issues for CNC applications.) Single precision error can accumulate to be greater than
6144
+     tool precision in some cases. Therefore, arc path correction is implemented. 
6145
+
6146
+     Small angle approximation may be used to reduce computation overhead further. This approximation
6147
+     holds for everything, but very small circles and large MM_PER_ARC_SEGMENT values. In other words,
6148
+     theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
6149
+     to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for 
6150
+     numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
6151
+     issue for CNC machines with the single precision Arduino calculations.
6152
+     
6153
+     This approximation also allows plan_arc to immediately insert a line segment into the planner 
6154
+     without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
6155
+     a correction, the planner should have caught up to the lag caused by the initial plan_arc overhead. 
6156
+     This is important when there are successive arc motions. 
6157
+  */
6158
+  // Vector rotation matrix values
6159
+  float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
6160
+  float sin_T = theta_per_segment;
6161
+  
6162
+  float arc_target[NUM_AXIS];
6163
+  float sin_Ti;
6164
+  float cos_Ti;
6165
+  float r_axisi;
6166
+  uint16_t i;
6167
+  int8_t count = 0;
6168
+
6169
+  // Initialize the linear axis
6170
+  arc_target[Z_AXIS] = current_position[Z_AXIS];
6171
+  
6172
+  // Initialize the extruder axis
6173
+  arc_target[E_AXIS] = current_position[E_AXIS];
6174
+
6175
+  float feed_rate = feedrate*feedrate_multiplier/60/100.0;
6176
+
6177
+  for (i = 1; i < segments; i++) { // Increment (segments-1)
6178
+
6179
+    if (count < N_ARC_CORRECTION) {
6180
+      // Apply vector rotation matrix to previous r_axis0 / 1
6181
+      r_axisi = r_axis0*sin_T + r_axis1*cos_T;
6182
+      r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
6183
+      r_axis1 = r_axisi;
6184
+      count++;
6185
+    }
6186
+    else {
6187
+      // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
6188
+      // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
6189
+      cos_Ti = cos(i*theta_per_segment);
6190
+      sin_Ti = sin(i*theta_per_segment);
6191
+      r_axis0 = -offset[X_AXIS]*cos_Ti + offset[Y_AXIS]*sin_Ti;
6192
+      r_axis1 = -offset[X_AXIS]*sin_Ti - offset[Y_AXIS]*cos_Ti;
6193
+      count = 0;
6194
+    }
6195
+
6196
+    // Update arc_target location
6197
+    arc_target[X_AXIS] = center_axis0 + r_axis0;
6198
+    arc_target[Y_AXIS] = center_axis1 + r_axis1;
6199
+    arc_target[Z_AXIS] += linear_per_segment;
6200
+    arc_target[E_AXIS] += extruder_per_segment;
6201
+
6202
+    clamp_to_software_endstops(arc_target);
6203
+
6204
+    #if defined(DELTA) || defined(SCARA)
6205
+      calculate_delta(arc_target);
6206
+      #ifdef ENABLE_AUTO_BED_LEVELING
6207
+        adjust_delta(arc_target);
6208
+      #endif
6209
+      plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], arc_target[E_AXIS], feed_rate, active_extruder);
6210
+    #else
6211
+      plan_buffer_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], arc_target[E_AXIS], feed_rate, active_extruder);
6212
+    #endif
6213
+  }
6214
+
6215
+  // Ensure last segment arrives at target location.
6216
+  #if defined(DELTA) || defined(SCARA)
6217
+    calculate_delta(target);
6218
+    #ifdef ENABLE_AUTO_BED_LEVELING
6219
+      adjust_delta(target);
6220
+    #endif
6221
+    plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], target[E_AXIS], feed_rate, active_extruder);
6222
+  #else
6223
+    plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], feed_rate, active_extruder);
6224
+  #endif
6225
+
6226
+  // As far as the parser is concerned, the position is now == target. In reality the
6227
+  // motion control system might still be processing the action and the real tool position
6228
+  // in any intermediate location.
6229
+  set_current_to_destination();
6230
+}
6231
+
6232 6232
 #if HAS_CONTROLLERFAN
6233 6233
 
6234 6234
   void controllerFan() {

読み込み中…
キャンセル
保存