|
@@ -474,20 +474,10 @@
|
474
|
474
|
set_current_to_destination();
|
475
|
475
|
}
|
476
|
476
|
|
477
|
|
-
|
478
|
|
- #ifdef UBL_DELTA
|
479
|
|
-
|
480
|
|
- #define COPY_XYZE( target, source ) { \
|
481
|
|
- target[X_AXIS] = source[X_AXIS]; \
|
482
|
|
- target[Y_AXIS] = source[Y_AXIS]; \
|
483
|
|
- target[Z_AXIS] = source[Z_AXIS]; \
|
484
|
|
- target[E_AXIS] = source[E_AXIS]; \
|
485
|
|
- }
|
|
477
|
+ #if UBL_DELTA
|
486
|
478
|
|
487
|
479
|
#if IS_SCARA // scale the feed rate from mm/s to degrees/s
|
488
|
|
- static float scara_feed_factor;
|
489
|
|
- static float scara_oldA;
|
490
|
|
- static float scara_oldB;
|
|
480
|
+ static float scara_feed_factor, scara_oldA, scara_oldB;
|
491
|
481
|
#endif
|
492
|
482
|
|
493
|
483
|
// We don't want additional apply_leveling() performed by regular buffer_line or buffer_line_kinematic,
|
|
@@ -501,18 +491,18 @@
|
501
|
491
|
float feedrate = fr_mm_s;
|
502
|
492
|
|
503
|
493
|
#if IS_SCARA // scale the feed rate from mm/s to degrees/s
|
504
|
|
- float adiff = abs(delta[A_AXIS] - scara_oldA);
|
505
|
|
- float bdiff = abs(delta[B_AXIS] - scara_oldB);
|
|
494
|
+ float adiff = abs(delta[A_AXIS] - scara_oldA),
|
|
495
|
+ bdiff = abs(delta[B_AXIS] - scara_oldB);
|
506
|
496
|
scara_oldA = delta[A_AXIS];
|
507
|
497
|
scara_oldB = delta[B_AXIS];
|
508
|
498
|
feedrate = max(adiff, bdiff) * scara_feed_factor;
|
509
|
499
|
#endif
|
510
|
500
|
|
511
|
|
- planner._buffer_line( delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], feedrate, extruder );
|
|
501
|
+ planner._buffer_line(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], ltarget[E_AXIS], feedrate, extruder);
|
512
|
502
|
|
513
|
503
|
#else // cartesian
|
514
|
504
|
|
515
|
|
- planner._buffer_line( ltarget[X_AXIS], ltarget[Y_AXIS], ltarget[Z_AXIS], ltarget[E_AXIS], fr_mm_s, extruder );
|
|
505
|
+ planner._buffer_line(ltarget[X_AXIS], ltarget[Y_AXIS], ltarget[Z_AXIS], ltarget[E_AXIS], fr_mm_s, extruder);
|
516
|
506
|
|
517
|
507
|
#endif
|
518
|
508
|
}
|
|
@@ -525,7 +515,7 @@
|
525
|
515
|
|
526
|
516
|
static bool ubl_prepare_linear_move_to(const float ltarget[XYZE], const float &feedrate) {
|
527
|
517
|
|
528
|
|
- if ( ! position_is_reachable_xy( ltarget[X_AXIS], ltarget[Y_AXIS] )) // fail if moving outside reachable boundary
|
|
518
|
+ if (!position_is_reachable_xy(ltarget[X_AXIS], ltarget[Y_AXIS])) // fail if moving outside reachable boundary
|
529
|
519
|
return true; // did not move, so current_position still accurate
|
530
|
520
|
|
531
|
521
|
const float difference[XYZE] = { // cartesian distances moved in XYZE
|
|
@@ -533,21 +523,21 @@
|
533
|
523
|
ltarget[Y_AXIS] - current_position[Y_AXIS],
|
534
|
524
|
ltarget[Z_AXIS] - current_position[Z_AXIS],
|
535
|
525
|
ltarget[E_AXIS] - current_position[E_AXIS]
|
536
|
|
- };
|
|
526
|
+ };
|
537
|
527
|
|
538
|
|
- float cartesian_xy_mm = sqrtf( sq(difference[X_AXIS]) + sq(difference[Y_AXIS]) ); // total horizontal xy distance
|
|
528
|
+ const float cartesian_xy_mm = HYPOT(difference[X_AXIS], difference[Y_AXIS]); // total horizontal xy distance
|
539
|
529
|
|
540
|
530
|
#if IS_KINEMATIC
|
541
|
|
- float seconds = cartesian_xy_mm / feedrate; // seconds to move xy distance at requested rate
|
542
|
|
- uint16_t segments = lroundf( delta_segments_per_second * seconds ); // preferred number of segments for distance @ feedrate
|
543
|
|
- uint16_t seglimit = lroundf( cartesian_xy_mm * (1.0/(DELTA_SEGMENT_MIN_LENGTH))); // number of segments at minimum segment length
|
544
|
|
- NOMORE( segments, seglimit ); // limit to minimum segment length (fewer segments)
|
|
531
|
+ const float seconds = cartesian_xy_mm / feedrate; // seconds to move xy distance at requested rate
|
|
532
|
+ uint16_t segments = lroundf(delta_segments_per_second * seconds), // preferred number of segments for distance @ feedrate
|
|
533
|
+ seglimit = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // number of segments at minimum segment length
|
|
534
|
+ NOMORE(segments, seglimit); // limit to minimum segment length (fewer segments)
|
545
|
535
|
#else
|
546
|
|
- uint16_t segments = lroundf( cartesian_xy_mm * (1.0/(DELTA_SEGMENT_MIN_LENGTH))); // cartesian fixed segment length
|
|
536
|
+ uint16_t segments = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // cartesian fixed segment length
|
547
|
537
|
#endif
|
548
|
538
|
|
549
|
|
- NOLESS( segments, 1 ); // must have at least one segment
|
550
|
|
- float inv_segments = 1.0 / segments; // divide once, multiply thereafter
|
|
539
|
+ NOLESS(segments, 1); // must have at least one segment
|
|
540
|
+ const float inv_segments = 1.0 / segments; // divide once, multiply thereafter
|
551
|
541
|
|
552
|
542
|
#if IS_SCARA // scale the feed rate from mm/s to degrees/s
|
553
|
543
|
scara_feed_factor = cartesian_xy_mm * inv_segments * feedrate;
|
|
@@ -560,57 +550,53 @@
|
560
|
550
|
difference[Y_AXIS] * inv_segments,
|
561
|
551
|
difference[Z_AXIS] * inv_segments,
|
562
|
552
|
difference[E_AXIS] * inv_segments
|
563
|
|
- };
|
|
553
|
+ };
|
564
|
554
|
|
565
|
555
|
// Note that E segment distance could vary slightly as z mesh height
|
566
|
556
|
// changes for each segment, but small enough to ignore.
|
567
|
557
|
|
568
|
|
- bool above_fade_height = false;
|
569
|
|
- #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
570
|
|
- if (( planner.z_fade_height != 0 ) &&
|
571
|
|
- ( planner.z_fade_height < RAW_Z_POSITION(ltarget[Z_AXIS]) )) {
|
572
|
|
- above_fade_height = true;
|
573
|
|
- }
|
574
|
|
- #endif
|
|
558
|
+ const bool above_fade_height = (
|
|
559
|
+ #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
|
560
|
+ planner.z_fade_height != 0 && planner.z_fade_height < RAW_Z_POSITION(ltarget[Z_AXIS])
|
|
561
|
+ #else
|
|
562
|
+ false
|
|
563
|
+ #endif
|
|
564
|
+ );
|
575
|
565
|
|
576
|
566
|
// Only compute leveling per segment if ubl active and target below z_fade_height.
|
577
|
567
|
|
578
|
|
- if (( ! ubl.state.active ) || ( above_fade_height )) { // no mesh leveling
|
|
568
|
+ if (!ubl.state.active || above_fade_height) { // no mesh leveling
|
579
|
569
|
|
580
|
570
|
const float z_offset = ubl.state.active ? ubl.state.z_offset : 0.0;
|
581
|
571
|
|
582
|
|
- float seg_dest[XYZE]; // per-segment destination,
|
583
|
|
- COPY_XYZE( seg_dest, current_position ); // starting from current position
|
|
572
|
+ float seg_dest[XYZE]; // per-segment destination,
|
|
573
|
+ COPY(seg_dest, current_position); // starting from current position
|
584
|
574
|
|
585
|
575
|
while (--segments) {
|
586
|
576
|
LOOP_XYZE(i) seg_dest[i] += segment_distance[i];
|
587
|
577
|
float ztemp = seg_dest[Z_AXIS];
|
588
|
578
|
seg_dest[Z_AXIS] += z_offset;
|
589
|
|
- ubl_buffer_line_segment( seg_dest, feedrate, active_extruder );
|
|
579
|
+ ubl_buffer_line_segment(seg_dest, feedrate, active_extruder);
|
590
|
580
|
seg_dest[Z_AXIS] = ztemp;
|
591
|
581
|
}
|
592
|
582
|
|
593
|
583
|
// Since repeated adding segment_distance accumulates small errors, final move to exact destination.
|
594
|
|
- COPY_XYZE( seg_dest, ltarget );
|
|
584
|
+ COPY(seg_dest, ltarget);
|
595
|
585
|
seg_dest[Z_AXIS] += z_offset;
|
596
|
|
- ubl_buffer_line_segment( seg_dest, feedrate, active_extruder );
|
|
586
|
+ ubl_buffer_line_segment(seg_dest, feedrate, active_extruder);
|
597
|
587
|
return false; // moved but did not set_current_to_destination();
|
598
|
588
|
}
|
599
|
589
|
|
600
|
590
|
// Otherwise perform per-segment leveling
|
601
|
591
|
|
602
|
|
- #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
603
|
|
- float fade_scaling_factor = ubl.fade_scaling_factor_for_z(ltarget[Z_AXIS]);
|
604
|
|
- #endif
|
605
|
|
-
|
606
|
592
|
float seg_dest[XYZE]; // per-segment destination, initialize to first segment
|
607
|
593
|
LOOP_XYZE(i) seg_dest[i] = current_position[i] + segment_distance[i];
|
608
|
594
|
|
609
|
595
|
const float& dx_seg = segment_distance[X_AXIS]; // alias for clarity
|
610
|
596
|
const float& dy_seg = segment_distance[Y_AXIS];
|
611
|
597
|
|
612
|
|
- float rx = RAW_X_POSITION(seg_dest[X_AXIS]); // assume raw vs logical coordinates shifted but not scaled.
|
613
|
|
- float ry = RAW_Y_POSITION(seg_dest[Y_AXIS]);
|
|
598
|
+ float rx = RAW_X_POSITION(seg_dest[X_AXIS]), // assume raw vs logical coordinates shifted but not scaled.
|
|
599
|
+ ry = RAW_Y_POSITION(seg_dest[Y_AXIS]);
|
614
|
600
|
|
615
|
601
|
do { // for each mesh cell encountered during the move
|
616
|
602
|
|
|
@@ -621,74 +607,75 @@
|
621
|
607
|
// in top of loop and again re-find same adjacent cell and use it, just less efficient
|
622
|
608
|
// for mesh inset area.
|
623
|
609
|
|
624
|
|
- int8_t cell_xi = (rx - (UBL_MESH_MIN_X)) * (1.0 / (MESH_X_DIST));
|
625
|
|
- cell_xi = constrain( cell_xi, 0, (GRID_MAX_POINTS_X) - 1 );
|
|
610
|
+ int8_t cell_xi = (rx - (UBL_MESH_MIN_X)) * (1.0 / (MESH_X_DIST)),
|
|
611
|
+ cell_yi = (ry - (UBL_MESH_MIN_Y)) * (1.0 / (MESH_X_DIST));
|
626
|
612
|
|
627
|
|
- int8_t cell_yi = (ry - (UBL_MESH_MIN_Y)) * (1.0 / (MESH_X_DIST));
|
628
|
|
- cell_yi = constrain( cell_yi, 0, (GRID_MAX_POINTS_Y) - 1 );
|
|
613
|
+ cell_xi = constrain(cell_xi, 0, (GRID_MAX_POINTS_X) - 1);
|
|
614
|
+ cell_yi = constrain(cell_yi, 0, (GRID_MAX_POINTS_Y) - 1);
|
629
|
615
|
|
630
|
616
|
// float x0 = (UBL_MESH_MIN_X) + ((MESH_X_DIST) * cell_xi ); // lower left cell corner
|
631
|
617
|
// float y0 = (UBL_MESH_MIN_Y) + ((MESH_Y_DIST) * cell_yi ); // lower left cell corner
|
632
|
618
|
// float x1 = x0 + MESH_X_DIST; // upper right cell corner
|
633
|
619
|
// float y1 = y0 + MESH_Y_DIST; // upper right cell corner
|
634
|
620
|
|
635
|
|
- float x0 = pgm_read_float(&(ubl.mesh_index_to_xpos[cell_xi ])); // 64 byte table lookup avoids mul+add
|
636
|
|
- float y0 = pgm_read_float(&(ubl.mesh_index_to_ypos[cell_yi ])); // 64 byte table lookup avoids mul+add
|
637
|
|
- float x1 = pgm_read_float(&(ubl.mesh_index_to_xpos[cell_xi+1])); // 64 byte table lookup avoids mul+add
|
638
|
|
- float y1 = pgm_read_float(&(ubl.mesh_index_to_ypos[cell_yi+1])); // 64 byte table lookup avoids mul+add
|
|
621
|
+ const float x0 = pgm_read_float(&(ubl.mesh_index_to_xpos[cell_xi ])), // 64 byte table lookup avoids mul+add
|
|
622
|
+ y0 = pgm_read_float(&(ubl.mesh_index_to_ypos[cell_yi ])), // 64 byte table lookup avoids mul+add
|
|
623
|
+ x1 = pgm_read_float(&(ubl.mesh_index_to_xpos[cell_xi+1])), // 64 byte table lookup avoids mul+add
|
|
624
|
+ y1 = pgm_read_float(&(ubl.mesh_index_to_ypos[cell_yi+1])), // 64 byte table lookup avoids mul+add
|
|
625
|
+
|
|
626
|
+ cx = rx - x0, // cell-relative x
|
|
627
|
+ cy = ry - y0; // cell-relative y
|
639
|
628
|
|
640
|
|
- float cx = rx - x0; // cell-relative x
|
641
|
|
- float cy = ry - y0; // cell-relative y
|
|
629
|
+ float z_x0y0 = ubl.z_values[cell_xi ][cell_yi ], // z at lower left corner
|
|
630
|
+ z_x1y0 = ubl.z_values[cell_xi+1][cell_yi ], // z at upper left corner
|
|
631
|
+ z_x0y1 = ubl.z_values[cell_xi ][cell_yi+1], // z at lower right corner
|
|
632
|
+ z_x1y1 = ubl.z_values[cell_xi+1][cell_yi+1]; // z at upper right corner
|
642
|
633
|
|
643
|
|
- float z_x0y0 = ubl.z_values[cell_xi ][cell_yi ]; // z at lower left corner
|
644
|
|
- float z_x1y0 = ubl.z_values[cell_xi+1][cell_yi ]; // z at upper left corner
|
645
|
|
- float z_x0y1 = ubl.z_values[cell_xi ][cell_yi+1]; // z at lower right corner
|
646
|
|
- float z_x1y1 = ubl.z_values[cell_xi+1][cell_yi+1]; // z at upper right corner
|
|
634
|
+ if (isnan(z_x0y0)) z_x0y0 = 0; // ideally activating ubl.state.active (G29 A)
|
|
635
|
+ if (isnan(z_x1y0)) z_x1y0 = 0; // should refuse if any invalid mesh points
|
|
636
|
+ if (isnan(z_x0y1)) z_x0y1 = 0; // in order to avoid isnan tests per cell,
|
|
637
|
+ if (isnan(z_x1y1)) z_x1y1 = 0; // thus guessing zero for undefined points
|
647
|
638
|
|
648
|
|
- if ( isnan( z_x0y0 )) z_x0y0 = 0; // ideally activating ubl.state.active (G29 A)
|
649
|
|
- if ( isnan( z_x1y0 )) z_x1y0 = 0; // should refuse if any invalid mesh points
|
650
|
|
- if ( isnan( z_x0y1 )) z_x0y1 = 0; // in order to avoid isnan tests per cell,
|
651
|
|
- if ( isnan( z_x1y1 )) z_x1y1 = 0; // thus guessing zero for undefined points
|
|
639
|
+ const float z_xmy0 = (z_x1y0 - z_x0y0) * (1.0 / (MESH_X_DIST)), // z slope per x along y0 (lower left to lower right)
|
|
640
|
+ z_xmy1 = (z_x1y1 - z_x0y1) * (1.0 / (MESH_X_DIST)); // z slope per x along y1 (upper left to upper right)
|
652
|
641
|
|
653
|
|
- float z_xmy0 = (z_x1y0 - z_x0y0) * (1.0/MESH_X_DIST); // z slope per x along y0 (lower left to lower right)
|
654
|
|
- float z_xmy1 = (z_x1y1 - z_x0y1) * (1.0/MESH_X_DIST); // z slope per x along y1 (upper left to upper right)
|
|
642
|
+ float z_cxy0 = z_x0y0 + z_xmy0 * cx; // z height along y0 at cx
|
655
|
643
|
|
656
|
|
- float z_cxy0 = z_x0y0 + z_xmy0 * cx; // z height along y0 at cx
|
657
|
|
- float z_cxy1 = z_x0y1 + z_xmy1 * cx; // z height along y1 at cx
|
658
|
|
- float z_cxyd = z_cxy1 - z_cxy0; // z height difference along cx from y0 to y1
|
|
644
|
+ const float z_cxy1 = z_x0y1 + z_xmy1 * cx, // z height along y1 at cx
|
|
645
|
+ z_cxyd = z_cxy1 - z_cxy0; // z height difference along cx from y0 to y1
|
659
|
646
|
|
660
|
|
- float z_cxym = z_cxyd * (1.0/MESH_Y_DIST); // z slope per y along cx from y0 to y1
|
661
|
|
- float z_cxcy = z_cxy0 + z_cxym * cy; // z height along cx at cy
|
|
647
|
+ float z_cxym = z_cxyd * (1.0 / (MESH_Y_DIST)), // z slope per y along cx from y0 to y1
|
|
648
|
+ z_cxcy = z_cxy0 + z_cxym * cy; // z height along cx at cy
|
662
|
649
|
|
663
|
650
|
// As subsequent segments step through this cell, the z_cxy0 intercept will change
|
664
|
651
|
// and the z_cxym slope will change, both as a function of cx within the cell, and
|
665
|
652
|
// each change by a constant for fixed segment lengths.
|
666
|
653
|
|
667
|
|
- float z_sxy0 = z_xmy0 * dx_seg; // per-segment adjustment to z_cxy0
|
668
|
|
- float z_sxym = ( z_xmy1 - z_xmy0 ) * (1.0/MESH_Y_DIST) * dx_seg; // per-segment adjustment to z_cxym
|
|
654
|
+ const float z_sxy0 = z_xmy0 * dx_seg, // per-segment adjustment to z_cxy0
|
|
655
|
+ z_sxym = (z_xmy1 - z_xmy0) * (1.0 / (MESH_Y_DIST)) * dx_seg; // per-segment adjustment to z_cxym
|
669
|
656
|
|
670
|
657
|
do { // for all segments within this mesh cell
|
671
|
658
|
|
672
|
659
|
z_cxcy += ubl.state.z_offset;
|
673
|
660
|
|
674
|
|
- if ( --segments == 0 ) { // this is last segment, use ltarget for exact
|
675
|
|
- COPY_XYZE( seg_dest, ltarget );
|
|
661
|
+ if (--segments == 0) { // this is last segment, use ltarget for exact
|
|
662
|
+ COPY(seg_dest, ltarget);
|
676
|
663
|
seg_dest[Z_AXIS] += z_cxcy;
|
677
|
|
- ubl_buffer_line_segment( seg_dest, feedrate, active_extruder );
|
|
664
|
+ ubl_buffer_line_segment(seg_dest, feedrate, active_extruder);
|
678
|
665
|
return false; // did not set_current_to_destination()
|
679
|
666
|
}
|
680
|
667
|
|
681
|
|
- float z_orig = seg_dest[Z_AXIS]; // remember the pre-leveled segment z value
|
682
|
|
- seg_dest[Z_AXIS] = z_orig + z_cxcy; // adjust segment z height per mesh leveling
|
683
|
|
- ubl_buffer_line_segment( seg_dest, feedrate, active_extruder );
|
684
|
|
- seg_dest[Z_AXIS] = z_orig; // restore pre-leveled z before incrementing
|
|
668
|
+ const float z_orig = seg_dest[Z_AXIS]; // remember the pre-leveled segment z value
|
|
669
|
+ seg_dest[Z_AXIS] = z_orig + z_cxcy; // adjust segment z height per mesh leveling
|
|
670
|
+ ubl_buffer_line_segment(seg_dest, feedrate, active_extruder);
|
|
671
|
+ seg_dest[Z_AXIS] = z_orig; // restore pre-leveled z before incrementing
|
685
|
672
|
|
686
|
673
|
LOOP_XYZE(i) seg_dest[i] += segment_distance[i]; // adjust seg_dest for next segment
|
687
|
674
|
|
688
|
675
|
cx += dx_seg;
|
689
|
676
|
cy += dy_seg;
|
690
|
677
|
|
691
|
|
- if ( !WITHIN(cx,0,MESH_X_DIST) || !WITHIN(cy,0,MESH_Y_DIST)) { // done within this cell, break to next
|
|
678
|
+ if (!WITHIN(cx, 0, MESH_X_DIST) || !WITHIN(cy, 0, MESH_Y_DIST)) { // done within this cell, break to next
|
692
|
679
|
rx = RAW_X_POSITION(seg_dest[X_AXIS]);
|
693
|
680
|
ry = RAW_Y_POSITION(seg_dest[Y_AXIS]);
|
694
|
681
|
break;
|