Explorar el Código

Junction Deviation jerk limiting option

Scott Lahteine hace 6 años
padre
commit
4d4bf7897d

+ 1
- 1
.travis.yml Ver fichero

@@ -84,7 +84,7 @@ script:
84 84
   - opt_set TEMP_SENSOR_4 999
85 85
   - opt_set TEMP_SENSOR_BED 1
86 86
   - opt_enable AUTO_BED_LEVELING_UBL RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT EEPROM_SETTINGS EEPROM_CHITCHAT G3D_PANEL SKEW_CORRECTION
87
-  - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME
87
+  - opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME JUNCTION_DEVIATION
88 88
   - build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
89 89
   #
90 90
   # Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language

+ 9
- 0
Marlin/Configuration_adv.h Ver fichero

@@ -431,6 +431,15 @@
431 431
 // if unwanted behavior is observed on a user's machine when running at very slow speeds.
432 432
 #define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
433 433
 
434
+//
435
+// Use Junction Deviation instead of traditional Jerk Limiting
436
+//
437
+//#define JUNCTION_DEVIATION
438
+#if ENABLED(JUNCTION_DEVIATION)
439
+  #define JUNCTION_DEVIATION_FACTOR 0.02
440
+  //#define JUNCTION_DEVIATION_INCLUDE_E
441
+#endif
442
+
434 443
 // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
435 444
 #define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
436 445
 

+ 9
- 0
Marlin/src/config/default/Configuration_adv.h Ver fichero

@@ -431,6 +431,15 @@
431 431
 // if unwanted behavior is observed on a user's machine when running at very slow speeds.
432 432
 #define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
433 433
 
434
+//
435
+// Use Junction Deviation instead of traditional Jerk Limiting
436
+//
437
+//#define JUNCTION_DEVIATION
438
+#if ENABLED(JUNCTION_DEVIATION)
439
+  #define JUNCTION_DEVIATION_FACTOR 0.02
440
+  //#define JUNCTION_DEVIATION_INCLUDE_E
441
+#endif
442
+
434 443
 // Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
435 444
 #define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
436 445
 

+ 133
- 102
Marlin/src/module/planner.cpp Ver fichero

@@ -787,8 +787,8 @@ void Planner::calculate_trapezoid_for_block(block_t* const block, const float &e
787 787
 
788 788
   #if ENABLED(BEZIER_JERK_CONTROL)
789 789
     // Jerk controlled speed requires to express speed versus time, NOT steps
790
-    uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * HAL_STEPPER_TIMER_RATE,
791
-             deceleration_time = ((float)(cruise_rate - final_rate) / accel) * HAL_STEPPER_TIMER_RATE;
790
+    uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * (HAL_STEPPER_TIMER_RATE),
791
+             deceleration_time = ((float)(cruise_rate - final_rate) / accel) * (HAL_STEPPER_TIMER_RATE);
792 792
 
793 793
     // And to offload calculations from the ISR, we also calculate the inverse of those times here
794 794
     uint32_t acceleration_time_inverse = get_period_inverse(acceleration_time);
@@ -1864,129 +1864,161 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
1864 1864
     }
1865 1865
   #endif
1866 1866
 
