|
@@ -85,8 +85,8 @@ float Planner::max_feedrate_mm_s[NUM_AXIS], // Max speeds in mm per second
|
85
|
85
|
Planner::axis_steps_per_mm[NUM_AXIS],
|
86
|
86
|
Planner::steps_to_mm[NUM_AXIS];
|
87
|
87
|
|
88
|
|
-unsigned long Planner::max_acceleration_steps_per_s2[NUM_AXIS],
|
89
|
|
- Planner::max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software
|
|
88
|
+uint32_t Planner::max_acceleration_steps_per_s2[NUM_AXIS],
|
|
89
|
+ Planner::max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software
|
90
|
90
|
|
91
|
91
|
millis_t Planner::min_segment_time;
|
92
|
92
|
float Planner::min_feedrate_mm_s,
|
|
@@ -145,17 +145,19 @@ void Planner::init() {
|
145
|
145
|
#endif
|
146
|
146
|
}
|
147
|
147
|
|
|
148
|
+#define MINIMAL_STEP_RATE 120
|
|
149
|
+
|
148
|
150
|
/**
|
149
|
151
|
* Calculate trapezoid parameters, multiplying the entry- and exit-speeds
|
150
|
152
|
* by the provided factors.
|
151
|
153
|
*/
|
152
|
|
-void Planner::calculate_trapezoid_for_block(block_t* block, float entry_factor, float exit_factor) {
|
|
154
|
+void Planner::calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor) {
|
153
|
155
|
uint32_t initial_rate = ceil(block->nominal_rate * entry_factor),
|
154
|
156
|
final_rate = ceil(block->nominal_rate * exit_factor); // (steps per second)
|
155
|
157
|
|
156
|
158
|
// Limit minimal step rate (Otherwise the timer will overflow.)
|
157
|
|
- NOLESS(initial_rate, 120);
|
158
|
|
- NOLESS(final_rate, 120);
|
|
159
|
+ NOLESS(initial_rate, MINIMAL_STEP_RATE);
|
|
160
|
+ NOLESS(final_rate, MINIMAL_STEP_RATE);
|
159
|
161
|
|
160
|
162
|
int32_t accel = block->acceleration_steps_per_s2,
|
161
|
163
|
accelerate_steps = ceil(estimate_acceleration_distance(initial_rate, block->nominal_rate, accel)),
|
|
@@ -172,13 +174,9 @@ void Planner::calculate_trapezoid_for_block(block_t* block, float entry_factor,
|
172
|
174
|
plateau_steps = 0;
|
173
|
175
|
}
|
174
|
176
|
|
175
|
|
- #if ENABLED(ADVANCE)
|
176
|
|
- volatile int32_t initial_advance = block->advance * sq(entry_factor),
|
177
|
|
- final_advance = block->advance * sq(exit_factor);
|
178
|
|
- #endif // ADVANCE
|
179
|
|
-
|
180
|
177
|
// block->accelerate_until = accelerate_steps;
|
181
|
178
|
// block->decelerate_after = accelerate_steps+plateau_steps;
|
|
179
|
+
|
182
|
180
|
CRITICAL_SECTION_START; // Fill variables used by the stepper in a critical section
|
183
|
181
|
if (!block->busy) { // Don't update variables if block is busy.
|
184
|
182
|
block->accelerate_until = accelerate_steps;
|
|
@@ -186,8 +184,8 @@ void Planner::calculate_trapezoid_for_block(block_t* block, float entry_factor,
|
186
|
184
|
block->initial_rate = initial_rate;
|
187
|
185
|
block->final_rate = final_rate;
|
188
|
186
|
#if ENABLED(ADVANCE)
|
189
|
|
- block->initial_advance = initial_advance;
|
190
|
|
- block->final_advance = final_advance;
|
|
187
|
+ block->initial_advance = block->advance * sq(entry_factor);
|
|
188
|
+ block->final_advance = block->advance * sq(exit_factor);
|
191
|
189
|
#endif
|
192
|
190
|
}
|
193
|
191
|
CRITICAL_SECTION_END;
|
|
@@ -203,29 +201,20 @@ void Planner::calculate_trapezoid_for_block(block_t* block, float entry_factor,
|
203
|
201
|
|
204
|
202
|
|
205
|
203
|
// The kernel called by recalculate() when scanning the plan from last to first entry.
|
206
|
|
-void Planner::reverse_pass_kernel(block_t* current, block_t* next) {
|
207
|
|
- if (!current) return;
|
208
|
|
-
|
209
|
|
- if (next) {
|
210
|
|
- // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
|
211
|
|
- // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and
|
212
|
|
- // check for maximum allowable speed reductions to ensure maximum possible planned speed.
|
213
|
|
- float max_entry_speed = current->max_entry_speed;
|
214
|
|
- if (current->entry_speed != max_entry_speed) {
|
215
|
|
-
|
216
|
|
- // If nominal length true, max junction speed is guaranteed to be reached. Only compute
|
217
|
|
- // for max allowable speed if block is decelerating and nominal length is false.
|
218
|
|
- if (!current->nominal_length_flag && max_entry_speed > next->entry_speed) {
|
219
|
|
- current->entry_speed = min(max_entry_speed,
|
220
|
|
- max_allowable_speed(-current->acceleration, next->entry_speed, current->millimeters));
|
221
|
|
- }
|
222
|
|
- else {
|
223
|
|
- current->entry_speed = max_entry_speed;
|
224
|
|
- }
|
225
|
|
- current->recalculate_flag = true;
|
226
|
|
-
|
227
|
|
- }
|
228
|
|
- } // Skip last block. Already initialized and set for recalculation.
|
|
204
|
+void Planner::reverse_pass_kernel(block_t* const current, const block_t *next) {
|
|
205
|
+ if (!current || !next) return;
|
|
206
|
+ // If entry speed is already at the maximum entry speed, no need to recheck. Block is cruising.
|
|
207
|
+ // If not, block in state of acceleration or deceleration. Reset entry speed to maximum and
|
|
208
|
+ // check for maximum allowable speed reductions to ensure maximum possible planned speed.
|
|
209
|
+ float max_entry_speed = current->max_entry_speed;
|
|
210
|
+ if (current->entry_speed != max_entry_speed) {
|
|
211
|
+ // If nominal length true, max junction speed is guaranteed to be reached. Only compute
|
|
212
|
+ // for max allowable speed if block is decelerating and nominal length is false.
|
|
213
|
+ current->entry_speed = ((current->flag & BLOCK_FLAG_NOMINAL_LENGTH) || max_entry_speed <= next->entry_speed)
|
|
214
|
+ ? max_entry_speed
|
|
215
|
+ : min(max_entry_speed, max_allowable_speed(-current->acceleration, next->entry_speed, current->millimeters));
|
|
216
|
+ current->flag |= BLOCK_FLAG_RECALCULATE;
|
|
217
|
+ }
|
229
|
218
|
}
|
230
|
219
|
|
231
|
220
|
/**
|
|
@@ -239,12 +228,14 @@ void Planner::reverse_pass() {
|
239
|
228
|
block_t* block[3] = { NULL, NULL, NULL };
|
240
|
229
|
|
241
|
230
|
// Make a local copy of block_buffer_tail, because the interrupt can alter it
|
242
|
|
- CRITICAL_SECTION_START;
|
243
|
|
- uint8_t tail = block_buffer_tail;
|
244
|
|
- CRITICAL_SECTION_END
|
|
231
|
+ // Is a critical section REALLY needed for a single byte change?
|
|
232
|
+ //CRITICAL_SECTION_START;
|
|
233
|
+ uint8_t tail = block_buffer_tail;
|
|
234
|
+ //CRITICAL_SECTION_END
|
245
|
235
|
|
246
|
236
|
uint8_t b = BLOCK_MOD(block_buffer_head - 3);
|
247
|
237
|
while (b != tail) {
|
|
238
|
+ if (block[0] && (block[0]->flag & BLOCK_FLAG_START_FROM_FULL_HALT)) break;
|
248
|
239
|
b = prev_block_index(b);
|
249
|
240
|
block[2] = block[1];
|
250
|
241
|
block[1] = block[0];
|
|
@@ -255,21 +246,21 @@ void Planner::reverse_pass() {
|
255
|
246
|
}
|
256
|
247
|
|
257
|
248
|
// The kernel called by recalculate() when scanning the plan from first to last entry.
|
258
|
|
-void Planner::forward_pass_kernel(block_t* previous, block_t* current) {
|
|
249
|
+void Planner::forward_pass_kernel(const block_t* previous, block_t* const current) {
|
259
|
250
|
if (!previous) return;
|
260
|
251
|
|
261
|
252
|
// If the previous block is an acceleration block, but it is not long enough to complete the
|
262
|
253
|
// full speed change within the block, we need to adjust the entry speed accordingly. Entry
|
263
|
254
|
// speeds have already been reset, maximized, and reverse planned by reverse planner.
|
264
|
255
|
// If nominal length is true, max junction speed is guaranteed to be reached. No need to recheck.
|
265
|
|
- if (!previous->nominal_length_flag) {
|
|
256
|
+ if (!(previous->flag & BLOCK_FLAG_NOMINAL_LENGTH)) {
|
266
|
257
|
if (previous->entry_speed < current->entry_speed) {
|
267
|
258
|
float entry_speed = min(current->entry_speed,
|
268
|
259
|
max_allowable_speed(-previous->acceleration, previous->entry_speed, previous->millimeters));
|
269
|
260
|
// Check for junction speed change
|
270
|
261
|
if (current->entry_speed != entry_speed) {
|
271
|
262
|
current->entry_speed = entry_speed;
|
272
|
|
- current->recalculate_flag = true;
|
|
263
|
+ current->flag |= BLOCK_FLAG_RECALCULATE;
|
273
|
264
|
}
|
274
|
265
|
}
|
275
|
266
|
}
|
|
@@ -298,19 +289,18 @@ void Planner::forward_pass() {
|
298
|
289
|
*/
|
299
|
290
|
void Planner::recalculate_trapezoids() {
|
300
|
291
|
int8_t block_index = block_buffer_tail;
|
301
|
|
- block_t* current;
|
302
|
|
- block_t* next = NULL;
|
|
292
|
+ block_t *current, *next = NULL;
|
303
|
293
|
|
304
|
294
|
while (block_index != block_buffer_head) {
|
305
|
295
|
current = next;
|
306
|
296
|
next = &block_buffer[block_index];
|
307
|
297
|
if (current) {
|
308
|
298
|
// Recalculate if current block entry or exit junction speed has changed.
|
309
|
|
- if (current->recalculate_flag || next->recalculate_flag) {
|
|
299
|
+ if ((current->flag & BLOCK_FLAG_RECALCULATE) || (next->flag & BLOCK_FLAG_RECALCULATE)) {
|
310
|
300
|
// NOTE: Entry and exit factors always > 0 by all previous logic operations.
|
311
|
301
|
float nom = current->nominal_speed;
|
312
|
302
|
calculate_trapezoid_for_block(current, current->entry_speed / nom, next->entry_speed / nom);
|
313
|
|
- current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed
|
|
303
|
+ current->flag &= ~BLOCK_FLAG_RECALCULATE; // Reset current only to ensure next trapezoid is computed
|
314
|
304
|
}
|
315
|
305
|
}
|
316
|
306
|
block_index = next_block_index(block_index);
|
|
@@ -319,7 +309,7 @@ void Planner::recalculate_trapezoids() {
|
319
|
309
|
if (next) {
|
320
|
310
|
float nom = next->nominal_speed;
|
321
|
311
|
calculate_trapezoid_for_block(next, next->entry_speed / nom, (MINIMUM_PLANNER_SPEED) / nom);
|
322
|
|
- next->recalculate_flag = false;
|
|
312
|
+ next->flag &= ~BLOCK_FLAG_RECALCULATE;
|
323
|
313
|
}
|
324
|
314
|
}
|
325
|
315
|
|
|
@@ -706,6 +696,9 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
706
|
696
|
// Bail if this is a zero-length block
|
707
|
697
|
if (block->step_event_count < MIN_STEPS_PER_SEGMENT) return;
|
708
|
698
|
|
|
699
|
+ // Clear the block flags
|
|
700
|
+ block->flag = 0;
|
|
701
|
+
|
709
|
702
|
// For a mixing extruder, get a magnified step_event_count for each
|
710
|
703
|
#if ENABLED(MIXING_EXTRUDER)
|
711
|
704
|
for (uint8_t i = 0; i < MIXING_STEPPERS; i++)
|
|
@@ -1021,90 +1014,170 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1021
|
1014
|
|
1022
|
1015
|
// Compute and limit the acceleration rate for the trapezoid generator.
|
1023
|
1016
|
float steps_per_mm = block->step_event_count / block->millimeters;
|
|
1017
|
+ uint32_t accel;
|
1024
|
1018
|
if (!block->steps[X_AXIS] && !block->steps[Y_AXIS] && !block->steps[Z_AXIS]) {
|
1025
|
|
- block->acceleration_steps_per_s2 = ceil(retract_acceleration * steps_per_mm); // convert to: acceleration steps/sec^2
|
|
1019
|
+ // convert to: acceleration steps/sec^2
|
|
1020
|
+ accel = ceil(retract_acceleration * steps_per_mm);
|
1026
|
1021
|
}
|
1027
|
1022
|
else {
|
|
1023
|
+ #define LIMIT_ACCEL(AXIS) do{ \
|
|
1024
|
+ const uint32_t comp = max_acceleration_steps_per_s2[AXIS] * block->step_event_count; \
|
|
1025
|
+ if (accel * block->steps[AXIS] > comp) accel = comp / block->steps[AXIS]; \
|
|
1026
|
+ }while(0)
|
|
1027
|
+
|
|
1028
|
+ // Start with print or travel acceleration
|
|
1029
|
+ accel = ceil((block->steps[E_AXIS] ? acceleration : travel_acceleration) * steps_per_mm);
|
|
1030
|
+
|
1028
|
1031
|
// Limit acceleration per axis
|
1029
|
|
- block->acceleration_steps_per_s2 = ceil((block->steps[E_AXIS] ? acceleration : travel_acceleration) * steps_per_mm);
|
1030
|
|
- if (max_acceleration_steps_per_s2[X_AXIS] < (block->acceleration_steps_per_s2 * block->steps[X_AXIS]) / block->step_event_count)
|
1031
|
|
- block->acceleration_steps_per_s2 = (max_acceleration_steps_per_s2[X_AXIS] * block->step_event_count) / block->steps[X_AXIS];
|
1032
|
|
- if (max_acceleration_steps_per_s2[Y_AXIS] < (block->acceleration_steps_per_s2 * block->steps[Y_AXIS]) / block->step_event_count)
|
1033
|
|
- block->acceleration_steps_per_s2 = (max_acceleration_steps_per_s2[Y_AXIS] * block->step_event_count) / block->steps[Y_AXIS];
|
1034
|
|
- if (max_acceleration_steps_per_s2[Z_AXIS] < (block->acceleration_steps_per_s2 * block->steps[Z_AXIS]) / block->step_event_count)
|
1035
|
|
- block->acceleration_steps_per_s2 = (max_acceleration_steps_per_s2[Z_AXIS] * block->step_event_count) / block->steps[Z_AXIS];
|
1036
|
|
- if (max_acceleration_steps_per_s2[E_AXIS] < (block->acceleration_steps_per_s2 * block->steps[E_AXIS]) / block->step_event_count)
|
1037
|
|
- block->acceleration_steps_per_s2 = (max_acceleration_steps_per_s2[E_AXIS] * block->step_event_count) / block->steps[E_AXIS];
|
|
1032
|
+ LIMIT_ACCEL(X_AXIS);
|
|
1033
|
+ LIMIT_ACCEL(Y_AXIS);
|
|
1034
|
+ LIMIT_ACCEL(Z_AXIS);
|
|
1035
|
+ LIMIT_ACCEL(E_AXIS);
|
1038
|
1036
|
}
|
1039
|
|
- block->acceleration = block->acceleration_steps_per_s2 / steps_per_mm;
|
1040
|
|
- block->acceleration_rate = (long)(block->acceleration_steps_per_s2 * 16777216.0 / ((F_CPU) * 0.125));
|
|
1037
|
+ block->acceleration_steps_per_s2 = accel;
|
|
1038
|
+ block->acceleration = accel / steps_per_mm;
|
|
1039
|
+ block->acceleration_rate = (long)(accel * 16777216.0 / ((F_CPU) * 0.125)); // * 8.388608
|
|
1040
|
+
|
|
1041
|
+ // Initial limit on the segment entry velocity
|
|
1042
|
+ float vmax_junction;
|
1041
|
1043
|
|
1042
|
1044
|
#if 0 // Use old jerk for now
|
1043
|
1045
|
|
1044
|
1046
|
float junction_deviation = 0.1;
|
1045
|
1047
|
|
1046
|
1048
|
// Compute path unit vector
|
1047
|
|
- double unit_vec[XYZ];
|
1048
|
|
-
|
1049
|
|
- unit_vec[X_AXIS] = delta_mm[X_AXIS] * inverse_millimeters;
|
1050
|
|
- unit_vec[Y_AXIS] = delta_mm[Y_AXIS] * inverse_millimeters;
|
1051
|
|
- unit_vec[Z_AXIS] = delta_mm[Z_AXIS] * inverse_millimeters;
|
1052
|
|
-
|
1053
|
|
- // Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
|
1054
|
|
- // Let a circle be tangent to both previous and current path line segments, where the junction
|
1055
|
|
- // deviation is defined as the distance from the junction to the closest edge of the circle,
|
1056
|
|
- // collinear with the circle center. The circular segment joining the two paths represents the
|
1057
|
|
- // path of centripetal acceleration. Solve for max velocity based on max acceleration about the
|
1058
|
|
- // radius of the circle, defined indirectly by junction deviation. This may be also viewed as
|
1059
|
|
- // path width or max_jerk in the previous grbl version. This approach does not actually deviate
|
1060
|
|
- // from path, but used as a robust way to compute cornering speeds, as it takes into account the
|
1061
|
|
- // nonlinearities of both the junction angle and junction velocity.
|
1062
|
|
- double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
|
|
1049
|
+ double unit_vec[XYZ] = {
|
|
1050
|
+ delta_mm[X_AXIS] * inverse_millimeters,
|
|
1051
|
+ delta_mm[Y_AXIS] * inverse_millimeters,
|
|
1052
|
+ delta_mm[Z_AXIS] * inverse_millimeters
|
|
1053
|
+ };
|
|
1054
|
+
|
|
1055
|
+ /*
|
|
1056
|
+ Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
|
|
1057
|
+
|
|
1058
|
+ Let a circle be tangent to both previous and current path line segments, where the junction
|
|
1059
|
+ deviation is defined as the distance from the junction to the closest edge of the circle,
|
|
1060
|
+ collinear with the circle center.
|
|
1061
|
+
|
|
1062
|
+ The circular segment joining the two paths represents the path of centripetal acceleration.
|
|
1063
|
+ Solve for max velocity based on max acceleration about the radius of the circle, defined
|
|
1064
|
+ indirectly by junction deviation.
|
|
1065
|
+
|
|
1066
|
+ This may be also viewed as path width or max_jerk in the previous grbl version. This approach
|
|
1067
|
+ does not actually deviate from path, but used as a robust way to compute cornering speeds, as
|
|
1068
|
+ it takes into account the nonlinearities of both the junction angle and junction velocity.
|
|
1069
|
+ */
|
|
1070
|
+
|
|
1071
|
+ vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
|
1063
|
1072
|
|
1064
|
1073
|
// Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
|
1065
|
|
- if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) {
|
|
1074
|
+ if (block_buffer_head != block_buffer_tail && previous_nominal_speed > 0.0) {
|
1066
|
1075
|
// Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
|
1067
|
1076
|
// NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
|
1068
|
|
- double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
|
1069
|
|
- - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
|
1070
|
|
- - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;
|
|
1077
|
+ float cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
|
|
1078
|
+ - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
|
|
1079
|
+ - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;
|
1071
|
1080
|
// Skip and use default max junction speed for 0 degree acute junction.
|
1072
|
1081
|
if (cos_theta < 0.95) {
|
1073
|
1082
|
vmax_junction = min(previous_nominal_speed, block->nominal_speed);
|
1074
|
1083
|
// Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
|
1075
|
1084
|
if (cos_theta > -0.95) {
|
1076
|
1085
|
// Compute maximum junction velocity based on maximum acceleration and junction deviation
|
1077
|
|
- double sin_theta_d2 = sqrt(0.5 * (1.0 - cos_theta)); // Trig half angle identity. Always positive.
|
|
1086
|
+ float sin_theta_d2 = sqrt(0.5 * (1.0 - cos_theta)); // Trig half angle identity. Always positive.
|
1078
|
1087
|
NOMORE(vmax_junction, sqrt(block->acceleration * junction_deviation * sin_theta_d2 / (1.0 - sin_theta_d2)));
|
1079
|
1088
|
}
|
1080
|
1089
|
}
|
1081
|
1090
|
}
|
1082
|
1091
|
#endif
|
1083
|
1092
|
|
1084
|
|
- // Start with a safe speed
|
1085
|
|
- float vmax_junction = max_jerk[X_AXIS] * 0.5, vmax_junction_factor = 1.0;
|
1086
|
|
- if (max_jerk[Y_AXIS] * 0.5 < fabs(current_speed[Y_AXIS])) NOMORE(vmax_junction, max_jerk[Y_AXIS] * 0.5);
|
1087
|
|
- if (max_jerk[Z_AXIS] * 0.5 < fabs(current_speed[Z_AXIS])) NOMORE(vmax_junction, max_jerk[Z_AXIS] * 0.5);
|
1088
|
|
- if (max_jerk[E_AXIS] * 0.5 < fabs(current_speed[E_AXIS])) NOMORE(vmax_junction, max_jerk[E_AXIS] * 0.5);
|
1089
|
|
- NOMORE(vmax_junction, block->nominal_speed);
|
1090
|
|
- float safe_speed = vmax_junction;
|
|
1093
|
+ /**
|
|
1094
|
+ * Adapted from Prusa MKS firmware
|
|
1095
|
+ *
|
|
1096
|
+ * Start with a safe speed (from which the machine may halt to stop immediately).
|
|
1097
|
+ */
|
|
1098
|
+
|
|
1099
|
+ // Exit speed limited by a jerk to full halt of a previous last segment
|
|
1100
|
+ static float previous_safe_speed;
|
|
1101
|
+
|
|
1102
|
+ float safe_speed = block->nominal_speed;
|
|
1103
|
+ bool limited = false;
|
|
1104
|
+ LOOP_XYZE(i) {
|
|
1105
|
+ float jerk = fabs(current_speed[i]);
|
|
1106
|
+ if (jerk > max_jerk[i]) {
|
|
1107
|
+ // The actual jerk is lower if it has been limited by the XY jerk.
|
|
1108
|
+ if (limited) {
|
|
1109
|
+ // Spare one division by a following gymnastics:
|
|
1110
|
+ // Instead of jerk *= safe_speed / block->nominal_speed,
|
|
1111
|
+ // multiply max_jerk[i] by the divisor.
|
|
1112
|
+ jerk *= safe_speed;
|
|
1113
|
+ float mjerk = max_jerk[i] * block->nominal_speed;
|
|
1114
|
+ if (jerk > mjerk) safe_speed *= mjerk / jerk;
|
|
1115
|
+ }
|
|
1116
|
+ else {
|
|
1117
|
+ safe_speed = max_jerk[i];
|
|
1118
|
+ limited = true;
|
|
1119
|
+ }
|
|
1120
|
+ }
|
|
1121
|
+ }
|
1091
|
1122
|
|
1092
|
1123
|
if (moves_queued > 1 && previous_nominal_speed > 0.0001) {
|
1093
|
|
- //if ((fabs(previous_speed[X_AXIS]) > 0.0001) || (fabs(previous_speed[Y_AXIS]) > 0.0001)) {
|
1094
|
|
- vmax_junction = block->nominal_speed;
|
1095
|
|
- //}
|
1096
|
|
-
|
1097
|
|
- float dsx = fabs(current_speed[X_AXIS] - previous_speed[X_AXIS]),
|
1098
|
|
- dsy = fabs(current_speed[Y_AXIS] - previous_speed[Y_AXIS]),
|
1099
|
|
- dsz = fabs(current_speed[Z_AXIS] - previous_speed[Z_AXIS]),
|
1100
|
|
- dse = fabs(current_speed[E_AXIS] - previous_speed[E_AXIS]);
|
1101
|
|
- if (dsx > max_jerk[X_AXIS]) NOMORE(vmax_junction_factor, max_jerk[X_AXIS] / dsx);
|
1102
|
|
- if (dsy > max_jerk[Y_AXIS]) NOMORE(vmax_junction_factor, max_jerk[Y_AXIS] / dsy);
|
1103
|
|
- if (dsz > max_jerk[Z_AXIS]) NOMORE(vmax_junction_factor, max_jerk[Z_AXIS] / dsz);
|
1104
|
|
- if (dse > max_jerk[E_AXIS]) NOMORE(vmax_junction_factor, max_jerk[E_AXIS] / dse);
|
1105
|
|
-
|
1106
|
|
- vmax_junction = min(previous_nominal_speed, vmax_junction * vmax_junction_factor); // Limit speed to max previous speed
|
|
1124
|
+ // Estimate a maximum velocity allowed at a joint of two successive segments.
|
|
1125
|
+ // If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
|
|
1126
|
+ // then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
|
|
1127
|
+
|
|
1128
|
+ // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
|
|
1129
|
+ bool prev_speed_larger = previous_nominal_speed > block->nominal_speed;
|
|
1130
|
+ float smaller_speed_factor = prev_speed_larger ? (block->nominal_speed / previous_nominal_speed) : (previous_nominal_speed / block->nominal_speed);
|
|
1131
|
+ // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
|
|
1132
|
+ vmax_junction = prev_speed_larger ? block->nominal_speed : previous_nominal_speed;
|
|
1133
|
+ // Factor to multiply the previous / current nominal velocities to get componentwise limited velocities.
|
|
1134
|
+ float v_factor = 1.f;
|
|
1135
|
+ limited = false;
|
|
1136
|
+ // Now limit the jerk in all axes.
|
|
1137
|
+ LOOP_XYZE(axis) {
|
|
1138
|
+ // Limit an axis. We have to differentiate: coasting, reversal of an axis, full stop.
|
|
1139
|
+ float v_exit = previous_speed[axis], v_entry = current_speed[axis];
|
|
1140
|
+ if (prev_speed_larger) v_exit *= smaller_speed_factor;
|
|
1141
|
+ if (limited) {
|
|
1142
|
+ v_exit *= v_factor;
|
|
1143
|
+ v_entry *= v_factor;
|
|
1144
|
+ }
|
|
1145
|
+ // Calculate jerk depending on whether the axis is coasting in the same direction or reversing.
|
|
1146
|
+ float jerk =
|
|
1147
|
+ (v_exit > v_entry) ?
|
|
1148
|
+ ((v_entry > 0.f || v_exit < 0.f) ?
|
|
1149
|
+ // coasting
|
|
1150
|
+ (v_exit - v_entry) :
|
|
1151
|
+ // axis reversal
|
|
1152
|
+ max(v_exit, -v_entry)) :
|
|
1153
|
+ // v_exit <= v_entry
|
|
1154
|
+ ((v_entry < 0.f || v_exit > 0.f) ?
|
|
1155
|
+ // coasting
|
|
1156
|
+ (v_entry - v_exit) :
|
|
1157
|
+ // axis reversal
|
|
1158
|
+ max(-v_exit, v_entry));
|
|
1159
|
+ if (jerk > max_jerk[axis]) {
|
|
1160
|
+ v_factor *= max_jerk[axis] / jerk;
|
|
1161
|
+ limited = true;
|
|
1162
|
+ }
|
|
1163
|
+ }
|
|
1164
|
+ if (limited) vmax_junction *= v_factor;
|
|
1165
|
+ // Now the transition velocity is known, which maximizes the shared exit / entry velocity while
|
|
1166
|
+ // respecting the jerk factors, it may be possible, that applying separate safe exit / entry velocities will achieve faster prints.
|
|
1167
|
+ float vmax_junction_threshold = vmax_junction * 0.99f;
|
|
1168
|
+ if (previous_safe_speed > vmax_junction_threshold && safe_speed > vmax_junction_threshold) {
|
|
1169
|
+ // Not coasting. The machine will stop and start the movements anyway,
|
|
1170
|
+ // better to start the segment from start.
|
|
1171
|
+ block->flag |= BLOCK_FLAG_START_FROM_FULL_HALT;
|
|
1172
|
+ vmax_junction = safe_speed;
|
|
1173
|
+ }
|
|
1174
|
+ }
|
|
1175
|
+ else {
|
|
1176
|
+ block->flag |= BLOCK_FLAG_START_FROM_FULL_HALT;
|
|
1177
|
+ vmax_junction = safe_speed;
|
1107
|
1178
|
}
|
|
1179
|
+
|
|
1180
|
+ // Max entry speed of this block equals the max exit speed of the previous block.
|
1108
|
1181
|
block->max_entry_speed = vmax_junction;
|
1109
|
1182
|
|
1110
|
1183
|
// Initialize block entry speed. Compute based on deceleration to user-defined MINIMUM_PLANNER_SPEED.
|
|
@@ -1119,12 +1192,12 @@ void Planner::_buffer_line(const float &a, const float &b, const float &c, const
|
1119
|
1192
|
// block nominal speed limits both the current and next maximum junction speeds. Hence, in both
|
1120
|
1193
|
// the reverse and forward planners, the corresponding block junction speed will always be at the
|
1121
|
1194
|
// the maximum junction speed and may always be ignored for any speed reduction checks.
|
1122
|
|
- block->nominal_length_flag = (block->nominal_speed <= v_allowable);
|
1123
|
|
- block->recalculate_flag = true; // Always calculate trapezoid for new block
|
|
1195
|
+ block->flag |= BLOCK_FLAG_RECALCULATE | (block->nominal_speed <= v_allowable ? BLOCK_FLAG_NOMINAL_LENGTH : 0);
|
1124
|
1196
|
|
1125
|
1197
|
// Update previous path unit_vector and nominal speed
|
1126
|
1198
|
memcpy(previous_speed, current_speed, sizeof(previous_speed));
|
1127
|
1199
|
previous_nominal_speed = block->nominal_speed;
|
|
1200
|
+ previous_safe_speed = safe_speed;
|
1128
|
1201
|
|
1129
|
1202
|
#if ENABLED(LIN_ADVANCE)
|
1130
|
1203
|
|