|
@@ -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;
|