1867
-  // Initial limit on the segment entry velocity
1868
-  float vmax_junction;
1869
-
1870
-  #if 0  // Use old jerk for now
1867
+  float vmax_junction; // Initial limit on the segment entry velocity
1868
+
1869
+  #if ENABLED(JUNCTION_DEVIATION)
1870
+
1871
+    /**
1872
+     * Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
1873
+     * Let a circle be tangent to both previous and current path line segments, where the junction 
1874
+     * deviation is defined as the distance from the junction to the closest edge of the circle, 
1875
+     * colinear with the circle center. The circular segment joining the two paths represents the 
1876
+     * path of centripetal acceleration. Solve for max velocity based on max acceleration about the
1877
+     * radius of the circle, defined indirectly by junction deviation. This may be also viewed as 
1878
+     * path width or max_jerk in the previous Grbl version. This approach does not actually deviate 
1879
+     * from path, but used as a robust way to compute cornering speeds, as it takes into account the
1880
+     * nonlinearities of both the junction angle and junction velocity.
1881
+     *
1882
+     * NOTE: If the junction deviation value is finite, Grbl executes the motions in an exact path 
1883
+     * mode (G61). If the junction deviation value is zero, Grbl will execute the motion in an exact
1884
+     * stop mode (G61.1) manner. In the future, if continuous mode (G64) is desired, the math here
1885
+     * is exactly the same. Instead of motioning all the way to junction point, the machine will
1886
+     * just follow the arc circle defined here. The Arduino doesn't have the CPU cycles to perform
1887
+     * a continuous mode path, but ARM-based microcontrollers most certainly do. 
1888
+     * 
1889
+     * NOTE: The max junction speed is a fixed value, since machine acceleration limits cannot be
1890
+     * changed dynamically during operation nor can the line move geometry. This must be kept in
1891
+     * memory in the event of a feedrate override changing the nominal speeds of blocks, which can 
1892
+     * change the overall maximum entry speed conditions of all blocks.
1893
+     */
1871 1894
 
1872
-    float junction_deviation = 0.1;
1895
+    // Unit vector of previous path line segment
1896
+    static float previous_unit_vec[
1897
+      #if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
1898
+        XYZE
1899
+      #else
1900
+        XYZ
1901
+      #endif
1902
+    ];
1873 1903
 
1874
-    // Compute path unit vector
1875
-    double unit_vec[XYZ] = {
1904
+    float unit_vec[] = {
1876 1905
       delta_mm[A_AXIS] * inverse_millimeters,
1877 1906
       delta_mm[B_AXIS] * inverse_millimeters,
1878 1907
       delta_mm[C_AXIS] * inverse_millimeters
1908
+      #if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
1909
+        , delta_mm[E_AXIS] * inverse_millimeters
1910
+      #endif
1879 1911
     };
1880 1912
 
1881
-    /*
1882
-       Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
1883
-
1884
-       Let a circle be tangent to both previous and current path line segments, where the junction
1885
-       deviation is defined as the distance from the junction to the closest edge of the circle,
1886
-       collinear with the circle center.
1887
-
1888
-       The circular segment joining the two paths represents the path of centripetal acceleration.
1889
-       Solve for max velocity based on max acceleration about the radius of the circle, defined
1890
-       indirectly by junction deviation.
1891
-
1892
-       This may be also viewed as path width or max_jerk in the previous grbl version. This approach
1893
-       does not actually deviate from path, but used as a robust way to compute cornering speeds, as
1894
-       it takes into account the nonlinearities of both the junction angle and junction velocity.
1895
-     */
1896
-
1897
-    vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
1898
-
1899 1913
     // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
1900 1914
     if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
1901 1915
       // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
1902 1916
       // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
1903
-      const float cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
1904
-                              - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
1905
-                              - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS];
1906
-      // Skip and use default max junction speed for 0 degree acute junction.
1907
-      if (cos_theta < 0.95) {
1908
-        vmax_junction = min(previous_nominal_speed, block->nominal_speed);
1909
-        // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
1910
-        if (cos_theta > -0.95) {
1911
-          // Compute maximum junction velocity based on maximum acceleration and junction deviation
1912
-          float sin_theta_d2 = SQRT(0.5 * (1.0 - cos_theta)); // Trig half angle identity. Always positive.
1913
-          NOMORE(vmax_junction, SQRT(block->acceleration * junction_deviation * sin_theta_d2 / (1.0 - sin_theta_d2)));
1914
-        }
1917
+      float junction_cos_theta = -previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
1918
+                                 -previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
1919
+                                 -previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS]
1920
+                                  #if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
1921
+                                    -previous_unit_vec[E_AXIS] * unit_vec[E_AXIS]
1922
+                                  #endif
1923
+                                ;
1924
+
1925
+      // NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
1926
+      if (junction_cos_theta > 0.999999) {
1927
+        // For a 0 degree acute junction, just set minimum junction speed.
1928
+        vmax_junction = MINIMUM_PLANNER_SPEED;
1929
+      }
1930
+      else {
1931
+        junction_cos_theta = max(junction_cos_theta, -0.999999); // Check for numerical round-off to avoid divide by zero.
1932
+        const float sin_theta_d2 = SQRT(0.5 * (1.0 - junction_cos_theta)); // Trig half angle identity. Always positive.
1933
+
1934
+        // TODO: Technically, the acceleration used in calculation needs to be limited by the minimum of the
1935
+        // two junctions. However, this shouldn't be a significant problem except in extreme circumstances.
1936
+        vmax_junction = SQRT((block->acceleration * JUNCTION_DEVIATION_FACTOR * sin_theta_d2) / (1.0 - sin_theta_d2));
1915 1937
       }
