Exposed exaggeration factor when rendering heightmap.

Added checkbox to select whether to run autoleveled program or not.
Heightmap can handle non integer from_x and to_x.
This commit is contained in:
2023-05-23 14:28:08 +03:00
parent 4e7e059e22
commit b7b9fed0dd
8 changed files with 118 additions and 143 deletions
+35 -27
View File
@@ -38,7 +38,7 @@ void grbl::machine::on_disconnected(grbl::transport *transport) {
switch_to_state(grbl_machine_state::disconnected);
}
grbl::realtime_status_report grbl::parse_status_report(std::string line, grbl::realtime_status_report& result) {
grbl::realtime_status_report grbl::parse_status_report(std::string line, grbl::realtime_status_report &result) {
// grbl::realtime_status_report result;
// pin values are always reset when a report arrives
@@ -71,7 +71,7 @@ grbl::realtime_status_report grbl::parse_status_report(std::string line, grbl::r
result.buffers_free = std::stoi(p[0]);
result.rx_chars_free = std::stoi(p[1]);
} else if (elements[0] == "Pn") {
for (auto& c: elements[1]) {
for (auto &c: elements[1]) {
switch (c) {
case 'P':
result.signals.bit.probe = true;
@@ -111,7 +111,7 @@ grbl::realtime_status_report grbl::parse_status_report(std::string line, grbl::r
}
grbl::machine_status grbl::status_from_string(const std::string& status) {
grbl::machine_status grbl::status_from_string(const std::string &status) {
if (status == "Idle") return machine_status::idle;
if (status == "Run") return machine_status::run;
if (status == "Hold") return machine_status::hold;
@@ -125,9 +125,10 @@ grbl::machine_status grbl::status_from_string(const std::string& status) {
return machine_status::unknown;
}
void grbl::machine::check_program(const grbl::program& pgm) {
void grbl::machine::check_program(const grbl::program &pgm) {
running_program = pgm;
std::cout << "checking program (" << running_program.filename << ") with " << running_program.number_of_instructions()
std::cout << "checking program (" << running_program.filename << ") with "
<< running_program.number_of_instructions()
<< " instructions" << std::endl;
switch_to_state(grbl_machine_state::check_program);
}
@@ -149,9 +150,10 @@ void grbl::machine::set_work_offset(std::string work_offset) {
}
void grbl::machine::run_program(const grbl::program& pgm, const std::string& work_offset) {
void grbl::machine::run_program(const grbl::program &pgm, const std::string &work_offset) {
running_program = pgm;
std::cout << "running program (" << running_program.filename << ") with " << running_program.number_of_instructions() << " instructions"
std::cout << "running program (" << running_program.filename << ") with "
<< running_program.number_of_instructions() << " instructions"
<< " on work offset " << work_offset << std::endl;
set_work_offset(work_offset);
@@ -159,7 +161,7 @@ void grbl::machine::run_program(const grbl::program& pgm, const std::string& wor
switch_to_state(grbl_machine_state::run_program);
}
std::string grbl::status_to_string(const grbl::machine_status& status) {
std::string grbl::status_to_string(const grbl::machine_status &status) {
switch (status) {
case machine_status::idle:
return "Idle";
@@ -590,11 +592,11 @@ void grbl::machine::switch_to_state(grbl::grbl_machine_state new_state) {
states[state]->on_enter(this);
}
const std::map<std::string, std::string, grbl::settings_cmp>& grbl::machine::get_settings() const {
const std::map<std::string, std::string, grbl::settings_cmp> &grbl::machine::get_settings() const {
return settings;
}
const std::map<std::string, std::string, grbl::parameters_cmp>& grbl::machine::get_parameters() const {
const std::map<std::string, std::string, grbl::parameters_cmp> &grbl::machine::get_parameters() const {
return parameters;
}
@@ -683,7 +685,7 @@ void grbl::machine::start_z_probe(float min_z, float feed_rate) {
awaiting_responses++;
}
void grbl::machine::probe_heightmap(grbl::heightmap& grid) {
void grbl::machine::probe_heightmap(grbl::heightmap &grid) {
std::cout << "probing heightmap" << std::endl;
dynamic_cast<machine_state_heightmap_probing *>(states[grbl_machine_state::heightmap_probing])->grid = &grid;
switch_to_state(grbl_machine_state::heightmap_probing);
@@ -756,7 +758,8 @@ void grbl::machine_state_init::on_line_received(std::string line) {
if (starts_with(line, "$")) {
auto pieces = split_string(line, "=");
cnc->settings[pieces[0]] = pieces[1];
} else if (starts_with(line, "[G") || starts_with(line, "[H") || starts_with(line, "[T") || starts_with(line, "[P")) {
} else if (starts_with(line, "[G") || starts_with(line, "[H") || starts_with(line, "[T") ||
starts_with(line, "[P")) {
line = line.substr(1, line.size() - 2);
// TODO: some parameters have more than two :
auto pieces = split_string(line, ":");
@@ -833,7 +836,8 @@ void grbl::machine_state_idle::on_line_received(std::string line) {
} else if (starts_with(line, "$")) {
auto pieces = split_string(line, "=");
cnc->settings[pieces[0]] = pieces[1];
} else if (starts_with(line, "[G") || starts_with(line, "[H") || starts_with(line, "[T") || starts_with(line, "[P")) {
} else if (starts_with(line, "[G") || starts_with(line, "[H") || starts_with(line, "[T") ||
starts_with(line, "[P")) {
line = line.substr(1, line.size() - 2);
// TODO: some parameters have more than two :
auto pieces = split_string(line, ":");
@@ -948,7 +952,8 @@ bool grbl::machine_state_check_program::continue_program() {
instruction to_send;
do {
to_send = cnc->running_program.instruction_at(cnc->executed_instructions++);
} while (to_send.type != instruction_type::gcode && cnc->executed_instructions < cnc->running_program.number_of_instructions());
} while (to_send.type != instruction_type::gcode &&
cnc->executed_instructions < cnc->running_program.number_of_instructions());
if (to_send.type == instruction_type::gcode) {
cnc->pipe->send(to_send.command);
@@ -1014,7 +1019,8 @@ bool grbl::machine_state_run_program::continue_program() {
instruction to_send;
do {
to_send = cnc->running_program.instruction_at(cnc->executed_instructions++);
} while (to_send.type != instruction_type::gcode && cnc->executed_instructions < cnc->running_program.number_of_instructions());
} while (to_send.type != instruction_type::gcode &&
cnc->executed_instructions < cnc->running_program.number_of_instructions());
if (to_send.type == instruction_type::gcode) {
cnc->pipe->send(to_send.command);
@@ -1116,21 +1122,23 @@ bool grbl::machine_state_heightmap_probing::continue_program() {
void grbl::machine_state_heightmap_probing::move_to_next_stage() {
switch (stage) {
case heightmap_probing_stage::start:
cnc->pipe->send("G0X0Y0Z15");
cnc->pipe->send("G0 X" + std::to_string(grid->vertices[0].x) + " Y" +
std::to_string(grid->vertices[0].y) + "Z0.5");
stage = heightmap_probing_stage::goto_home;
break;
case heightmap_probing_stage::goto_home:
cnc->pipe->send("G38.2 Z-65 F100");
cnc->pipe->send("G38.2 Z-65 F5");
stage = heightmap_probing_stage::initial_probe_step_back;
break;
case heightmap_probing_stage::initial_probe_step_back:
// step back a bit (1mm, relative)
cnc->pipe->send("G91 G0 Z1");
cnc->pipe->send("G91 G0 Z0.3");
stage = heightmap_probing_stage::initial_probe_fine_seek;
break;
case heightmap_probing_stage::initial_probe_fine_seek:
// probe again but finer
cnc->pipe->send(" G38.2 Z-5 F5");
cnc->pipe->send("G38.2 Z-1 F5");
stage = heightmap_probing_stage::initial_probe;
break;
case heightmap_probing_stage::initial_probe:
@@ -1147,7 +1155,6 @@ void grbl::machine_state_heightmap_probing::move_to_next_stage() {
grid->vertices[probed_locations].z = 0;
}
stage = heightmap_probing_stage::goto_next_location;
break;
case heightmap_probing_stage::goto_next_location: {
@@ -1172,7 +1179,7 @@ void grbl::machine_state_heightmap_probing::move_to_next_stage() {
cnc->pipe->send("G0Z15"); // safe height
stage = heightmap_probing_stage::done;
} else {
cnc->pipe->send("G90 G0 Z1.5");
cnc->pipe->send("G90 G0 Z1");
stage = heightmap_probing_stage::goto_next_location_move;
}
break;
@@ -1182,13 +1189,13 @@ void grbl::machine_state_heightmap_probing::move_to_next_stage() {
stage = heightmap_probing_stage::goto_start_probing_at;
break;
case heightmap_probing_stage::goto_start_probing_at:
cnc->pipe->send("G0 Z0.5"); // this appears to move Z upwards instead of downwards. why?
cnc->pipe->send("G0 Z0.3"); // this appears to move Z upwards instead of downwards. why?
// faking the G0 Z0.5
// cnc->pipe->send("G91 G0 Z-1"); // 1.5 - 1 = 0.5.//
stage = heightmap_probing_stage::probing;
break;
case heightmap_probing_stage::probing:
cnc->pipe->send("G38.2 Z-5 F5");
cnc->pipe->send("G38.2 Z-1 F5");
stage = heightmap_probing_stage::goto_next_location;
break;
case heightmap_probing_stage::done:
@@ -1208,17 +1215,17 @@ grbl::machine_event_disconnect::machine_event_disconnect() {
machine_event::type = machine_event_type::disconnected;
}
grbl::machine_event_report_received::machine_event_report_received(const grbl::realtime_status_report& r)
grbl::machine_event_report_received::machine_event_report_received(const grbl::realtime_status_report &r)
: report(r) {
machine_event::type = machine_event_type::report_received;
}
grbl::machine_event_banner::machine_event_banner(const std::string& b)
grbl::machine_event_banner::machine_event_banner(const std::string &b)
: banner{b} {
machine_event::type = machine_event_type::banner;
}
grbl::machine_event_message::machine_event_message(const std::string& m)
grbl::machine_event_message::machine_event_message(const std::string &m)
: message{m} {
machine_event::type = machine_event_type::message;
}
@@ -1260,7 +1267,8 @@ grbl::machine_event_probe_result::machine_event_probe_result(bool touched, const
machine_event::type = machine_event_type::probe_result;
}
grbl::machine_event_heightmap_probe_acquired::machine_event_heightmap_probe_acquired(grbl::heightmap *g, size_t location)
grbl::machine_event_heightmap_probe_acquired::machine_event_heightmap_probe_acquired(grbl::heightmap *g,
size_t location)
: grid(g),
probed_location(location) {
machine_event::type = machine_event_type::heightmap_probe_acquired;
+20 -16
View File
@@ -30,8 +30,8 @@ grbl::heightmap grbl::heightmap::from_params(float from_x, float from_y, float t
size_t grbl::heightmap::index_from_coords(float x, float y) const {
size_t result = 0;
for (auto& v: vertices) {
if (v.x == x && v.y == y) {
for (auto &v: vertices) {
if (float_equal(v.x, x) && float_equal(v.y, y)) {
return result;
}
result++;
@@ -44,21 +44,25 @@ float grbl::heightmap::get_z_at(float x, float y) const {
// TODO: make faster by precalculating indices
float x1 = x - fmodf(x, resolution);
float x2 = x1 + resolution;
float y1 = y - fmodf(y, resolution);
float y2 = y1 + resolution;
float z11 = vertices[index_from_coords(x1, y1)].z;
float z12 = vertices[index_from_coords(x1, y2)].z;
float z21 = vertices[index_from_coords(x2, y1)].z;
float z22 = vertices[index_from_coords(x2, y2)].z;
double x1 = x - fmod(x - from_x, resolution);
double x2 = x1 + resolution;
double y1 = y - fmod(y - from_y, resolution);
double y2 = y1 + resolution;
double z11 = vertices[index_from_coords(x1, y1)].z;
double z12 = vertices[index_from_coords(x1, y2)].z;
double z21 = vertices[index_from_coords(x2, y1)].z;
double z22 = vertices[index_from_coords(x2, y2)].z;
float alpha_x = (x - x1) / resolution;
float a = z11 + (z21 - z11) * alpha_x;
float b = z12 + (z22 - z12) * alpha_x;
double alpha_x = (x - x1) / (double) resolution;
double a = z11 + (z21 - z11) * alpha_x;
double b = z12 + (z22 - z12) * alpha_x;
float alpha_y = (y - y1) / resolution;
float c = a + (b - a) * alpha_y;
double alpha_y = (y - y1) / (double) resolution;
double c = a + (b - a) * alpha_y;
return c;
return (float) c;
}
bool grbl::float_equal(float a, float b) {
return fabs(a - b) < 0.0001;
}
+4 -3
View File
@@ -7,7 +7,9 @@
namespace grbl {
struct heightmap {
bool float_equal(float a, float b);
struct heightmap {
static heightmap from_params(float from_x, float from_y, float to_x, float to_y, float resolution);
float get_z_at(float x, float y) const;
size_t index_from_coords(float x, float y) const;
@@ -17,7 +19,6 @@ struct heightmap {
float resolution;
size_t x_segments, y_segments;
std::vector<glm::vec3> vertices;
};
};
}
+23
View File
@@ -24,3 +24,26 @@ TEST(heightmap, get_z_at) {
z = grid.get_z_at(1, 0.5f);
EXPECT_EQ(2, z);
}
TEST(heightmap, get_z_at_non_zero_origin) {
auto grid = grbl::heightmap::from_params(0 - 0.123, 0 + 0.234, 1 - 0.123, 1 + 0.234, 1);
grid.vertices[0].z = 0;
grid.vertices[1].z = 1;
grid.vertices[2].z = 2;
grid.vertices[3].z = 3;
auto z = grid.get_z_at(0.5f - 0.123f, 0.5f + 0.234f);
EXPECT_EQ(true, grbl::float_equal(1.5, z));
z = grid.get_z_at(0.5f - 0.123f, 0 + 0.234f);
EXPECT_EQ(true, grbl::float_equal(0.5, z));
z = grid.get_z_at(0.5f - 0.123f, 1 + 0.234f);
EXPECT_EQ(true, grbl::float_equal(2.5, z));
z = grid.get_z_at(0 - 0.123f, 0.5f + 0.234f);
EXPECT_EQ(true, grbl::float_equal(1, z));
z = grid.get_z_at(1 - 0.123f, 0.5f + 0.234f);
EXPECT_EQ(true, grbl::float_equal(2, z));
}
+1 -81
View File
@@ -349,85 +349,6 @@ GLsizei grbl::program_renderer::update_model_vbo(const grbl::program &pgm) {
min_pos = glm::vec3(std::numeric_limits<float>::max());
max_pos = glm::vec3(std::numeric_limits<float>::min());
min_pos = max_pos = glm::vec3(0);
/*
static auto movement_re = std::regex(R"(([gG]0*1?\s+|[xXyYzZ]\s*[0-9\.\-]+))");
bool is_tool_on = false;
glm::vec3 tool_pos;
min_pos = max_pos = tool_pos = glm::vec3(0);
std::vector<float> buffer_data;
for (auto& i: pgm.instructions) {
if (i.type == grbl::instruction_type::gcode) {
std::vector<std::string> tokens;
std::smatch res;
std::string::const_iterator start(i.command.cbegin());
while (std::regex_search(start, i.command.cend(), res, movement_re)) {
auto str = res[0].str();
// make upper case
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
// remove whitespace from things like "X 123.1234"
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
tokens.push_back(str);
start = res.suffix().first;
}
if (!tokens.empty()) {
auto new_pos = tool_pos;
for (auto& t: tokens) {
if (t[0] == 'X') {
new_pos.x = std::stof(t.substr(1));
} else if (t[0] == 'Y') {
new_pos.y = std::stof(t.substr(1));
} else if (t[0] == 'Z') {
new_pos.z = std::stof(t.substr(1));
}
}
bool has_g1 = tokens[0][0] == 'G' && std::stoi(tokens[0].substr(1)) == 1;
bool has_g0 = tokens[0][0] == 'G' && std::stoi(tokens[0].substr(1)) == 0;
bool is_plunge = has_g1 && tokens.size() > 1 && tokens[1][0] == 'Z';
bool is_retract = has_g0 && tokens.size() > 1 && tokens[1][0] == 'Z';
is_tool_on = has_g1 || (is_retract ? false : is_tool_on);
auto from_color = glm::vec4(1.0f);
auto to_color = glm::vec4(1.0f);
if (is_tool_on) {
from_color = glm::vec4(1, 0.6, 0.6, 1);
to_color = glm::vec4(1, 0.6, 0.6, 1);
}
if (is_plunge) {
to_color = glm::vec4(1, 0.6, 0.6, 1);
} else if (is_retract) {
to_color = glm::vec4(0.6, 1, 0.6, 1);
}
add_line(buffer_data, tool_pos, from_color, new_pos, to_color);
// calculate extents
min_pos.x = std::min(min_pos.x, new_pos.x);
min_pos.y = std::min(min_pos.y, new_pos.y);
min_pos.z = std::min(min_pos.z, new_pos.z);
max_pos.x = std::max(max_pos.x, new_pos.x);
max_pos.y = std::max(max_pos.y, new_pos.y);
max_pos.z = std::max(max_pos.z, new_pos.z);
tool_pos = new_pos;
}
}
}
*/
std::vector<float> buffer_data;
grbl::grbl_parser parser;
@@ -475,7 +396,7 @@ GLsizei grbl::program_renderer::update_model_vbo(const grbl::program &pgm) {
}
void grbl::program_renderer::update_grid(const grbl::heightmap &grid) {
void grbl::program_renderer::update_grid(const grbl::heightmap &grid, float exaggeration_factor) {
glm::vec4 color = {0.5, 0.3, 0, 1};
@@ -496,7 +417,6 @@ void grbl::program_renderer::update_grid(const grbl::heightmap &grid) {
auto p3 = grid.vertices[next];
// exaggerate Z
auto exaggeration_factor = 100.0f;
p1.z *= exaggeration_factor;
p2.z *= exaggeration_factor;
p3.z *= exaggeration_factor;
+1 -1
View File
@@ -19,7 +19,7 @@ public:
glm::vec3 get_extents_max() const { return max_pos; };
void update_grid(const grbl::heightmap& grid);
void update_grid(const grbl::heightmap& grid, float exaggeration_factor);
private:
GLsizei update_model_vbo(const grbl::program& pgm);
void update_model_extents(glm::vec3 point);
+24 -7
View File
@@ -102,7 +102,7 @@ void SenderApp::add_work_parameters_markup() {
auto work_btn_holder = work_holder->add<nanogui::Widget>();
work_btn_holder->set_layout(
new nanogui::GridLayout(nanogui::Orientation::Horizontal, 3, nanogui::Alignment::Fill, 0, 6));
new nanogui::GridLayout(nanogui::Orientation::Horizontal, 4, nanogui::Alignment::Fill, 0, 6));
btn_load_program = work_btn_holder->add<nanogui::Button>("Load");
@@ -132,12 +132,16 @@ void SenderApp::add_work_parameters_markup() {
btn_run_program = work_btn_holder->add<nanogui::Button>("Run");
// btnRunProgram->set_enabled(false);
btn_run_program->set_callback([&] {
// auto leveled_pgm = pgm.apply_heightmap(heightmap_grid);
// leveled_pgm.save("output_corrected6.nc");
cnc.run_program(pgm, "G" + std::to_string(cbo_work_offset->selected_index() + 54));
auto leveled_pgm = pgm.apply_heightmap(heightmap_grid);
leveled_pgm.save("last-run-autoleveled.nc");
cnc.run_program(btn_run_autoleveled->pushed() ? leveled_pgm : pgm,
"G" + std::to_string(cbo_work_offset->selected_index() + 54));
});
btn_run_program->set_tooltip("Execute program");
btn_run_autoleveled = work_btn_holder->add<nanogui::Button>("", FA_TABLE);
btn_run_autoleveled->set_flags(nanogui::Button::ToggleButton);
btn_run_autoleveled->set_tooltip("Run auto-leveled program version, using the current heightmap");
}
void SenderApp::add_status_markup() {
@@ -490,7 +494,7 @@ void SenderApp::add_heightmap_markup() {
if (!path.empty()) {
heightmap_grid = load_heightmap(path);
fill_heightmap_controls_from_grid(heightmap_grid);
renderer.update_grid(heightmap_grid);
renderer.update_grid(heightmap_grid, std::stof(exaggeration_factors[cbo_exaggeration->selected_index()]));
}
});
@@ -566,6 +570,19 @@ void SenderApp::add_heightmap_markup() {
save_heightmap(heightmap_grid, path);
}
});
heightmap_layer->add<nanogui::Label>("Grid rendering", "sans-bold", 20);
auto heightmap_render_holder = heightmap_layer->add<nanogui::Widget>();
heightmap_render_holder->set_layout(
new nanogui::GridLayout(nanogui::Orientation::Horizontal, 2, nanogui::Alignment::Fill, 4, 4));
heightmap_render_holder->add<nanogui::Label>("Exaggeration factor");
cbo_exaggeration = heightmap_render_holder->add<nanogui::ComboBox>(exaggeration_factors);
cbo_exaggeration->set_callback([&](int idx) {
renderer.update_grid(heightmap_grid, std::stof(exaggeration_factors[cbo_exaggeration->selected_index()]));
});
}
void SenderApp::fill_heightmap_from_model() const {
@@ -590,7 +607,7 @@ void SenderApp::update_grid() {
to_y != heightmap_grid.to_y ||
res != heightmap_grid.resolution) {
heightmap_grid = std::move(grbl::heightmap::from_params(from_x, from_y, to_x, to_y, res));
renderer.update_grid(heightmap_grid);
renderer.update_grid(heightmap_grid, std::stof(exaggeration_factors[cbo_exaggeration->selected_index()]));
}
}
@@ -996,7 +1013,7 @@ void SenderApp::draw(NVGcontext *ctx) {
case grbl::machine_event_type::heightmap_probe_acquired: {
std::cout << "Updating grid" << std::endl;
auto ev = dynamic_cast<grbl::machine_event_heightmap_probe_acquired *>(event.get());
renderer.update_grid(*ev->grid);
renderer.update_grid(*ev->grid, std::stof(exaggeration_factors[cbo_exaggeration->selected_index()]));
break;
}
}
+3 -1
View File
@@ -115,12 +115,13 @@ private:
nanogui::Widget *parameters_layer = nullptr;
nanogui::TextBox *mpos_x_text = nullptr, *mpos_y_text = nullptr, *mpos_z_text = nullptr;
nanogui::ComboBox *cbo_work_offset = nullptr, *cbo_tool = nullptr, *cbo_jog_feed_rates = nullptr, *cbo_jog_distance = nullptr;
nanogui::ComboBox *cbo_work_offset = nullptr, *cbo_tool = nullptr, *cbo_jog_feed_rates = nullptr, *cbo_jog_distance = nullptr, *cbo_exaggeration = nullptr;
nanogui::ToolButton *btn_pin_door = nullptr, *btn_pin_hold = nullptr, *btn_pin_reset = nullptr, *btn_pin_cycle_start = nullptr;
nanogui::ToolButton *btn_pin_limit_x = nullptr, *btn_pin_limit_y = nullptr, *btn_pin_limit_z = nullptr, *btn_pin_probe = nullptr;
nanogui::Button *btn_keyboard_jog = nullptr;
nanogui::Button *btn_run_autoleveled = nullptr;
std::stringstream dro_ss;
grbl::heightmap heightmap_grid;
@@ -136,6 +137,7 @@ private:
std::vector<std::string> jog_distances = {"0.01", "0.1", "1", "10"};
std::vector<std::string> jog_feed_rates = {"5", "100", "500", "1000"};
std::vector<std::string> exaggeration_factors = {"0", "1", "5", "10", "20", "50", "100"};
int last_alarm = 0;