feat:gcodechecker support multi nozzle

Change-Id: If9695a7c0117aefb9e91d10e8224eb21314c166d
This commit is contained in:
BBL\chuan.he 2024-12-11 19:46:59 +08:00 committed by lane.wei
parent 22b3446ba3
commit ee6c46cbd4
2 changed files with 119 additions and 16 deletions

View File

@ -28,6 +28,8 @@ const std::string nozzle_temperature_initial_layer_Tag = " nozzle_temperature_i
const std::string Z_HEIGHT_TAG = " Z_HEIGHT: ";
const std::string Initial_Layer_Ptint_Height_Tag = " initial_layer_print_height =";
const std::string Line_Width_Tag = " line_width =";
const std::string Filament_Map_Tag = " filament_map =";
const std::string Physical_Extruder_Map_Tag = " physical_extruder_map =";
GCodeCheckResult GCodeChecker::parse_file(const std::string& path)
{
@ -38,7 +40,12 @@ GCodeCheckResult GCodeChecker::parse_file(const std::string& path)
}
std::string line_raw;
std::string line;
int line_number = 0;
while (std::getline(file, line_raw)) {
line_number++;
const char *c = line_raw.c_str();
c = skip_whitespaces(c);
if (std::toupper(*c) == 'N')
@ -46,7 +53,8 @@ GCodeCheckResult GCodeChecker::parse_file(const std::string& path)
c = skip_whitespaces(c);
line = c;
if (parse_line(line) != GCodeCheckResult::Success) {
std::cout << "Failed to parse line " << line_raw << std::endl;
std::cerr << "Failed to parse line " << line_number
<< ": " << line_raw << std::endl;
return GCodeCheckResult::ParseFailed;
}
}
@ -115,17 +123,32 @@ GCodeCheckResult GCodeChecker::parse_comment(GCodeLine& line)
if (starts_with(comment, Extrusion_Role_Tag)) {
m_role = string_to_role(comment.substr(Extrusion_Role_Tag.length()));
check_gap_infill_width = false;
double check_nozzle_temp = 0.0f;
if (is_multi_nozzle == true) {
check_nozzle_temp = multi_nozzle_temp[current_nozzle_id];
}
else
{
check_nozzle_temp = nozzle_temp;
}
if (m_role == erExternalPerimeter) {
if (z_height == initial_layer_height && nozzle_temp != nozzle_temperature_initial_layer[filament_id]) {
std::cout << "invalid filament nozzle initial layer temperature comment with invalid value!" << std::endl;
if (z_height == initial_layer_height && check_nozzle_temp != nozzle_temperature_initial_layer[filament_id]) {
std::cout << "Invalid filament nozzle initial layer temperature! Expected: "
<< nozzle_temperature_initial_layer[filament_id]
<< ", but got: " << check_nozzle_temp << "." << std::endl;
return GCodeCheckResult::ParseFailed;
}
if (z_height != initial_layer_height && nozzle_temp != nozzle_temperature[filament_id]) {
std::cout << "invalid filament nozzle temperature comment with invalid value!" << std::endl;
if (z_height != initial_layer_height && check_nozzle_temp != nozzle_temperature[filament_id]) {
std::cout << "Invalid filament nozzle temperature! Expected: "
<< nozzle_temperature[filament_id]
<< ", but got: " << check_nozzle_temp << "." << std::endl;
return GCodeCheckResult::ParseFailed;
}
} else if (m_role == erGapFill) {
}
else if (m_role == erGapFill) {
check_gap_infill_width = true;
}
@ -189,7 +212,36 @@ GCodeCheckResult GCodeChecker::parse_comment(GCodeLine& line)
std::cout << "invalid nozzle temperature initial layer comment with invalid value!" << std::endl;
return GCodeCheckResult::ParseFailed;
}
} else if (starts_with(comment, Z_HEIGHT_TAG)) {
}
else if (starts_with(comment, Filament_Map_Tag)) {
std::string str = comment.substr(Filament_Map_Tag.size() + 1);
if (!parse_double_from_str(str, filament_map)) {
std::cout << "invalid filament map comment with invalid value!" << std::endl;
return GCodeCheckResult::ParseFailed;
}
else {
for (size_t i = 0; i < filament_map.size(); ++i) {
filament_map[i] -= 1;
}
is_multi_nozzle = true;
}
}
else if (starts_with(comment, Physical_Extruder_Map_Tag)) {
std::string str = comment.substr(Physical_Extruder_Map_Tag.size() + 1);
std::vector<double>tmp;
if (!parse_double_from_str(str, tmp)){
std::cout << "invalid physical extruder map comment with invalid value!" << std::endl;
return GCodeCheckResult::ParseFailed;
}
for (size_t idx = 0; idx < tmp.size(); ++idx) {
physical_to_logic_extruder_map[(int)(tmp[idx])]= idx;
logic_to_physical_extruder_map[idx] = (int)(tmp[idx]);
}
}
else if (starts_with(comment, Z_HEIGHT_TAG)) {
std::string str = comment.substr(Z_HEIGHT_TAG.size());
if (!parse_double_from_str(str, z_height)) {
std::cout << "invalid z height comment with invalid value!" << std::endl;
@ -257,7 +309,7 @@ GCodeCheckResult GCodeChecker::parse_command(GCodeLine& gcode_line)
case 'T':{
int pt = ::atoi(&cmd[1]);
if (pt == 1000 || pt == 1100 || pt == 255 || pt == 1001) {
if (pt == 1000 || pt == 1100 || pt == 255 || pt == 1001 || pt == 65535 || pt == 65279) {
break;
}
@ -267,6 +319,12 @@ GCodeCheckResult GCodeChecker::parse_command(GCodeLine& gcode_line)
break;
}
filament_id = pt;
if (is_multi_nozzle == true) {
set_current_nozzle(pt);
}
flow_ratio = filament_flow_ratio[pt];
break;
}
@ -480,21 +538,45 @@ GCodeCheckResult GCodeChecker::parse_M83(const GCodeLine& gcode_line)
}
GCodeCheckResult GCodeChecker::parse_M104_M109(const GCodeLine &gcode_line)
{
{
const char *c = gcode_line.m_raw.c_str();
const char *rs = strchr(c,'S');
std::string str=rs;
str = str.substr(1);
for (int i = 0; i < str.size(); i++) {
if (str[i] == ' ')
str=str.substr(0,i);
std::string strS = rs;
strS = strS.substr(1);
for (int i = 0; i < strS.size(); i++) {
if (strS[i] == ' ')
strS = strS.substr(0,i);
}
if (!parse_double_from_str(str, nozzle_temp)) {
double temp_nozzle_temp;
if (!parse_double_from_str(strS, temp_nozzle_temp)) {
std::cout << "invalid nozzle temperature comment with invalid value!" << std::endl;
return GCodeCheckResult::ParseFailed;
}
if (is_multi_nozzle == true) {
const char* rt = strchr(c, 'T');
if (rt) {
std::string strT = rt + 1; // 跳过 'T'
for (size_t i = 0; i < strT.size(); i++) {
if (strT[i] == ' ') {
strT = strT.substr(0, i);
break;
}
}
int logic_nozzle_id = physical_to_logic_extruder_map[std::stoi(strT)];
multi_nozzle_temp[logic_nozzle_id] = temp_nozzle_temp;
}
else
{
multi_nozzle_temp[current_nozzle_id] = temp_nozzle_temp;
}
}
else {
nozzle_temp = temp_nozzle_temp;
}
return GCodeCheckResult::Success;
}
@ -768,6 +850,16 @@ GCodeCheckResult GCodeChecker::check_G2_G3_width(const GCodeLine& line)
return GCodeCheckResult::Success;
}
void GCodeChecker::set_current_nozzle(int filament_id) {
if (filament_id >= 0 && filament_id < static_cast<int>(filament_map.size())) {
current_nozzle_id = filament_map[filament_id];
}
else {
std::cerr << "Error: filament_id is out of range!" << std::endl;
current_nozzle_id = 0;
}
}
const std::map<std::string, ExtrusionRole> string_to_role_map = {
{ "Inner wall", erPerimeter },
{ "Outer wall", erExternalPerimeter },

View File

@ -5,7 +5,7 @@
#include <string>
#include <vector>
#include <array>
#include <map>
namespace BambuStudio {
enum class GCodeCheckResult : unsigned char
@ -116,6 +116,7 @@ private:
GCodeCheckResult check_line_width(const GCodeLine& gcode_line);
GCodeCheckResult check_G0_G1_width(const GCodeLine& gcode_line);
GCodeCheckResult check_G2_G3_width(const GCodeLine& gcode_line);
void set_current_nozzle(int id);
double calculate_G1_width(const std::array<double, 3>& source,
const std::array<double, 3>& target,
@ -214,12 +215,22 @@ private:
bool check_gap_infill_width = false;
int filament_id;
double flow_ratio = 0;
double nozzle_temp = 0.0f;
std::array<double, 2> multi_nozzle_temp = { 0.0, 0.0 };
int current_nozzle_id = 0;
std::vector<double> filament_map;
std::map<int, int> physical_to_logic_extruder_map;
std::map<int, int> logic_to_physical_extruder_map;
std::vector<double> filament_flow_ratio;
std::vector<double> nozzle_temperature;
std::vector<double> nozzle_temperature_initial_layer;
bool has_scarf_joint_seam = false;
bool is_wipe_tower = false;
bool is_multi_nozzle = false;
};
}