G26 Hilbert Curve followup (#21480)

This commit is contained in:
Marcio T
2021-04-01 18:12:00 -06:00
committed by GitHub
parent 05b39623b0
commit 45c1432946
24 changed files with 442 additions and 444 deletions

View File

@ -85,9 +85,9 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
//#define EXTRAPOLATE_FROM_EDGE
#if ENABLED(EXTRAPOLATE_FROM_EDGE)
#if GRID_MAX_POINTS_X < GRID_MAX_POINTS_Y
#if (GRID_MAX_POINTS_X) < (GRID_MAX_POINTS_Y)
#define HALF_IN_X
#elif GRID_MAX_POINTS_Y < GRID_MAX_POINTS_X
#elif (GRID_MAX_POINTS_Y) < (GRID_MAX_POINTS_X)
#define HALF_IN_Y
#endif
#endif
@ -98,23 +98,23 @@ static void extrapolate_one_point(const uint8_t x, const uint8_t y, const int8_t
*/
void extrapolate_unprobed_bed_level() {
#ifdef HALF_IN_X
constexpr uint8_t ctrx2 = 0, xlen = GRID_MAX_POINTS_X - 1;
constexpr uint8_t ctrx2 = 0, xend = GRID_MAX_POINTS_X - 1;
#else
constexpr uint8_t ctrx1 = (GRID_MAX_POINTS_X - 1) / 2, // left-of-center
ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center
xlen = ctrx1;
constexpr uint8_t ctrx1 = (GRID_MAX_CELLS_X) / 2, // left-of-center
ctrx2 = (GRID_MAX_POINTS_X) / 2, // right-of-center
xend = ctrx1;
#endif
#ifdef HALF_IN_Y
constexpr uint8_t ctry2 = 0, ylen = GRID_MAX_POINTS_Y - 1;
constexpr uint8_t ctry2 = 0, yend = GRID_MAX_POINTS_Y - 1;
#else
constexpr uint8_t ctry1 = (GRID_MAX_POINTS_Y - 1) / 2, // top-of-center
ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center
ylen = ctry1;
constexpr uint8_t ctry1 = (GRID_MAX_CELLS_Y) / 2, // top-of-center
ctry2 = (GRID_MAX_POINTS_Y) / 2, // bottom-of-center
yend = ctry1;
#endif
LOOP_LE_N(xo, xlen)
LOOP_LE_N(yo, ylen) {
LOOP_LE_N(xo, xend)
LOOP_LE_N(yo, yend) {
uint8_t x2 = ctrx2 + xo, y2 = ctry2 + yo;
#ifndef HALF_IN_X
const uint8_t x1 = ctrx1 - xo;
@ -143,8 +143,8 @@ void print_bilinear_leveling_grid() {
#if ENABLED(ABL_BILINEAR_SUBDIVISION)
#define ABL_GRID_POINTS_VIRT_X (GRID_MAX_POINTS_X - 1) * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_Y (GRID_MAX_POINTS_Y - 1) * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_X GRID_MAX_CELLS_X * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_GRID_POINTS_VIRT_Y GRID_MAX_CELLS_Y * (BILINEAR_SUBDIVISIONS) + 1
#define ABL_TEMP_POINTS_X (GRID_MAX_POINTS_X + 2)
#define ABL_TEMP_POINTS_Y (GRID_MAX_POINTS_Y + 2)
float z_values_virt[ABL_GRID_POINTS_VIRT_X][ABL_GRID_POINTS_VIRT_Y];
@ -161,7 +161,7 @@ void print_bilinear_leveling_grid() {
#define LINEAR_EXTRAPOLATION(E, I) ((E) * 2 - (I))
float bed_level_virt_coord(const uint8_t x, const uint8_t y) {
uint8_t ep = 0, ip = 1;
if (x > GRID_MAX_POINTS_X + 1 || y > GRID_MAX_POINTS_Y + 1) {
if (x > (GRID_MAX_POINTS_X) + 1 || y > (GRID_MAX_POINTS_Y) + 1) {
// The requested point requires extrapolating two points beyond the mesh.
// These values are only requested for the edges of the mesh, which are always an actual mesh point,
// and do not require interpolation. When interpolation is not needed, this "Mesh + 2" point is
@ -171,8 +171,8 @@ void print_bilinear_leveling_grid() {
}
if (!x || x == ABL_TEMP_POINTS_X - 1) {
if (x) {
ep = GRID_MAX_POINTS_X - 1;
ip = GRID_MAX_POINTS_X - 2;
ep = (GRID_MAX_POINTS_X) - 1;
ip = GRID_MAX_CELLS_X - 1;
}
if (WITHIN(y, 1, ABL_TEMP_POINTS_Y - 2))
return LINEAR_EXTRAPOLATION(
@ -187,8 +187,8 @@ void print_bilinear_leveling_grid() {
}
if (!y || y == ABL_TEMP_POINTS_Y - 1) {
if (y) {
ep = GRID_MAX_POINTS_Y - 1;
ip = GRID_MAX_POINTS_Y - 2;
ep = (GRID_MAX_POINTS_Y) - 1;
ip = GRID_MAX_CELLS_Y - 1;
}
if (WITHIN(x, 1, ABL_TEMP_POINTS_X - 2))
return LINEAR_EXTRAPOLATION(

View File

@ -36,7 +36,7 @@ constexpr uint8_t dim = _BV(ord);
static inline bool eval_candidate(int8_t x, int8_t y, hilbert_curve::callback_ptr func, void *data) {
// The print bed likely has fewer points than the full Hilbert
// curve, so cull unecessary points
return x < GRID_MAX_POINTS_X && y < GRID_MAX_POINTS_Y ? func(x, y, data) : false;
return x < (GRID_MAX_POINTS_X) && y < (GRID_MAX_POINTS_Y) ? func(x, y, data) : false;
}
bool hilbert_curve::hilbert(int8_t x, int8_t y, int8_t xi, int8_t xj, int8_t yi, int8_t yj, uint8_t n, hilbert_curve::callback_ptr func, void *data) {
@ -102,10 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt
*/
bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
// Find closest grid intersection
uint8_t grid_x = LROUND(float(pos.x - MESH_MIN_X) / MESH_X_DIST);
uint8_t grid_y = LROUND(float(pos.y - MESH_MIN_Y) / MESH_Y_DIST);
LIMIT(grid_x, 0, GRID_MAX_POINTS_X);
LIMIT(grid_y, 0, GRID_MAX_POINTS_Y);
const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
return search_from(grid_x, grid_y, func, data);
}

View File

@ -64,10 +64,10 @@
void mesh_bed_leveling::line_to_destination(const_feedRate_t scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
// Get current and destination cells for this line
xy_int8_t scel = cell_indexes(current_position), ecel = cell_indexes(destination);
NOMORE(scel.x, GRID_MAX_POINTS_X - 2);
NOMORE(scel.y, GRID_MAX_POINTS_Y - 2);
NOMORE(ecel.x, GRID_MAX_POINTS_X - 2);
NOMORE(ecel.y, GRID_MAX_POINTS_Y - 2);
NOMORE(scel.x, GRID_MAX_CELLS_X - 1);
NOMORE(scel.y, GRID_MAX_CELLS_Y - 1);
NOMORE(ecel.x, GRID_MAX_CELLS_X - 1);
NOMORE(ecel.y, GRID_MAX_CELLS_Y - 1);
// Start and end in the same cell? No split needed.
if (scel == ecel) {

View File

@ -32,8 +32,8 @@ enum MeshLevelingState : char {
MeshReset // G29 S5
};
#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
#define _GET_MESH_X(I) mbl.index_to_xpos[I]
#define _GET_MESH_Y(J) mbl.index_to_ypos[J]
#define Z_VALUES_ARR mbl.z_values
@ -61,7 +61,7 @@ public:
static inline void zigzag(const int8_t index, int8_t &px, int8_t &py) {
px = index % (GRID_MAX_POINTS_X);
py = index / (GRID_MAX_POINTS_X);
if (py & 1) px = (GRID_MAX_POINTS_X - 1) - px; // Zig zag
if (py & 1) px = (GRID_MAX_POINTS_X) - 1 - px; // Zig zag
}
static void set_zigzag_z(const int8_t index, const_float_t z) {
@ -72,11 +72,11 @@ public:
static int8_t cell_index_x(const_float_t x) {
int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST);
return constrain(cx, 0, (GRID_MAX_POINTS_X) - 2);
return constrain(cx, 0, GRID_MAX_CELLS_X - 1);
}
static int8_t cell_index_y(const_float_t y) {
int8_t cy = (y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST);
return constrain(cy, 0, (GRID_MAX_POINTS_Y) - 2);
return constrain(cy, 0, GRID_MAX_CELLS_Y - 1);
}
static inline xy_int8_t cell_indexes(const_float_t x, const_float_t y) {
return { cell_index_x(x), cell_index_y(y) };
@ -85,11 +85,11 @@ public:
static int8_t probe_index_x(const_float_t x) {
int8_t px = (x - (MESH_MIN_X) + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST);
return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
}
static int8_t probe_index_y(const_float_t y) {
int8_t py = (y - (MESH_MIN_Y) + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST);
return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
}
static inline xy_int8_t probe_indexes(const_float_t x, const_float_t y) {
return { probe_index_x(x), probe_index_y(y) };

View File

@ -190,7 +190,7 @@ void unified_bed_leveling::display_map(const int map_type) {
const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy);
if (!lcd) SERIAL_EOL();
for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
for (int8_t j = (GRID_MAX_POINTS_Y) - 1; j >= 0; j--) {
// Row Label (J index)
if (human) {
@ -217,7 +217,7 @@ void unified_bed_leveling::display_map(const int map_type) {
if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' '); // Display sign also for positive numbers (' ' for 0)
SERIAL_ECHO_F(f, 3); // Positive: 5 digits, Negative: 6 digits
}
if (csv && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR('\t');
if (csv && i < (GRID_MAX_POINTS_X) - 1) SERIAL_CHAR('\t');
// Closing Brace or Space
if (human) SERIAL_CHAR(is_current ? ']' : ' ');

View File

@ -38,8 +38,8 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP };
struct mesh_index_pair;
#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / float(GRID_MAX_POINTS_Y - 1))
#define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
#if ENABLED(OPTIMIZED_MESH_STORAGE)
typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
@ -142,19 +142,19 @@ public:
}
static int8_t cell_index_x_valid(const_float_t x) {
return WITHIN(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X - 2));
return WITHIN(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1);
}
static int8_t cell_index_y_valid(const_float_t y) {
return WITHIN(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y - 2));
return WITHIN(cell_index_y_raw(y), 0, GRID_MAX_CELLS_Y - 1);
}
static int8_t cell_index_x(const_float_t x) {
return constrain(cell_index_x_raw(x), 0, (GRID_MAX_POINTS_X) - 2);
return constrain(cell_index_x_raw(x), 0, GRID_MAX_CELLS_X - 1);
}
static int8_t cell_index_y(const_float_t y) {
return constrain(cell_index_y_raw(y), 0, (GRID_MAX_POINTS_Y) - 2);
return constrain(cell_index_y_raw(y), 0, GRID_MAX_CELLS_Y - 1);
}
static inline xy_int8_t cell_indexes(const_float_t x, const_float_t y) {
@ -164,11 +164,11 @@ public:
static int8_t closest_x_index(const_float_t x) {
const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
return WITHIN(px, 0, GRID_MAX_POINTS_X - 1) ? px : -1;
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
}
static int8_t closest_y_index(const_float_t y) {
const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
return WITHIN(py, 0, GRID_MAX_POINTS_Y - 1) ? py : -1;
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
}
static inline xy_int8_t closest_indexes(const xy_pos_t &xy) {
return { closest_x_index(xy.x), closest_y_index(xy.y) };
@ -204,10 +204,10 @@ public:
* the case where the printer is making a vertical line that only crosses horizontal mesh lines.
*/
static inline float z_correction_for_x_on_horizontal_mesh_line(const_float_t rx0, const int x1_i, const int yi) {
if (!WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(yi, 0, GRID_MAX_POINTS_Y - 1)) {
if (!WITHIN(x1_i, 0, (GRID_MAX_POINTS_X) - 1) || !WITHIN(yi, 0, (GRID_MAX_POINTS_Y) - 1)) {
if (DEBUGGING(LEVELING)) {
if (WITHIN(x1_i, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i");
if (WITHIN(x1_i, 0, (GRID_MAX_POINTS_X) - 1)) DEBUG_ECHOPGM("yi"); else DEBUG_ECHOPGM("x1_i");
DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_x_on_horizontal_mesh_line(rx0=", rx0, ",x1_i=", x1_i, ",yi=", yi, ")");
}
@ -218,19 +218,19 @@ public:
const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST),
z1 = z_values[x1_i][yi];
return z1 + xratio * (z_values[_MIN(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
// If it is, it is clamped to the last element of the
// z_values[][] array and no correction is applied.
return z1 + xratio * (z_values[_MIN(x1_i, (GRID_MAX_POINTS_X) - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
// If it is, it is clamped to the last element of the
// z_values[][] array and no correction is applied.
}
//
// See comments above for z_correction_for_x_on_horizontal_mesh_line
//
static inline float z_correction_for_y_on_vertical_mesh_line(const_float_t ry0, const int xi, const int y1_i) {
if (!WITHIN(xi, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(y1_i, 0, GRID_MAX_POINTS_Y - 1)) {
if (!WITHIN(xi, 0, (GRID_MAX_POINTS_X) - 1) || !WITHIN(y1_i, 0, (GRID_MAX_POINTS_Y) - 1)) {
if (DEBUGGING(LEVELING)) {
if (WITHIN(xi, 0, GRID_MAX_POINTS_X - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi");
if (WITHIN(xi, 0, (GRID_MAX_POINTS_X) - 1)) DEBUG_ECHOPGM("y1_i"); else DEBUG_ECHOPGM("xi");
DEBUG_ECHOLNPAIR(" out of bounds in z_correction_for_y_on_vertical_mesh_line(ry0=", ry0, ", xi=", xi, ", y1_i=", y1_i, ")");
}
@ -241,9 +241,9 @@ public:
const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST),
z1 = z_values[xi][y1_i];
return z1 + yratio * (z_values[xi][_MIN(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
// If it is, it is clamped to the last element of the
// z_values[][] array and no correction is applied.
return z1 + yratio * (z_values[xi][_MIN(y1_i, (GRID_MAX_POINTS_Y) - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
// If it is, it is clamped to the last element of the
// z_values[][] array and no correction is applied.
}
/**
@ -266,11 +266,11 @@ public:
const float z1 = calc_z0(rx0,
mesh_index_to_xpos(cx), z_values[cx][cy],
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][cy]);
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1][cy]);
const float z2 = calc_z0(rx0,
mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1],
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, GRID_MAX_POINTS_X - 2) + 1][_MIN(cy, GRID_MAX_POINTS_Y - 2) + 1]);
mesh_index_to_xpos(cx), z_values[cx][_MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1],
mesh_index_to_xpos(cx + 1), z_values[_MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1][_MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1]);
float z0 = calc_z0(ry0,
mesh_index_to_ypos(cy), z1,
@ -302,10 +302,10 @@ public:
static inline float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); }
static inline float mesh_index_to_xpos(const uint8_t i) {
return i < GRID_MAX_POINTS_X ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
}
static inline float mesh_index_to_ypos(const uint8_t i) {
return i < GRID_MAX_POINTS_Y ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
}
#if UBL_SEGMENTED

View File

@ -433,8 +433,7 @@ void unified_bed_leveling::G29() {
SERIAL_DECIMAL(param.XY_pos.y);
SERIAL_ECHOLNPGM(").\n");
}
const xy_pos_t near_probe_xy = param.XY_pos + probe.offset_xy;
probe_entire_mesh(near_probe_xy, parser.seen('T'), parser.seen('E'), parser.seen('U'));
probe_entire_mesh(param.XY_pos, parser.seen('T'), parser.seen('E'), parser.seen('U'));
report_current_position();
probe_deployed = true;
@ -1140,8 +1139,9 @@ bool unified_bed_leveling::G29_parse_parameters() {
}
// If X or Y are not valid, use center of the bed values
if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = X_CENTER;
if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = Y_CENTER;
// (for UBL_HILBERT_CURVE default to lower-left corner instead)
if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, X_CENTER);
if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, Y_CENTER);
if (err_flag) return UBL_ERR;

View File

@ -397,8 +397,8 @@
int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)),
int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST))
};
LIMIT(icell.x, 0, (GRID_MAX_POINTS_X) - 1);
LIMIT(icell.y, 0, (GRID_MAX_POINTS_Y) - 1);
LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
float z_x0y0 = z_values[icell.x ][icell.y ], // z at lower left corner
z_x1y0 = z_values[icell.x+1][icell.y ], // z at upper left corner