|
46 | 46 | // corners of cells. To fix the issue, simply check if the start/end of the line |
47 | 47 | // is very close to a cell boundary in advance and don't split the line there. |
48 | 48 |
|
49 | | - void unified_bed_leveling::line_to_destination_cartesian(const feedRate_t scaled_fr_mm_s, const uint8_t extruder) { |
| 49 | + void unified_bed_leveling::line_to_destination_cartesian(const feedRate_t scaled_fr, const uint8_t extruder) { |
50 | 50 | /** |
51 | 51 | * Much of the nozzle movement will be within the same cell. So we will do as little computation |
52 | 52 | * as possible to determine if this is the case. If this move is within the same cell, we will |
|
60 | 60 | const xyze_pos_t &start = current_position, &end = destination; |
61 | 61 | #endif |
62 | 62 |
|
| 63 | + const xyze_pos_t total = end - start; |
| 64 | + |
| 65 | + #if ENABLED(FEEDRATE_MODE_SUPPORT) |
| 66 | + // Get the linear distance in XYZ |
| 67 | + #if HAS_ROTATIONAL_AXES |
| 68 | + bool cartes_move = true; |
| 69 | + #endif |
| 70 | + float cartesian_mm = get_move_distance(total OPTARG(HAS_ROTATIONAL_AXES, cartes_move)); |
| 71 | + |
| 72 | + // If the move is very short, check the E move distance |
| 73 | + TERN_(HAS_EXTRUDERS, if (UNEAR_ZERO(cartesian_mm)) cartesian_mm = ABS(total.e)); |
| 74 | + |
| 75 | + const bool old_inverse_time_enabled = parser.inverse_time_enabled; |
| 76 | + |
| 77 | + const feedRate_t scaled_fr_mm_s = (old_inverse_time_enabled && parser.print_move) ? cartesian_mm * scaled_fr : scaled_fr; |
| 78 | + parser.inverse_time_enabled = false; |
| 79 | + |
| 80 | + #else |
| 81 | + const feedRate_t scaled_fr_mm_s = scaled_fr; |
| 82 | + #endif |
| 83 | + |
63 | 84 | const xy_uint8_t istart = cell_indexes(start), iend = cell_indexes(end); |
64 | 85 |
|
65 | 86 | // A move within the same cell needs no splitting |
|
79 | 100 | end.z += UBL_Z_RAISE_WHEN_OFF_MESH; |
80 | 101 | planner.buffer_segment(end, scaled_fr_mm_s, extruder); |
81 | 102 | current_position = destination; |
| 103 | + TERN_(FEEDRATE_MODE_SUPPORT, parser.inverse_time_enabled = old_inverse_time_enabled); |
82 | 104 | return; |
83 | 105 | } |
84 | 106 | #endif |
|
97 | 119 | if (!isnan(z0)) end.z += z0; |
98 | 120 | planner.buffer_segment(end, scaled_fr_mm_s, extruder); |
99 | 121 | current_position = destination; |
| 122 | + TERN_(FEEDRATE_MODE_SUPPORT, parser.inverse_time_enabled = old_inverse_time_enabled); |
100 | 123 | return; |
101 | 124 | } |
102 | 125 |
|
|
105 | 128 | * case - crossing only one X or Y line - after details are worked out to reduce computation. |
106 | 129 | */ |
107 | 130 |
|
108 | | - const xy_float_t dist = end - start; |
| 131 | + const xy_float_t dist = xy_float:t(total); |
109 | 132 | const xy_bool_t neg { dist.x < 0, dist.y < 0 }; |
110 | 133 | const xy_uint8_t ineg { uint8_t(neg.x), uint8_t(neg.y) }; |
111 | 134 | const xy_float_t sign { neg.x ? -1.0f : 1.0f, neg.y ? -1.0f : 1.0f }; |
|
194 | 217 | goto FINAL_MOVE; |
195 | 218 |
|
196 | 219 | current_position = destination; |
| 220 | + TERN_(FEEDRATE_MODE_SUPPORT, parser.inverse_time_enabled = old_inverse_time_enabled); |
197 | 221 | return; |
198 | 222 | } |
199 | 223 |
|
|
357 | 381 |
|
358 | 382 | const xyze_pos_t total = destination - current_position; |
359 | 383 |
|
360 | | - const float cart_xy_mm_2 = HYPOT2(total.x, total.y), |
361 | | - cart_xy_mm = SQRT(cart_xy_mm_2); // Total XY distance |
| 384 | + // If the move is only in Z/E don't split up the move |
| 385 | + if (!total.x && !total.y) { |
| 386 | + planner.buffer_line(destination, scaled_fr_mm_s); |
| 387 | + return false; // caller will update current_position |
| 388 | + } |
| 389 | + |
| 390 | + #if HAS_ROTATIONAL_AXES |
| 391 | + bool cartes_move = true; |
| 392 | + #endif |
| 393 | + float cartesian_mm = get_move_distance(total OPTARG(HAS_ROTATIONAL_AXES, cartes_move)); |
| 394 | + |
| 395 | + // If the move is very short, check the E move distance |
| 396 | + TERN_(HAS_EXTRUDERS, if (UNEAR_ZERO(cartesian_mm)) cartesian_mm = ABS(total.e)); |
| 397 | + |
| 398 | + // No E move either? Game over. |
| 399 | + if (UNEAR_ZERO(cartesian_mm)) return true; |
362 | 400 |
|
363 | 401 | #if IS_KINEMATIC |
364 | | - const float seconds = cart_xy_mm / scaled_fr_mm_s; // Duration of XY move at requested rate |
| 402 | + // Minimum number of seconds to move the given distance |
| 403 | + #if ENABLED(FEEDRATE_MODE_SUPPORT) |
| 404 | + const float seconds = (parser.print_move && parser.inverse_time_enabled) ? RECIPROCAL(scaled_fr_mm_s) : cartesian_mm / ( |
| 405 | + #if ALL(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) |
| 406 | + cartes_move ? scaled_fr_mm_s : LINEAR_UNIT(scaled_fr_mm_s) |
| 407 | + #else |
| 408 | + scaled_fr_mm_s |
| 409 | + #endif |
| 410 | + ); |
| 411 | + #else |
| 412 | + const float seconds = cartesian_mm / ( |
| 413 | + #if ALL(HAS_ROTATIONAL_AXES, INCH_MODE_SUPPORT) |
| 414 | + cartes_move ? scaled_fr_mm_s : LINEAR_UNIT(scaled_fr_mm_s) |
| 415 | + #else |
| 416 | + scaled_fr_mm_s |
| 417 | + #endif |
| 418 | + ); |
| 419 | + #endif |
365 | 420 | uint16_t segments = LROUND(segments_per_second * seconds), // Preferred number of segments for distance @ feedrate |
366 | | - seglimit = LROUND(cart_xy_mm * RECIPROCAL(SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length |
| 421 | + seglimit = LROUND(cartesian_mm * RECIPROCAL(SEGMENT_MIN_LENGTH)); // Number of segments at minimum segment length |
| 422 | + |
367 | 423 | NOMORE(segments, seglimit); // Limit to minimum segment length (fewer segments) |
368 | 424 | #else |
369 | | - uint16_t segments = LROUND(cart_xy_mm * RECIPROCAL(SEGMENT_MIN_LENGTH)); // Cartesian fixed segment length |
| 425 | + uint16_t segments = LROUND(cartesian_mm * RECIPROCAL(SEGMENT_MIN_LENGTH)); // Cartesian fixed segment length |
370 | 426 | #endif |
371 | 427 |
|
372 | 428 | NOLESS(segments, 1U); // Must have at least one segment |
373 | 429 | const float inv_segments = 1.0f / segments; // Reciprocal to save calculation |
374 | 430 |
|
375 | 431 | // Add hints to help optimize the move |
376 | | - PlannerHints hints(SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments); // Length of each segment |
377 | | - #if ENABLED(FEEDRATE_SCALING) |
| 432 | + PlannerHints hints(cartesian_mm * inv_segments); // Length of each segment |
| 433 | + #if IS_KINEMATIC && ENABLED(FEEDRATE_MODE_SUPPORT) |
| 434 | + hints.inv_duration = segments / seconds; |
| 435 | + #elif ENABLED(FEEDRATE_SCALING) |
378 | 436 | hints.inv_duration = scaled_fr_mm_s / hints.millimeters; |
379 | 437 | #endif |
380 | 438 |
|
|
0 commit comments