Junction Deviation jerk limiting option
This commit is contained in:
parent
0436e16fb2
commit
4d4bf7897d
@ -84,7 +84,7 @@ script:
|
|||||||
- opt_set TEMP_SENSOR_4 999
|
- opt_set TEMP_SENSOR_4 999
|
||||||
- opt_set TEMP_SENSOR_BED 1
|
- opt_set TEMP_SENSOR_BED 1
|
||||||
- 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
|
- 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
|
||||||
- opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME
|
- opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME JUNCTION_DEVIATION
|
||||||
- build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
|
- build_marlin_pio ${TRAVIS_BUILD_DIR} ${TEST_PLATFORM}
|
||||||
#
|
#
|
||||||
# Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language
|
# Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language
|
||||||
|
@ -431,6 +431,15 @@
|
|||||||
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
|
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
|
||||||
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
|
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use Junction Deviation instead of traditional Jerk Limiting
|
||||||
|
//
|
||||||
|
//#define JUNCTION_DEVIATION
|
||||||
|
#if ENABLED(JUNCTION_DEVIATION)
|
||||||
|
#define JUNCTION_DEVIATION_FACTOR 0.02
|
||||||
|
//#define JUNCTION_DEVIATION_INCLUDE_E
|
||||||
|
#endif
|
||||||
|
|
||||||
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
|
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
|
||||||
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
|
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
|
||||||
|
|
||||||
|
@ -431,6 +431,15 @@
|
|||||||
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
|
// if unwanted behavior is observed on a user's machine when running at very slow speeds.
|
||||||
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
|
#define MINIMUM_PLANNER_SPEED 0.05 // (mm/sec)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use Junction Deviation instead of traditional Jerk Limiting
|
||||||
|
//
|
||||||
|
//#define JUNCTION_DEVIATION
|
||||||
|
#if ENABLED(JUNCTION_DEVIATION)
|
||||||
|
#define JUNCTION_DEVIATION_FACTOR 0.02
|
||||||
|
//#define JUNCTION_DEVIATION_INCLUDE_E
|
||||||
|
#endif
|
||||||
|
|
||||||
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
|
// Microstep setting (Only functional when stepper driver microstep pins are connected to MCU.
|
||||||
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
|
#define MICROSTEP_MODES {16,16,16,16,16} // [1,2,4,8,16]
|
||||||
|
|
||||||
|
@ -787,8 +787,8 @@ void Planner::calculate_trapezoid_for_block(block_t* const block, const float &e
|
|||||||
|
|
||||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||||
// Jerk controlled speed requires to express speed versus time, NOT steps
|
// Jerk controlled speed requires to express speed versus time, NOT steps
|
||||||
uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * HAL_STEPPER_TIMER_RATE,
|
uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * (HAL_STEPPER_TIMER_RATE),
|
||||||
deceleration_time = ((float)(cruise_rate - final_rate) / accel) * HAL_STEPPER_TIMER_RATE;
|
deceleration_time = ((float)(cruise_rate - final_rate) / accel) * (HAL_STEPPER_TIMER_RATE);
|
||||||
|
|
||||||
// And to offload calculations from the ISR, we also calculate the inverse of those times here
|
// And to offload calculations from the ISR, we also calculate the inverse of those times here
|
||||||
uint32_t acceleration_time_inverse = get_period_inverse(acceleration_time);
|
uint32_t acceleration_time_inverse = get_period_inverse(acceleration_time);
|
||||||
@ -1864,57 +1864,86 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Initial limit on the segment entry velocity
|
float vmax_junction; // Initial limit on the segment entry velocity
|
||||||
float vmax_junction;
|
|
||||||
|
|
||||||
#if 0 // Use old jerk for now
|
#if ENABLED(JUNCTION_DEVIATION)
|
||||||
|
|
||||||
float junction_deviation = 0.1;
|
/**
|
||||||
|
* Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
|
||||||
|
* Let a circle be tangent to both previous and current path line segments, where the junction
|
||||||
|
* deviation is defined as the distance from the junction to the closest edge of the circle,
|
||||||
|
* colinear with the circle center. The circular segment joining the two paths represents the
|
||||||
|
* path of centripetal acceleration. Solve for max velocity based on max acceleration about the
|
||||||
|
* radius of the circle, defined indirectly by junction deviation. This may be also viewed as
|
||||||
|
* path width or max_jerk in the previous Grbl version. This approach does not actually deviate
|
||||||
|
* from path, but used as a robust way to compute cornering speeds, as it takes into account the
|
||||||
|
* nonlinearities of both the junction angle and junction velocity.
|
||||||
|
*
|
||||||
|
* NOTE: If the junction deviation value is finite, Grbl executes the motions in an exact path
|
||||||
|
* mode (G61). If the junction deviation value is zero, Grbl will execute the motion in an exact
|
||||||
|
* stop mode (G61.1) manner. In the future, if continuous mode (G64) is desired, the math here
|
||||||
|
* is exactly the same. Instead of motioning all the way to junction point, the machine will
|
||||||
|
* just follow the arc circle defined here. The Arduino doesn't have the CPU cycles to perform
|
||||||
|
* a continuous mode path, but ARM-based microcontrollers most certainly do.
|
||||||
|
*
|
||||||
|
* NOTE: The max junction speed is a fixed value, since machine acceleration limits cannot be
|
||||||
|
* changed dynamically during operation nor can the line move geometry. This must be kept in
|
||||||
|
* memory in the event of a feedrate override changing the nominal speeds of blocks, which can
|
||||||
|
* change the overall maximum entry speed conditions of all blocks.
|
||||||
|
*/
|
||||||
|
|
||||||
// Compute path unit vector
|
// Unit vector of previous path line segment
|
||||||
double unit_vec[XYZ] = {
|
static float previous_unit_vec[
|
||||||
|
#if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
|
||||||
|
XYZE
|
||||||
|
#else
|
||||||
|
XYZ
|
||||||
|
#endif
|
||||||
|
];
|
||||||
|
|
||||||
|
float unit_vec[] = {
|
||||||
delta_mm[A_AXIS] * inverse_millimeters,
|
delta_mm[A_AXIS] * inverse_millimeters,
|
||||||
delta_mm[B_AXIS] * inverse_millimeters,
|
delta_mm[B_AXIS] * inverse_millimeters,
|
||||||
delta_mm[C_AXIS] * inverse_millimeters
|
delta_mm[C_AXIS] * inverse_millimeters
|
||||||
|
#if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
|
||||||
|
, delta_mm[E_AXIS] * inverse_millimeters
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
|
|
||||||
|
|
||||||
Let a circle be tangent to both previous and current path line segments, where the junction
|
|
||||||
deviation is defined as the distance from the junction to the closest edge of the circle,
|
|
||||||
collinear with the circle center.
|
|
||||||
|
|
||||||
The circular segment joining the two paths represents the path of centripetal acceleration.
|
|
||||||
Solve for max velocity based on max acceleration about the radius of the circle, defined
|
|
||||||
indirectly by junction deviation.
|
|
||||||
|
|
||||||
This may be also viewed as path width or max_jerk in the previous grbl version. This approach
|
|
||||||
does not actually deviate from path, but used as a robust way to compute cornering speeds, as
|
|
||||||
it takes into account the nonlinearities of both the junction angle and junction velocity.
|
|
||||||
*/
|
|
||||||
|
|
||||||
vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
|
|
||||||
|
|
||||||
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
|
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
|
||||||
if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
|
if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
|
||||||
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
|
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
|
||||||
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
|
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
|
||||||
const float cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
|
float junction_cos_theta = -previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
|
||||||
- previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
|
-previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
|
||||||
- previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS];
|
-previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS]
|
||||||
// Skip and use default max junction speed for 0 degree acute junction.
|
#if ENABLED(JUNCTION_DEVIATION_INCLUDE_E)
|
||||||
if (cos_theta < 0.95) {
|
-previous_unit_vec[E_AXIS] * unit_vec[E_AXIS]
|
||||||
vmax_junction = min(previous_nominal_speed, block->nominal_speed);
|
|
||||||
// Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
|
|
||||||
if (cos_theta > -0.95) {
|
|
||||||
// Compute maximum junction velocity based on maximum acceleration and junction deviation
|
|
||||||
float sin_theta_d2 = SQRT(0.5 * (1.0 - cos_theta)); // Trig half angle identity. Always positive.
|
|
||||||
NOMORE(vmax_junction, SQRT(block->acceleration * junction_deviation * sin_theta_d2 / (1.0 - sin_theta_d2)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
;
|
||||||
|
|
||||||
|
// NOTE: Computed without any expensive trig, sin() or acos(), by trig half angle identity of cos(theta).
|
||||||
|
if (junction_cos_theta > 0.999999) {
|
||||||
|
// For a 0 degree acute junction, just set minimum junction speed.
|
||||||
|
vmax_junction = MINIMUM_PLANNER_SPEED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
junction_cos_theta = max(junction_cos_theta, -0.999999); // Check for numerical round-off to avoid divide by zero.
|
||||||
|
const float sin_theta_d2 = SQRT(0.5 * (1.0 - junction_cos_theta)); // Trig half angle identity. Always positive.
|
||||||
|
|
||||||
|
// TODO: Technically, the acceleration used in calculation needs to be limited by the minimum of the
|
||||||
|
// two junctions. However, this shouldn't be a significant problem except in extreme circumstances.
|
||||||
|
vmax_junction = SQRT((block->acceleration * JUNCTION_DEVIATION_FACTOR * sin_theta_d2) / (1.0 - sin_theta_d2));
|
||||||
|
}
|
||||||
|
|
||||||
|
vmax_junction = MIN3(vmax_junction, block->nominal_speed, previous_nominal_speed);
|
||||||
|
}
|
||||||
|
else // Init entry speed to zero. Assume it starts from rest. Planner will correct this later.
|
||||||
|
vmax_junction = 0.0;
|
||||||
|
|
||||||
|
COPY(previous_unit_vec, unit_vec);
|
||||||
|
|
||||||
|
#else // Classic Jerk Limiting
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapted from Průša MKS firmware
|
* Adapted from Průša MKS firmware
|
||||||
@ -1988,6 +2017,9 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
|
|||||||
else
|
else
|
||||||
vmax_junction = safe_speed;
|
vmax_junction = safe_speed;
|
||||||
|
|
||||||
|
previous_safe_speed = safe_speed;
|
||||||
|
#endif // Classic Jerk Limiting
|
||||||
|
|
||||||
// Max entry speed of this block equals the max exit speed of the previous block.
|
// Max entry speed of this block equals the max exit speed of the previous block.
|
||||||
block->max_entry_speed = vmax_junction;
|
block->max_entry_speed = vmax_junction;
|
||||||
|
|
||||||
@ -2010,7 +2042,6 @@ void Planner::_buffer_steps(const int32_t (&target)[XYZE]
|
|||||||
// Update previous path unit_vector and nominal speed
|
// Update previous path unit_vector and nominal speed
|
||||||
COPY(previous_speed, current_speed);
|
COPY(previous_speed, current_speed);
|
||||||
previous_nominal_speed = block->nominal_speed;
|
previous_nominal_speed = block->nominal_speed;
|
||||||
previous_safe_speed = safe_speed;
|
|
||||||
|
|
||||||
// Move buffer head
|
// Move buffer head
|
||||||
block_buffer_head = next_buffer_head;
|
block_buffer_head = next_buffer_head;
|
||||||
|
Loading…
Reference in New Issue
Block a user