diff options
author | FormerLurker <hochgebe@gmail.com> | 2020-12-13 00:49:33 +0300 |
---|---|---|
committer | FormerLurker <hochgebe@gmail.com> | 2020-12-13 00:49:33 +0300 |
commit | 893b8eea5e182457e90db9ddbaac8a7fb435a0c7 (patch) | |
tree | 421dd5296fcdf57f807c86a2a78ceb5143201fbe | |
parent | 8cbd08c6c27bb792d28345d24ffc7a7765c35079 (diff) |
Prevent arc generation if I and J are both 0 within the current precision. Add default xyz and e precision settings, and enable/disable dynamic gcode precision.
-rw-r--r-- | ArcWelder/arc_welder.cpp | 15 | ||||
-rw-r--r-- | ArcWelder/arc_welder.h | 7 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.cpp | 58 | ||||
-rw-r--r-- | ArcWelder/segmented_arc.h | 4 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.cpp | 50 | ||||
-rw-r--r-- | ArcWelder/segmented_shape.h | 27 | ||||
-rw-r--r-- | ArcWelderConsole/ArcWelderConsole.cpp | 68 | ||||
-rw-r--r-- | ArcWelderTest/ArcWelderTest.cpp | 9 | ||||
-rw-r--r-- | ArcWelderTest/ArcWelderTest.h | 2 | ||||
-rw-r--r-- | PyArcWelder/py_arc_welder.h | 6 | ||||
-rw-r--r-- | PyArcWelder/py_arc_welder_extension.cpp | 76 | ||||
-rw-r--r-- | PyArcWelder/py_arc_welder_extension.h | 11 |
12 files changed, 280 insertions, 53 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp index 9fe02d0..d7b6120 100644 --- a/ArcWelder/arc_welder.cpp +++ b/ArcWelder/arc_welder.cpp @@ -46,6 +46,9 @@ arc_welder::arc_welder( double mm_per_arc_segment, bool g90_g91_influences_extruder, bool allow_3d_arcs, + bool allow_dynamic_precision, + unsigned char default_xyz_precision, + unsigned char default_e_precision, int buffer_size, progress_callback callback) : current_arc_( DEFAULT_MIN_SEGMENTS, @@ -55,7 +58,9 @@ arc_welder::arc_welder( max_radius, min_arc_segments, mm_per_arc_segment, - allow_3d_arcs + allow_3d_arcs, + default_xyz_precision, + default_e_precision ), segment_statistics_( segment_statistic_lengths, @@ -77,6 +82,7 @@ arc_welder::arc_welder( target_path_ = target_path; gcode_position_args_ = get_args_(g90_g91_influences_extruder, buffer_size); allow_3d_arcs_ = allow_3d_arcs; + allow_dynamic_precision_ = allow_dynamic_precision; notification_period_seconds = 1; lines_processed_ = 0; gcodes_processed_ = 0; @@ -195,7 +201,10 @@ arc_welder_results results; << ", min_arc_segments:" << std::setprecision(0) <<current_arc_.get_min_arc_segments() << ", mm_per_arc_segment:" << std::setprecision(0) << current_arc_.get_mm_per_arc_segment() << ", g90_91_influences_extruder: " << (p_source_position_->get_g90_91_influences_extruder() ? "True" : "False") - << ", allow_3d_arcs: " << (allow_3d_arcs_ ? "True" : "False"); + << ", allow_3d_arcs: " << (allow_3d_arcs_ ? "True" : "False") + << ", allow_dynamic_precision: " << (allow_dynamic_precision_ ? "True" : "False") + << ", default_xyz_precision: " << std::setprecision(0) << (current_arc_.get_xyz_precision()) + << ", default_e_precision: " << std::setprecision(0) << (current_arc_.get_e_precision()); p_logger_->log(logger_type_, INFO, stream.str()); @@ -407,7 +416,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess // We need to make sure the printer is using absolute xyz, is extruding, and the extruder axis mode is the same as that of the previous position // TODO: Handle relative XYZ axis. This is possible, but maybe not so important. bool is_g1_g2 = cmd.command == "G0" || cmd.command == "G1"; - if (is_g1_g2) + if (allow_dynamic_precision_ && is_g1_g2) { for (std::vector<parsed_command_parameter>::iterator it = cmd.parameters.begin(); it != cmd.parameters.end(); ++it) { diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h index 0e6bb81..9e6d74a 100644 --- a/ArcWelder/arc_welder.h +++ b/ArcWelder/arc_welder.h @@ -412,6 +412,7 @@ struct arc_welder_results { }; #define DEFAULT_GCODE_BUFFER_SIZE 1000 #define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false +#define DEFAULT_ALLOW_DYNAMIC_PRECISION false class arc_welder { public: @@ -425,7 +426,10 @@ public: int min_arc_segments, double mm_per_arc_segment, bool g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTRUDER, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs, + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS, + bool allow_dynamic_precision = DEFAULT_ALLOW_DYNAMIC_PRECISION, + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION, + unsigned char default_e_precision = DEFAULT_E_PRECISION, int buffer_size = DEFAULT_GCODE_BUFFER_SIZE, progress_callback callback = NULL); void set_logger_type(int logger_type); @@ -451,6 +455,7 @@ private: std::string target_path_; double resolution_mm_; gcode_position_args gcode_position_args_; + bool allow_dynamic_precision_; bool allow_3d_arcs_; long file_size_; int lines_processed_; diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp index c92809f..0618917 100644 --- a/ArcWelder/segmented_arc.cpp +++ b/ArcWelder/segmented_arc.cpp @@ -35,7 +35,8 @@ segmented_arc::segmented_arc() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_M { max_radius_mm_ = DEFAULT_MAX_RADIUS_MM; min_arc_segments_ = DEFAULT_MIN_ARC_SEGMENTS, - allow_3d_arcs_ = DEFAULT_allow_3d_arcs; + mm_per_arc_segment_ = DEFAULT_MM_PER_ARC_SEGMENT; + allow_3d_arcs_ = DEFAULT_ALLOW_3D_ARCS; num_firmware_compensations_ = 0; } @@ -47,8 +48,10 @@ segmented_arc::segmented_arc( double max_radius_mm, int min_arc_segments, double mm_per_arc_segment, - bool allow_3d_arcs -) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent) + bool allow_3d_arcs, + unsigned char default_xyz_precision, + unsigned char default_e_precision +) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent, default_xyz_precision, default_e_precision) { max_radius_mm_ = max_radius_mm; if (max_radius_mm > DEFAULT_MAX_RADIUS_MM) { @@ -210,10 +213,10 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) double previous_shape_length = original_shape_length_; original_shape_length_ += pd; arc original_arc = current_arc_; - if (arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_, min_arc_segments_, mm_per_arc_segment_, xyz_precision_, allow_3d_arcs_)) + if (arc::try_create_arc(points_, current_arc_, original_shape_length_, max_radius_mm_, resolution_mm_, path_tolerance_percent_, min_arc_segments_, mm_per_arc_segment_, get_xyz_precision(), allow_3d_arcs_)) { // See how many arcs will be interpolated - bool firmware_corrected = false; + bool abort_arc = false; if (min_arc_segments_ > 0 && mm_per_arc_segment_ > 0) { double circumference = 2.0 * PI_DOUBLE * current_arc_.radius; @@ -222,14 +225,24 @@ bool segmented_arc::try_add_point_internal_(point p, double pd) //num_segments = (int)std::ceil(circumference/approximate_length) * (int)std::ceil(approximate_length / mm_per_arc_segment); num_segments = (int)std::floor(circumference / original_shape_length_); if (num_segments < min_arc_segments_) { - firmware_corrected = true; - current_arc_ = original_arc; + abort_arc = true; num_firmware_compensations_++; } } } + // check for I=0 and J=0 + if (!abort_arc && utilities::is_zero(current_arc_.get_i(), get_xyz_tolerance()) && utilities::is_zero(current_arc_.get_j(), get_xyz_tolerance())) + { + abort_arc = true; + } - if (!firmware_corrected) + if (abort_arc) + { + // This arc has been cancelled either due to firmware correction, + // or because both I and J == 0 + current_arc_ = original_arc; + } + else if (!abort_arc) { if (!is_shape()) { @@ -262,8 +275,8 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons std::string gcode; - double i = current_arc_.center.x - current_arc_.start_point.x; - double j = current_arc_.center.y - current_arc_.start_point.y; + double i = current_arc_.get_i(); + double j = current_arc_.get_j(); // Here is where the performance part kicks in (these are expensive calls) that makes things a bit ugly. // there are a few cases we need to take into consideration before choosing our sprintf string // create the XYZ portion @@ -279,35 +292,40 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons } // Add X, Y, I and J gcode += " X"; - gcode += utilities::to_string(current_arc_.end_point.x, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.x, get_xyz_precision(), buf, false); gcode += " Y"; - gcode += utilities::to_string(current_arc_.end_point.y, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.y, get_xyz_precision(), buf, false); if (allow_3d_arcs_) { // We may need to add a z coordinate double z_initial = current_arc_.start_point.z; double z_final = current_arc_.end_point.z; - if (!utilities::is_equal(z_initial, z_final, std::pow(10.0, -1.0 * xyz_precision_))) + if (!utilities::is_equal(z_initial, z_final, get_xyz_tolerance())) { // The z axis has changed within the precision of the gcode coordinates gcode += " Z"; - gcode += utilities::to_string(current_arc_.end_point.z, xyz_precision_, buf, false); + gcode += utilities::to_string(current_arc_.end_point.z, get_xyz_precision(), buf, false); } } - gcode += " I"; - gcode += utilities::to_string(i, xyz_precision_, buf, false); - - gcode += " J"; - gcode += utilities::to_string(j, xyz_precision_, buf, false); + if (!utilities::is_zero(i, get_xyz_tolerance())) + { + gcode += " I"; + gcode += utilities::to_string(i, get_xyz_precision(), buf, false); + } + if (!utilities::is_zero(j, get_xyz_tolerance())) + { + gcode += " J"; + gcode += utilities::to_string(j, get_xyz_precision(), buf, false); + } // Add E if it appears if (has_e) { gcode += " E"; - gcode += utilities::to_string(e, e_precision_, buf, false); + gcode += utilities::to_string(e, get_e_precision(), buf, false); } // Add F if it appears diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h index a51cbbd..36d20da 100644 --- a/ArcWelder/segmented_arc.h +++ b/ArcWelder/segmented_arc.h @@ -43,7 +43,9 @@ public: double max_radius_mm = DEFAULT_MAX_RADIUS_MM, int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS, double mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS, + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION, + unsigned char default_e_precision = DEFAULT_E_PRECISION ); virtual ~segmented_arc(); virtual bool try_add_point(point p, double e_relative); diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp index 65995b4..f505d59 100644 --- a/ArcWelder/segmented_shape.cpp +++ b/ArcWelder/segmented_shape.cpp @@ -323,6 +323,16 @@ bool circle::is_over_deviation(const array_list<point>& points, const double res #pragma region Arc Functions +double arc::get_i() const +{ + return center.x - start_point.x; +} + +double arc::get_j() const +{ + return center.y - start_point.y; +} + bool arc::try_create_arc( const circle& c, const point& start_point, @@ -477,11 +487,11 @@ bool arc::try_create_arc( #pragma endregion -segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm, double path_tolerance_percnet) : points_(max_segments) +segmented_shape::segmented_shape(int min_segments, int max_segments, double resolution_mm, double path_tolerance_percnet, unsigned char default_xyz_precision, unsigned char default_e_precision) : points_(max_segments) { - xyz_precision_ = DEFAULT_XYZ_PRECISION; - e_precision_ = DEFAULT_E_PRECISION; + set_xyz_precision(default_xyz_precision); + e_precision_ = default_e_precision; max_segments_ = max_segments; path_tolerance_percent_ = path_tolerance_percnet; resolution_mm_ = resolution_mm / 2.0; // divide by 2 because it is + or - 1/2 of the desired resolution. @@ -500,21 +510,47 @@ segmented_shape::~segmented_shape() } +unsigned char segmented_shape::get_xyz_precision() const +{ + return xyz_precision_; +} + +double segmented_shape::get_xyz_tolerance() const +{ + return xyz_tolerance_; +} + +unsigned char segmented_shape::get_e_precision() const +{ + return e_precision_; +} + +void segmented_shape::set_xyz_precision(unsigned char precision) +{ + xyz_precision_ = precision; + set_xyz_tolerance_from_precision(); +} + +void segmented_shape::set_xyz_tolerance_from_precision() +{ + xyz_tolerance_ = std::pow(10.0, -1.0 * static_cast<double>(xyz_precision_)); +} + void segmented_shape::reset_precision() { - xyz_precision_ = DEFAULT_XYZ_PRECISION; + set_xyz_precision(DEFAULT_XYZ_PRECISION); e_precision_ = DEFAULT_E_PRECISION; } -void segmented_shape::update_xyz_precision(int precision) +void segmented_shape::update_xyz_precision(unsigned char precision) { if (xyz_precision_ < precision) { - xyz_precision_ = precision; + set_xyz_precision(precision); } } -void segmented_shape::update_e_precision(int precision) +void segmented_shape::update_e_precision(unsigned char precision) { if (e_precision_ < precision) { diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h index eda6a7c..3b8e807 100644 --- a/ArcWelder/segmented_shape.h +++ b/ArcWelder/segmented_shape.h @@ -121,7 +121,7 @@ struct circle { }; #define DEFAULT_RESOLUTION_MM 0.05 -#define DEFAULT_allow_3d_arcs false +#define DEFAULT_ALLOW_3D_ARCS false #define DEFAULT_MIN_ARC_SEGMENTS 0 #define DEFAULT_MM_PER_ARC_SEGMENT 0 struct arc : circle @@ -153,6 +153,9 @@ struct arc : circle double max_deviation; point start_point; point end_point; + + double get_i() const; + double get_j() const; // Statis functions static bool try_create_arc( const circle& c, @@ -163,7 +166,7 @@ struct arc : circle double approximate_length, double resolution = DEFAULT_RESOLUTION_MM, double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs); + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS); static bool try_create_arc( const array_list<point>& points, @@ -175,7 +178,7 @@ struct arc : circle int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS, double mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT, int xyz_precision = DEFAULT_XYZ_PRECISION, - bool allow_3d_arcs = DEFAULT_allow_3d_arcs); + bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS); }; double distance_from_segment(segment s, point p); @@ -189,7 +192,9 @@ public: segmented_shape(int min_segments = DEFAULT_MIN_SEGMENTS, int max_segments = DEFAULT_MAX_SEGMENTS, double resolution_mm = DEFAULT_RESOLUTION_MM, - double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT + double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT, + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION, + unsigned char default_e_precision = DEFAULT_E_PRECISION ); segmented_shape& operator=(const segmented_shape& pos); virtual ~segmented_shape(); @@ -202,8 +207,8 @@ public: double get_shape_e_relative(); void set_resolution_mm(double resolution_mm); void reset_precision(); - void update_xyz_precision(int precision); - void update_e_precision(int precision); + void update_xyz_precision(unsigned char precision); + void update_e_precision(unsigned char precision); virtual bool is_shape() const; // public virtual functions virtual void clear(); @@ -213,11 +218,12 @@ public: virtual std::string get_shape_gcode_absolute(double e_abs_start); virtual std::string get_shape_gcode_relative(); bool is_extruding(); + unsigned char get_xyz_precision() const; + unsigned char get_e_precision() const; + double get_xyz_tolerance() const; protected: array_list<point> points_; void set_is_shape(bool value); - unsigned char xyz_precision_; - unsigned char e_precision_; double original_shape_length_; double e_relative_; bool is_extruding_; @@ -227,5 +233,10 @@ protected: private: int min_segments_; int max_segments_; + unsigned char xyz_precision_; + double xyz_tolerance_; + unsigned char e_precision_; + void set_xyz_tolerance_from_precision(); + void set_xyz_precision(unsigned char precision); }; diff --git a/ArcWelderConsole/ArcWelderConsole.cpp b/ArcWelderConsole/ArcWelderConsole.cpp index bf7c63f..b301237 100644 --- a/ArcWelderConsole/ArcWelderConsole.cpp +++ b/ArcWelderConsole/ArcWelderConsole.cpp @@ -47,6 +47,9 @@ int main(int argc, char* argv[]) bool hide_progress; bool overwrite_source_file = false; bool allow_3d_arcs = false; + bool allow_dynamic_precision = DEFAULT_ALLOW_DYNAMIC_PRECISION; + unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION; + unsigned char default_e_precision = DEFAULT_E_PRECISION; std::string log_level_string; std::string log_level_string_default = "INFO"; int log_level_value; @@ -114,8 +117,26 @@ int main(int argc, char* argv[]) // -z --allow-3d-arcs arg_description_stream.clear(); arg_description_stream.str(""); - arg_description_stream << "(experimental) - If supplied, 3D arcs will be allowed (supports spiral vase mode). Not all firmware supports this. Default Value: " << DEFAULT_allow_3d_arcs; - TCLAP::SwitchArg allow_3d_arcs_arg("z", "allow-3d-arcs", arg_description_stream.str(), DEFAULT_allow_3d_arcs); + arg_description_stream << "(experimental) - If supplied, 3D arcs will be allowed (supports spiral vase mode). Not all firmware supports this. Default Value: " << DEFAULT_ALLOW_3D_ARCS; + TCLAP::SwitchArg allow_3d_arcs_arg("z", "allow-3d-arcs", arg_description_stream.str(), DEFAULT_ALLOW_3D_ARCS); + + // -d --allow-dynamic-precision + arg_description_stream.clear(); + arg_description_stream.str(""); + arg_description_stream << "If supplied, arcwelder will adjust the precision of the outputted gcode based on the precision of the input gcode. Default Value: " << DEFAULT_ALLOW_DYNAMIC_PRECISION; + TCLAP::SwitchArg allow_dynamic_precision_arg("d", "allow-dynamic-precision", arg_description_stream.str(), DEFAULT_ALLOW_DYNAMIC_PRECISION); + + // -x --default-xyz-precision + arg_description_stream.clear(); + arg_description_stream.str(""); + arg_description_stream << "The default precision of X, Y, Z, I and J output gcode parameters. The precision may be larger than this value if allow-dynamic-precision is set to true. Default Value: " << DEFAULT_XYZ_PRECISION; + TCLAP::ValueArg<unsigned char> default_xyz_precision_arg("x", "default-xyz-precision", arg_description_stream.str(), false, DEFAULT_XYZ_PRECISION, "unsigned char"); + + // -e --default-e-precision + arg_description_stream.clear(); + arg_description_stream.str(""); + arg_description_stream << "The default precision of E output gcode parameters. The precision may be larger than this value if allow-dynamic-precision is set to true. Default Value: " << DEFAULT_E_PRECISION; + TCLAP::ValueArg<unsigned char> default_e_precision_arg("e", "default-e-precision", arg_description_stream.str(), false, DEFAULT_E_PRECISION, "unsigned char"); // -g --hide-progress TCLAP::SwitchArg hide_progress_arg("p", "hide-progress", "If supplied, prevents progress updates from being displayed.", false); @@ -145,6 +166,9 @@ int main(int argc, char* argv[]) cmd.add(min_arc_segments_arg); cmd.add(mm_per_arc_segment_arg); cmd.add(allow_3d_arcs_arg); + cmd.add(allow_dynamic_precision_arg); + cmd.add(default_xyz_precision_arg); + cmd.add(default_e_precision_arg); cmd.add(g90_arg); cmd.add(hide_progress_arg); cmd.add(log_level_arg); @@ -168,6 +192,9 @@ int main(int argc, char* argv[]) path_tolerance_percent = path_tolerance_percent_arg.getValue(); allow_3d_arcs = allow_3d_arcs_arg.getValue(); g90_g91_influences_extruder = g90_arg.getValue(); + allow_dynamic_precision = allow_dynamic_precision_arg.getValue(); + default_xyz_precision = default_xyz_precision_arg.getValue(); + default_e_precision = default_e_precision_arg.getValue(); hide_progress = hide_progress_arg.getValue(); log_level_string = log_level_arg.getValue(); @@ -218,6 +245,34 @@ int main(int argc, char* argv[]) std::cout << "warning: The provided path tolerance percent of " << path_tolerance_percent << " is less than greater than 0.001 (0.1%), which is not recommended." << std::endl; } + if (default_xyz_precision < 3) + { + // warning + std::cout << "warning: The provided default_xyz_precision " << default_xyz_precision << "mm is less than 3, with will cause issues printing arcs. A value of 3 will be used instead." << std::endl; + default_xyz_precision = 3; + } + + if (default_e_precision < DEFAULT_E_PRECISION) + { + // warning + std::cout << "warning: The provided default_e_precision " << default_e_precision << "mm is less than 3, with will cause extrusion issues. A value of 3 will be used instead." << std::endl; + default_e_precision = 3; + } + + if (default_xyz_precision > 6) + { + // warning + std::cout << "warning: The provided default_xyz_precision " << default_xyz_precision << "mm is greater than 6, which may cause gcode checksum errors while printing depending on your firmeware, so a value of 6 will be used instead." << std::endl; + default_xyz_precision = 6; + } + + if (default_e_precision > 6) + { + // warning + std::cout << "warning: The provided default_e_precision " << default_e_precision << "mm is greater than 6, which may cause gcode checksum errors while printing depending on your firmeware, so value of 6 will be used instead." << std::endl; + default_e_precision = 6; + } + if (has_error) { return 1; @@ -292,7 +347,10 @@ int main(int argc, char* argv[]) log_messages << "\tMaximum Arc Radius : " << std::setprecision(0) << max_radius_mm << "mm\n"; log_messages << "\tMin Arc Segments : " << std::setprecision(0) << min_arc_segments << "\n"; log_messages << "\tMM Per Arc Segment : " << std::setprecision(3) << mm_per_arc_segment << "\n"; - log_messages << "\tAllow Z-Axis Changes : " << (allow_3d_arcs ? "True" : "False") << "\n"; + log_messages << "\tAllow 3D Arcs : " << (allow_3d_arcs ? "True" : "False") << "\n"; + log_messages << "\tAllow Dynamic Precision : " << (allow_dynamic_precision ? "True" : "False") << "\n"; + log_messages << "\tDefault XYZ Precision : " << std::setprecision(0) << static_cast<int>(default_xyz_precision) << "\n"; + log_messages << "\tDefault E Precision : " << std::setprecision(0) << static_cast<int>(default_e_precision) << "\n"; log_messages << "\tG90/G91 Influences Extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n"; log_messages << "\tLog Level : " << log_level_string << "\n"; log_messages << "\tHide Progress Updates : " << (hide_progress ? "True" : "False"); @@ -304,9 +362,9 @@ int main(int argc, char* argv[]) target_file_path = temp_file_path; } if (!hide_progress) - p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, path_tolerance_percent, max_radius_mm, min_arc_segments, mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, DEFAULT_GCODE_BUFFER_SIZE, on_progress); + p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, path_tolerance_percent, max_radius_mm, min_arc_segments, mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, allow_dynamic_precision, default_xyz_precision, default_e_precision, DEFAULT_GCODE_BUFFER_SIZE, on_progress); else - p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, path_tolerance_percent, max_radius_mm, min_arc_segments, mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, DEFAULT_GCODE_BUFFER_SIZE, suppress_progress); + p_arc_welder = new arc_welder(source_file_path, target_file_path, p_logger, resolution_mm, path_tolerance_percent, max_radius_mm, min_arc_segments, mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, allow_dynamic_precision, default_xyz_precision, default_e_precision, DEFAULT_GCODE_BUFFER_SIZE, suppress_progress); arc_welder_results results = p_arc_welder->process(); if (results.success) diff --git a/ArcWelderTest/ArcWelderTest.cpp b/ArcWelderTest/ArcWelderTest.cpp index ab33d83..0a11498 100644 --- a/ArcWelderTest/ArcWelderTest.cpp +++ b/ArcWelderTest/ArcWelderTest.cpp @@ -237,11 +237,11 @@ static void TestAntiStutter(std::string filePath) double max_resolution = 0.05; double max_radius_mm = 100000; //int min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS; - int min_arc_segments = 12; + int min_arc_segments = 0; double mm_per_arc_segment = 1; //double path_tolerance_percent = ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT; // 1 percent - double path_tolerance_percent = 0.05; + double path_tolerance_percent = 0.05; //double path_tolerance_percent = 0.05; std::vector<std::string> logger_names; logger_names.push_back("arc_welder.gcode_conversion"); @@ -259,7 +259,7 @@ static void TestAntiStutter(std::string filePath) //arc_welder arc_welder_obj(BENCHY_0_5_MM_NO_WIPE, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, static_cast<progress_callback>(on_progress)); //arc_welder arc_welder_obj(SIX_SPEED_TEST, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, false, 50, on_progress); arc_welder arc_welder_obj( - ISSUE_85, + ISSUE_93, "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\test_output.gcode", p_logger, max_resolution, @@ -269,6 +269,9 @@ static void TestAntiStutter(std::string filePath) mm_per_arc_segment, false, true, + DEFAULT_ALLOW_DYNAMIC_PRECISION, + DEFAULT_XYZ_PRECISION, + DEFAULT_E_PRECISION, DEFAULT_GCODE_BUFFER_SIZE, on_progress); //FIRMWARE_COMPENSATION_TEST_1 diff --git a/ArcWelderTest/ArcWelderTest.h b/ArcWelderTest/ArcWelderTest.h index e6d843a..65a3604 100644 --- a/ArcWelderTest/ArcWelderTest.h +++ b/ArcWelderTest/ArcWelderTest.h @@ -88,7 +88,7 @@ static std::string SPIRAL_VASE_TEST_PI_BOWL = "C:\\Users\\Brad\\Documents\\3DPri static std::string FIRMWARE_COMPENSATION_TEST_1 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\cylinder_tests\\cylinder_test_0.1_5.0_0.1.gcode"; static std::string BENCHY_MIN_RADIUS_TEST = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\BenchyMinRadiusTest.gcode"; -static std::string ISSUE_85 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issue85.gcode"; +static std::string ISSUE_93 = "C:\\Users\\Brad\\Documents\\3DPrinter\\AntiStutter\\Issues\\93\\FailingGCode.gcode"; diff --git a/PyArcWelder/py_arc_welder.h b/PyArcWelder/py_arc_welder.h index 14d5760..ed4e8cc 100644 --- a/PyArcWelder/py_arc_welder.h +++ b/PyArcWelder/py_arc_welder.h @@ -46,6 +46,9 @@ public: double mm_per_arc_segment, bool g90_g91_influences_extruder, bool allow_3d_arcs, + bool allow_dynamic_precision, + unsigned char default_xyz_precision, + unsigned char default_e_precision, int buffer_size, PyObject* py_progress_callback ): arc_welder( @@ -59,6 +62,9 @@ public: mm_per_arc_segment, g90_g91_influences_extruder, allow_3d_arcs, + allow_dynamic_precision, + default_xyz_precision, + default_e_precision, buffer_size ){ guid_ = guid; diff --git a/PyArcWelder/py_arc_welder_extension.cpp b/PyArcWelder/py_arc_welder_extension.cpp index 25eb9d9..1e0728b 100644 --- a/PyArcWelder/py_arc_welder_extension.cpp +++ b/PyArcWelder/py_arc_welder_extension.cpp @@ -195,7 +195,24 @@ extern "C" std::string message = "py_gcode_arc_converter.ConvertFile - Beginning Arc Conversion."; p_py_logger->log(GCODE_CONVERSION, INFO, message); - py_arc_welder arc_welder_obj(args.guid, args.source_path, args.target_path, p_py_logger, args.resolution_mm, args.path_tolerance_percent, args.max_radius_mm, args.min_arc_segments, args.mm_per_arc_segment, args.g90_g91_influences_extruder, args.allow_3d_arcs, DEFAULT_GCODE_BUFFER_SIZE, py_progress_callback); + py_arc_welder arc_welder_obj( + args.guid, + args.source_path, + args.target_path, + p_py_logger, + args.resolution_mm, + args.path_tolerance_percent, + args.max_radius_mm, + args.min_arc_segments, + args.mm_per_arc_segment, + args.g90_g91_influences_extruder, + args.allow_3d_arcs, + args.allow_dynamic_precision, + args.default_xyz_precision, + args.default_e_precision, + DEFAULT_GCODE_BUFFER_SIZE, + py_progress_callback + ); arc_welder_results results = arc_welder_obj.process(); message = "py_gcode_arc_converter.ConvertFile - Arc Conversion Complete."; p_py_logger->log(GCODE_CONVERSION, INFO, message); @@ -271,6 +288,60 @@ static bool ParseArgs(PyObject* py_args, py_gcode_arc_args& args, PyObject** py_ args.resolution_mm = 0.05; // Set to the default if no resolution is provided, or if it is less than 0. } + // extract allow_dynamic_precision + PyObject* py_allow_dynamic_precision = PyDict_GetItemString(py_args, "allow_dynamic_precision"); + if (py_allow_dynamic_precision == NULL) + { + std::string message = "ParseArgs - Unable to retrieve allow_dynamic_precision from the args."; + p_py_logger->log_exception(GCODE_CONVERSION, message); + return false; + } + args.allow_dynamic_precision = PyLong_AsLong(py_allow_dynamic_precision) > 0; + + // extract default_xyz_precision + PyObject* py_default_xyz_precision = PyDict_GetItemString(py_args, "default_xyz_precision"); + if (py_default_xyz_precision == NULL) + { + std::string message = "ParseArgs - Unable to retrieve the default_xyz_precision parameter from the args."; + p_py_logger->log_exception(GCODE_CONVERSION, message); + return false; + } + args.default_xyz_precision = gcode_arc_converter::PyFloatOrInt_AsDouble(py_default_xyz_precision); + if (args.default_xyz_precision < 3) + { + std::string message = "ParseArgs - The default XYZ precision received was less than 3, which could cause problems printing arcs. Setting to 3."; + p_py_logger->log(WARNING, GCODE_CONVERSION, message); + args.default_xyz_precision = 3; + } + else if (args.default_xyz_precision > 6) + { + std::string message = "ParseArgs - The default XYZ precision received was greater than 6, which could can cause checksum errors depending on your firmware. Setting to 6."; + p_py_logger->log(WARNING, GCODE_CONVERSION, message); + args.default_xyz_precision = 6; + } + + // extract default_e_precision + PyObject* py_default_e_precision = PyDict_GetItemString(py_args, "default_e_precision"); + if (py_default_e_precision == NULL) + { + std::string message = "ParseArgs - Unable to retrieve the default_e_precision parameter from the args."; + p_py_logger->log_exception(GCODE_CONVERSION, message); + return false; + } + args.default_e_precision = gcode_arc_converter::PyFloatOrInt_AsDouble(py_default_e_precision); + if (args.default_e_precision < 3) + { + std::string message = "ParseArgs - The default E precision received was less than 3, which could cause extrusion problems. Setting to 3."; + p_py_logger->log(WARNING, GCODE_CONVERSION, message); + args.default_e_precision = 3; + } + else if (args.default_e_precision > 6) + { + std::string message = "ParseArgs - The default E precision received was greater than 6, which could can cause checksum errors depending on your firmware. Setting to 6."; + p_py_logger->log(WARNING, GCODE_CONVERSION, message); + args.default_e_precision = 6; + } + // Extract the path tolerance_percent PyObject* py_path_tolerance_percent = PyDict_GetItemString(py_args, "path_tolerance_percent"); if (py_path_tolerance_percent == NULL) @@ -327,8 +398,7 @@ static bool ParseArgs(PyObject* py_args, py_gcode_arc_args& args, PyObject** py_ args.min_arc_segments = 0; // Set to the default if no resolution is provided, or if it is less than 0. } - // Extract Allow Z Axis Changes - // allow_3d_arcs + // extract allow_3d_arcs PyObject* py_allow_3d_arcs = PyDict_GetItemString(py_args, "allow_3d_arcs"); if (py_allow_3d_arcs == NULL) { diff --git a/PyArcWelder/py_arc_welder_extension.h b/PyArcWelder/py_arc_welder_extension.h index 46944a1..2c2ecec 100644 --- a/PyArcWelder/py_arc_welder_extension.h +++ b/PyArcWelder/py_arc_welder_extension.h @@ -52,7 +52,7 @@ struct py_gcode_arc_args { min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS; mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT; g90_g91_influences_extruder = DEFAULT_G90_G91_INFLUENCES_EXTREUDER; - allow_3d_arcs = DEFAULT_allow_3d_arcs; + allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS; log_level = 0; } py_gcode_arc_args( @@ -66,6 +66,9 @@ struct py_gcode_arc_args { double mm_per_arc_segment_, bool g90_g91_influences_extruder_, bool allow_3d_arcs_, + bool allow_dynamic_precision_, + unsigned char default_xyz_precision_, + unsigned char default_e_precision_, int log_level_ ) { guid = guid_; @@ -77,6 +80,9 @@ struct py_gcode_arc_args { min_arc_segments = min_arc_segments_; mm_per_arc_segment = mm_per_arc_segment_; allow_3d_arcs = allow_3d_arcs_; + allow_dynamic_precision = allow_dynamic_precision_; + default_xyz_precision = default_xyz_precision_; + default_e_precision = default_e_precision_; g90_g91_influences_extruder = g90_g91_influences_extruder_; log_level = log_level_; } @@ -86,6 +92,9 @@ struct py_gcode_arc_args { double resolution_mm; double path_tolerance_percent; bool allow_3d_arcs; + bool allow_dynamic_precision; + unsigned char default_xyz_precision; + unsigned char default_e_precision; bool g90_g91_influences_extruder; double max_radius_mm; int min_arc_segments; |