1938
+
1939
+      vmax_junction = MIN3(vmax_junction, block->nominal_speed, previous_nominal_speed);
1916 1940
     }
1917
-  #endif
1941
+    else // Init entry speed to zero. Assume it starts from rest. Planner will correct this later.
1942
+      vmax_junction = 0.0;
1918 1943
 
1919
-  /**
1920
-   * Adapted from Průša MKS firmware
1921
-   * https://github.com/prusa3d/Prusa-Firmware
1922
-   *
1923
-   * Start with a safe speed (from which the machine may halt to stop immediately).
1924
-   */
1944
+    COPY(previous_unit_vec, unit_vec);
1925 1945
 
1926
-  // Exit speed limited by a jerk to full halt of a previous last segment
1927
-  static float previous_safe_speed;
1946
+  #else // Classic Jerk Limiting
1928 1947
 
1929
-  float safe_speed = block->nominal_speed;
1930
-  uint8_t limited = 0;
1931
-  LOOP_XYZE(i) {
1932
-    const float jerk = FABS(current_speed[i]), maxj = max_jerk[i];
1933
-    if (jerk > maxj) {
1934
-      if (limited) {
1935
-        const float mjerk = maxj * block->nominal_speed;
1936
-        if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk;
1937
-      }
1938
-      else {
1939
-        ++limited;
1940
-        safe_speed = maxj;
1948
+    /**
1949
+     * Adapted from Průša MKS firmware
1950
+     * https://github.com/prusa3d/Prusa-Firmware
1951
+     *
1952
+     * Start with a safe speed (from which the machine may halt to stop immediately).
1953
+     */
1954
+
1955
+    // Exit speed limited by a jerk to full halt of a previous last segment
1956
+    static float previous_safe_speed;
1957
+
1958
+    float safe_speed = block->nominal_speed;
1959
+    uint8_t limited = 0;
1960
+    LOOP_XYZE(i) {
1961
+      const float jerk = FABS(current_speed[i]), maxj = max_jerk[i];
1962
+      if (jerk > maxj) {
1963
+        if (limited) {
1964
+          const float mjerk = maxj * block->nominal_speed;
1965
+          if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk;
1966
+        }
1967
+        else {
1968
+          ++limited;
1969
+          safe_speed = maxj;
1970
+        }
1941 1971
       }
1942 1972
     }
1943
-  }
1944 1973
 
1945
-  if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
1946
-    // Estimate a maximum velocity allowed at a joint of two successive segments.
1947
-    // If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
1948
-    // then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
1949
-
1950
-    // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
1951
-    // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
1952
-    vmax_junction = min(block->nominal_speed, previous_nominal_speed);
1953
-
1954
-    // Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
1955
-    float v_factor = 1;
1956
-    limited = 0;
1957
-
1958
-    // Now limit the jerk in all axes.
1959
-    const float smaller_speed_factor = vmax_junction / previous_nominal_speed;
1960
-    LOOP_XYZE(axis) {
1961
-      // Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
1962
-      float v_exit = previous_speed[axis] * smaller_speed_factor,
1963
-            v_entry = current_speed[axis];
1964
-      if (limited) {
1965
-        v_exit *= v_factor;
1966
-        v_entry *= v_factor;
1967
-      }
1974
+    if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
1975
+      // Estimate a maximum velocity allowed at a joint of two successive segments.
1976
+      // If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
1977
+      // then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
1978
+
1979
+      // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
1980
+      // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
1981
+      vmax_junction = min(block->nominal_speed, previous_nominal_speed);
1982
+
1983
+      // Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
1984
+      float v_factor = 1;
1985
+      limited = 0;
1986
+
1987
+      // Now limit the jerk in all axes.
1988
+      const float smaller_speed_factor = vmax_junction / previous_nominal_speed;
1989
+      LOOP_XYZE(axis) {
1990
+        // Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
1991
+        float v_exit = previous_speed[axis] * smaller_speed_factor,
1992
+              v_entry = current_speed[axis];
1993
+        if (limited) {
1994
+          v_exit *= v_factor;
1995
+          v_entry *= v_factor;
1996
+        }
1968 1997
 
1969
-      // Calculate jerk depending on whether the axis is coasting in the same direction or reversing.
1970
-      const float jerk = (v_exit > v_entry)
1971
-          ? //                                  coasting             axis reversal
1972
-            ( (v_entry > 0 || v_exit < 0) ? (v_exit - v_entry) : max(v_exit, -v_entry) )
1973
-          : // v_exit <= v_entry                coasting             axis reversal
1974
-            ( (v_entry < 0 || v_exit > 0) ? (v_entry - v_exit) : max(-v_exit, v_entry) );
1998
+        // Calculate jerk depending on whether the axis is coasting in the same direction or reversing.
1999
+        const float jerk = (v_exit > v_entry)
2000
+            ? //                                  coasting             axis reversal
2001
+              ( (v_entry > 0 || v_exit < 0) ? (v_exit - v_entry) : max(v_exit, -v_entry) )
2002
+            : // v_exit <= v_entry                coasting             axis reversal
2003
+              ( (v_entry < 0 || v_exit > 0) ? (v_entry - v_exit) : max(-v_exit, v_entry) );
1975 2004
 
1976
-      if (jerk > max_jerk[axis]) {
1977
-        v_factor *= max_jerk[axis] / jerk;
1978
-        ++limited;
2005
+        if (jerk > max_jerk[axis]) {
2006
+          v_factor *= max_jerk[axis] / jerk;
2007
+          ++limited;
2008
+        }
1979 2009
       }
2010
+      if (limited) vmax_junction *= v_factor;
2011
+      // Now the transition velocity is known, which maximizes the shared exit / entry velocity while
2012
+      // respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
2013
+      const float vmax_junction_threshold = vmax_junction * 0.99f;
2014
+      if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold)
2015
+        vmax_junction = safe_speed;
1980 2016
     }
1981
-    if (limited) vmax_junction *= v_factor;
1982
-    // Now the transition velocity is known, which maximizes the shared exit / entry velocity while
1983
-    // respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
1984
-    const float vmax_junction_threshold = vmax_junction * 0.99f;
1985
-    if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold)
2017
+    else
1986 2018
       vmax_junction = safe_speed;
1987
-  }
1988
-  else
1989
-    vmax_junction = safe_speed;
2019
+  
2020
+    previous_safe_speed = safe_speed;
2021
+  #endif // Classic Jerk Limiting
1990 2022
 
1991 2023
   // Max entry speed of this block equals the max exit speed of the previous block.
1992 2024
   block->max_entry_speed = vmax_junction;
@@ -2010,7 +2042,6 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
2010 2042
   // Update previous path unit_vector and nominal speed
2011 2043
   COPY(previous_speed, current_speed);
2012 2044
   previous_nominal_speed = block->nominal_speed;
2013
-  previous_safe_speed = safe_speed;
2014 2045
 
2015 2046
   // Move buffer head
2016 2047
   block_buffer_head = next_buffer_head;

Loading…
Cancelar
Guardar