Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FormerLurker/ArcWelderLib.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFormerLurker <hochgebe@gmail.com>2021-07-06 02:57:33 +0300
committerFormerLurker <hochgebe@gmail.com>2021-07-06 02:57:33 +0300
commit9d3361e145c806a2ea0d3c7f1f6fc7252e4d0ef1 (patch)
tree52de3bf32785619982801e542c4121908916d145 /ArcWelder
parentb2e44aa85c9da175c6e78fd909c9f92531f5f393 (diff)
Add alpha gcode length restrictions. Enhance output statistics. Create arc_welder_args. Add new progress type args to command line processor.
Diffstat (limited to 'ArcWelder')
-rw-r--r--ArcWelder/arc_welder.cpp165
-rw-r--r--ArcWelder/arc_welder.h174
-rw-r--r--ArcWelder/segmented_arc.cpp83
-rw-r--r--ArcWelder/segmented_arc.h13
-rw-r--r--ArcWelder/segmented_shape.cpp8
-rw-r--r--ArcWelder/segmented_shape.h20
-rw-r--r--ArcWelder/unwritten_command.h34
7 files changed, 352 insertions, 145 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp
index b45f9e9..0531a67 100644
--- a/ArcWelder/arc_welder.cpp
+++ b/ArcWelder/arc_welder.cpp
@@ -52,6 +52,7 @@ arc_welder::arc_welder(
unsigned char default_xyz_precision,
unsigned char default_e_precision,
double extrusion_rate_variance_percent,
+ int max_gcode_length,
int buffer_size,
progress_callback callback) : current_arc_(
DEFAULT_MIN_SEGMENTS,
@@ -63,13 +64,19 @@ arc_welder::arc_welder(
mm_per_arc_segment,
allow_3d_arcs,
default_xyz_precision,
- default_e_precision
+ default_e_precision,
+ max_gcode_length
),
segment_statistics_(
segment_statistic_lengths,
segment_statistic_lengths_count,
log
- )
+ ),
+ travel_statistics_(
+ segment_statistic_lengths,
+ segment_statistic_lengths_count,
+ log
+ )
{
p_logger_ = log;
debug_logging_enabled_ = false;
@@ -203,24 +210,6 @@ arc_welder_results results;
error_logging_enabled_ = p_logger_->is_log_level_enabled(logger_type_, ERROR);
std::stringstream stream;
- stream << std::fixed << std::setprecision(2);
- stream << "arc_welder::process - Parameters received: source_file_path: '" <<
- source_path_ << "', target_file_path:'" << target_path_ << "', resolution_mm:" <<
- resolution_mm_ << "mm (+-" << current_arc_.get_resolution_mm()
- << "mm), path_tolerance_percent: " << current_arc_.get_path_tolerance_percent()
- << "%, extrusion_rate_variance_percent: " << extrusion_rate_variance_percent_
- << "%, max_radius_mm:" << current_arc_.get_max_radius()
- << ", 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_travel_arcs: " << (allow_travel_arcs_ ? "True" : "False")
- << ", allow_dynamic_precision: " << (allow_dynamic_precision_ ? "True" : "False")
- << ", default_xyz_precision: " << std::setprecision(0) << static_cast<double>(current_arc_.get_xyz_precision())
- << ", default_e_precision: " << std::setprecision(0) << static_cast<double>(current_arc_.get_e_precision());
- p_logger_->log(logger_type_, INFO, stream.str());
-
-
// reset tracking variables
reset();
// local variable to hold the progress update return. If it's false, we will exit.
@@ -236,6 +225,28 @@ arc_welder_results results;
stream.str("");
stream << "Source file size: " << file_size_;
p_logger_->log(logger_type_, DEBUG, stream.str());
+
+ // Determine if we need to overwrite the source file
+ bool overwrite_source_file = false;
+ std::string temp_file_path;
+ if (source_path_ == target_path_)
+ {
+ overwrite_source_file = true;
+ if (!utilities::get_temp_file_path_for_file(source_path_, temp_file_path))
+ {
+ results.success = false;
+ results.message = "The source and target path are the same, but a temporary file path could not be created. Are the paths empty?";
+ p_logger_->log_exception(logger_type_, results.message);
+ return results;
+ }
+
+ stream.clear();
+ stream.str("");
+ stream << "Source and target path are the same. The source file will be overwritten. Temporary file path: " << temp_file_path;
+ p_logger_->log(logger_type_, DEBUG, stream.str());
+ target_path_ = temp_file_path;
+ }
+
// Create the source file read stream and target write stream
std::ifstream gcodeFile;
p_logger_->log(logger_type_, DEBUG, "Opening the source file for reading.");
@@ -340,6 +351,7 @@ arc_welder_results results;
}
p_logger_->log(logger_type_, DEBUG, "Writing all unwritten gcodes to the target file.");
write_unwritten_gcodes_to_file();
+
p_logger_->log(logger_type_, DEBUG, "Fetching the final progress struct.");
arc_welder_progress final_progress = get_progress_(static_cast<long>(file_size_), static_cast<double>(start_clock));
@@ -347,13 +359,26 @@ arc_welder_results results;
{
p_logger_->log(logger_type_, DEBUG, "Sending final progress update message.");
}
- on_progress_(arc_welder_progress(final_progress));
+ on_progress_(final_progress);
- p_logger_->log(logger_type_, DEBUG, "Processing complete, closing source and target file.");
+ p_logger_->log(logger_type_, DEBUG, "Closing source and target files.");
output_file_.close();
gcodeFile.close();
- const clock_t end_clock = clock();
-
+
+ if (overwrite_source_file)
+ {
+ stream.clear();
+ stream.str("");
+ stream << "Deleting the original source file at '" << source_path_ << "'.";
+ p_logger_->log(logger_type_, DEBUG, stream.str());
+ stream.clear();
+ stream.str("");
+ std::remove(source_path_.c_str());
+ stream << "Renaming temporary file at '" << target_path_ << "' to '" << source_path_ << "'.";
+ p_logger_->log(0, DEBUG, stream.str());
+ std::rename(target_path_.c_str(), source_path_.c_str());
+ }
+
results.success = continue_processing;
results.cancelled = !continue_processing;
results.progress = final_progress;
@@ -397,8 +422,14 @@ arc_welder_progress arc_welder::get_progress_(long source_file_position, double
progress.compression_ratio = (static_cast<float>(source_file_position) / static_cast<float>(progress.target_file_size));
progress.compression_percent = (1.0 - (static_cast<float>(progress.target_file_size) / static_cast<float>(source_file_position))) * 100.0f;
}
+ else {
+ progress.compression_ratio = 0;
+ progress.compression_percent = 0;
+ }
progress.num_firmware_compensations = current_arc_.get_num_firmware_compensations();
+ progress.num_gcode_length_exceptions = current_arc_.get_num_gcode_length_exceptions();
progress.segment_statistics = segment_statistics_;
+ progress.travel_statistics = travel_statistics_;
return progress;
}
@@ -427,7 +458,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
bool arc_added = false;
bool clear_shapes = false;
double movement_length_mm = 0;
- bool has_e_changed = extruder_current.is_extruding || extruder_current.is_retracting;
+ bool has_e_changed = extruder_current.e_relative != 0;
// Update the source file statistics
if (p_cur_pos->has_xy_position_changed)
{
@@ -441,7 +472,17 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
if (movement_length_mm > 0)
{
if (!is_reprocess)
- segment_statistics_.update(movement_length_mm, true);
+ {
+ if (has_e_changed)
+ {
+ segment_statistics_.update(movement_length_mm, true);
+ }
+ else if (allow_3d_arcs_)
+ {
+ travel_statistics_.update(movement_length_mm, true);
+ }
+
+ }
}
}
@@ -466,8 +507,8 @@ 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 (allow_dynamic_precision_ && is_g1_g2)
+ bool is_g0_g1 = cmd.command == "G0" || cmd.command == "G1";
+ if (allow_dynamic_precision_ && is_g0_g1)
{
for (std::vector<parsed_command_parameter>::iterator it = cmd.parameters.begin(); it != cmd.parameters.end(); ++it)
{
@@ -490,7 +531,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
if (
!is_end && cmd.is_known_command && !cmd.is_empty && (
- is_g1_g2 && z_axis_ok &&
+ is_g0_g1 && z_axis_ok &&
utilities::is_equal(p_cur_pos->x_offset, p_pre_pos->x_offset) &&
utilities::is_equal(p_cur_pos->y_offset, p_pre_pos->y_offset) &&
utilities::is_equal(p_cur_pos->z_offset, p_pre_pos->z_offset) &&
@@ -516,7 +557,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// Record the extrusion rate
previous_extrusion_rate_ = mm_extruded_per_mm_travel;
- printer_point p(p_cur_pos->get_gcode_x(), p_cur_pos->get_gcode_y(), p_cur_pos->get_gcode_z(), extruder_current.e_relative, movement_length_mm);
+ printer_point p(p_cur_pos->get_gcode_x(), p_cur_pos->get_gcode_y(), p_cur_pos->get_gcode_z(), extruder_current.get_offset_e() ,extruder_current.e_relative, p_cur_pos->f, movement_length_mm, p_pre_pos->is_extruder_relative);
if (!waiting_for_arc_)
{
if (debug_logging_enabled_)
@@ -525,7 +566,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
}
write_unwritten_gcodes_to_file();
// add the previous point as the starting point for the current arc
- printer_point previous_p(p_pre_pos->get_gcode_x(), p_pre_pos->get_gcode_y(), p_pre_pos->get_gcode_z(), previous_extruder.e_relative, 0);
+ printer_point previous_p(p_pre_pos->get_gcode_x(), p_pre_pos->get_gcode_y(), p_pre_pos->get_gcode_z(), previous_extruder.get_offset_e(),previous_extruder.e_relative, p_pre_pos->f, 0, p_pre_pos->is_extruder_relative);
// Don't add any extrusion, or you will over extrude!
//std::cout << "Trying to add first point (" << p.x << "," << p.y << "," << p.z << ")...";
@@ -652,8 +693,6 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// Reset the previous extrusion rate
previous_extrusion_rate_ = 0;
}
-
-
if (!arc_added && !(cmd.is_empty && cmd.comment.length() == 0))
{
@@ -677,7 +716,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// update our statistics
points_compressed_ += current_arc_.get_num_segments()-1;
arcs_created_++; // increment the number of generated arcs
- write_arc_gcodes(p_pre_pos->is_extruder_relative, p_pre_pos->f);
+ write_arc_gcodes(p_pre_pos->f);
// Now clear the arc and flag the processor as not waiting for an arc
waiting_for_arc_ = false;
current_arc_.clear();
@@ -721,7 +760,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
// This might not work....
//position* cur_pos = p_source_position_->get_current_position_ptr();
- unwritten_commands_.push_back(unwritten_command(cmd, is_previous_extruder_relative, movement_length_mm));
+ unwritten_commands_.push_back(unwritten_command(cmd, is_previous_extruder_relative, !has_e_changed && is_g0_g1, movement_length_mm));
}
else if (!waiting_for_arc_)
@@ -732,7 +771,7 @@ int arc_welder::process_gcode(parsed_command cmd, bool is_end, bool is_reprocess
return lines_written;
}
-void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feedrate)
+void arc_welder::write_arc_gcodes(double current_feedrate)
{
std::string comment = get_comment_for_arc();
@@ -742,7 +781,7 @@ void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feed
int num_segments = current_arc_.get_num_segments() - 1;
for (int index = 0; index < num_segments; index++)
{
- while (!unwritten_commands_.pop_back().is_g1_g2);
+ while (!unwritten_commands_.pop_back().is_g0_g1);
}
// Undo the current command, since it isn't included in the arc
@@ -754,16 +793,8 @@ void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feed
}
// Craete the arc gcode
- std::string gcode;
- if (is_extruder_relative) {
- gcode = get_arc_gcode_relative(current_feedrate, comment);
- }
-
- else {
- gcode = get_arc_gcode_absolute(p_source_position_->get_current_position_ptr()->get_current_extruder().get_offset_e(), current_feedrate, comment);
- }
-
-
+ std::string gcode = get_arc_gcode(comment);
+
if (debug_logging_enabled_)
{
char buffer[20];
@@ -779,11 +810,16 @@ void arc_welder::write_arc_gcodes(bool is_extruder_relative, double current_feed
write_unwritten_gcodes_to_file();
// Update the current extrusion statistics for the current arc gcode
- segment_statistics_.update(current_arc_.get_shape_length() , false);
+ if (current_arc_.get_shape_e_relative() != 0)
+ {
+ segment_statistics_.update(current_arc_.get_shape_length(), false);
+
+ }
+ else if (allow_3d_arcs_){
+ travel_statistics_.update(current_arc_.get_shape_length(), false);
+ }
// now write the current arc to the file
write_gcode_to_file(gcode);
-
-
}
std::string arc_welder::get_comment_for_arc()
@@ -830,9 +866,15 @@ int arc_welder::write_unwritten_gcodes_to_file()
{
// The the current unwritten position and remove it from the list
unwritten_command p = unwritten_commands_.pop_front();
- if (p.extrusion_length > 0)
+ if(p.is_g0_g1 && p.length > 0)
{
- segment_statistics_.update(p.extrusion_length, false);
+ if (!p.is_travel)
+ {
+ segment_statistics_.update(p.length, false);
+ }
+ else if (allow_3d_arcs_) {
+ travel_statistics_.update(p.length, false);
+ }
}
lines_to_write.append(p.to_string()).append("\n");
}
@@ -841,27 +883,12 @@ int arc_welder::write_unwritten_gcodes_to_file()
return size;
}
-std::string arc_welder::get_arc_gcode_relative(double f, const std::string comment)
-{
- // Write gcode to file
- std::string gcode;
-
- gcode = current_arc_.get_shape_gcode_relative(f);
-
- if (comment.length() > 0)
- {
- gcode += ";" + comment;
- }
- return gcode;
-
-}
-
-std::string arc_welder::get_arc_gcode_absolute(double e, double f, const std::string comment)
+std::string arc_welder::get_arc_gcode(const std::string comment)
{
// Write gcode to file
std::string gcode;
- gcode = current_arc_.get_shape_gcode_absolute(e, f);
+ gcode = current_arc_.get_shape_gcode();
if (comment.length() > 0)
{
diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h
index 98564ec..fc5bb84 100644
--- a/ArcWelder/arc_welder.h
+++ b/ArcWelder/arc_welder.h
@@ -44,9 +44,6 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
-
-#define DEFAULT_G90_G91_INFLUENCES_EXTREUDER false
-
static const int segment_statistic_lengths_count = 12;
const double segment_statistic_lengths[] = { 0.002f, 0.005f, 0.01f, 0.05f, 0.1f, 0.5f, 1.0f, 5.0f, 10.0f, 20.0f, 50.0f, 100.0f };
@@ -346,7 +343,7 @@ private:
// Struct to hold the progress, statistics, and return values
struct arc_welder_progress {
- arc_welder_progress() : segment_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL) {
+ arc_welder_progress() : segment_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL), travel_statistics(segment_statistic_lengths, segment_statistic_lengths_count, NULL) {
percent_complete = 0.0;
seconds_elapsed = 0.0;
seconds_remaining = 0.0;
@@ -356,6 +353,7 @@ struct arc_welder_progress {
arcs_created = 0;
arcs_aborted_by_flow_rate = 0;
num_firmware_compensations = 0;
+ num_gcode_length_exceptions = 0;
source_file_size = 0;
source_file_position = 0;
target_file_size = 0;
@@ -371,12 +369,30 @@ struct arc_welder_progress {
int arcs_created;
int arcs_aborted_by_flow_rate;
int num_firmware_compensations;
+ int num_gcode_length_exceptions;
double compression_ratio;
double compression_percent;
long source_file_position;
long source_file_size;
long target_file_size;
source_target_segment_statistics segment_statistics;
+ source_target_segment_statistics travel_statistics;
+
+ std::string simple_progress_str() const {
+ std::stringstream stream;
+ if (percent_complete == 0) {
+ stream << " 00.0% complete - Estimating remaining time.";
+ }
+ else if (percent_complete == 100)
+ {
+ stream << "100.0% complete - " << seconds_elapsed << " seconds total.";
+ }
+ else {
+ stream << " " << std::fixed << std::setprecision(1) << std::setfill('0') << std::setw(4) << percent_complete << "% complete - Estimated " << std::setprecision(0) << std::setw(-1) << seconds_remaining << " of " << seconds_elapsed + seconds_remaining << " seconds remaing.";
+ }
+
+ return stream.str();
+ }
std::string str() const {
std::stringstream stream;
@@ -389,19 +405,128 @@ struct arc_welder_progress {
stream << ", arcs_created: " << arcs_created;
stream << ", arcs_aborted_by_flowrate: " << arcs_aborted_by_flow_rate;
stream << ", num_firmware_compensations: " << num_firmware_compensations;
+ stream << ", num_gcode_length_exceptions: " << num_gcode_length_exceptions;
stream << ", compression_ratio: " << compression_ratio;
stream << ", size_reduction: " << compression_percent << "% ";
return stream.str();
}
std::string detail_str() const {
std::stringstream stream;
- stream << "\n" << "Extrusion/Retraction Counts" << "\n" << segment_statistics.str() << "\n";
+ if (travel_statistics.total_count_source > 0)
+ {
+ stream << "Target File Travel Statistics:" << "\n" << travel_statistics.str() << "\n";
+ }
+
+ stream << "\n" << "Target File Extrusion Statistics:" << "\n" << segment_statistics.str() << "\n";
+
return stream.str();
}
};
-
// define the progress callback type
typedef bool(*progress_callback)(arc_welder_progress, logger* p_logger, int logger_type);
+// LOGGER_NAME
+#define ARC_WELDER_LOGGER_NAME "arc_welder.gcode_conversion"
+// Default argument values
+#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
+#define DEFAULT_GCODE_BUFFER_SIZE 10
+#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
+#define DEFAULT_ALLOW_DYNAMIC_PRECISION false
+#define DEFAULT_ALLOW_TRAVEL_ARCS false
+#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 0.05
+#define DEFAULT_CONVERT_TRAVEL_MOVES false
+
+
+struct arc_welder_args
+{
+ arc_welder_args() :
+ source_path(""),
+ target_path(""),
+ log(NULL),
+ resolution_mm(DEFAULT_RESOLUTION_MM),
+ path_tolerance_percent(ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT),
+ max_radius_mm(DEFAULT_MAX_RADIUS_MM),
+ min_arc_segments(DEFAULT_MIN_ARC_SEGMENTS),
+ mm_per_arc_segment(DEFAULT_MM_PER_ARC_SEGMENT),
+ g90_g91_influences_extruder(DEFAULT_G90_G91_INFLUENCES_EXTRUDER),
+ allow_3d_arcs(DEFAULT_ALLOW_3D_ARCS),
+ allow_travel_arcs(DEFAULT_ALLOW_TRAVEL_ARCS),
+ allow_dynamic_precision(DEFAULT_ALLOW_DYNAMIC_PRECISION),
+ default_xyz_precision(DEFAULT_XYZ_PRECISION),
+ default_e_precision(DEFAULT_E_PRECISION),
+ extrusion_rate_variance_percent(DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT),
+ max_gcode_length(DEFAULT_MAX_GCODE_LENGTH),
+ buffer_size(DEFAULT_GCODE_BUFFER_SIZE),
+ callback(NULL){};
+
+ arc_welder_args(std::string source, std::string target, logger* ptr_log) : arc_welder_args()
+ {
+ source_path = source;
+ target_path = target;
+ log = ptr_log;
+ }
+ std::string source_path;
+ std::string target_path;
+ logger* log;
+ double resolution_mm;
+ double path_tolerance_percent;
+ double max_radius_mm;
+ int min_arc_segments;
+ double mm_per_arc_segment;
+ bool g90_g91_influences_extruder;
+ bool allow_3d_arcs;
+ bool allow_travel_arcs;
+ bool allow_dynamic_precision;
+ unsigned char default_xyz_precision;
+ unsigned char default_e_precision;
+ double extrusion_rate_variance_percent;
+ int buffer_size;
+ int max_gcode_length;
+
+ progress_callback callback;
+
+ std::string str() const {
+ std::string log_level_name = "NO_LOGGING";
+ if (log != NULL)
+ {
+ log_level_name = log->get_log_level_name(ARC_WELDER_LOGGER_NAME);
+ }
+ std::stringstream stream;
+ stream << "Arc Welder Arguments\n";
+ stream << std::fixed << std::setprecision(2);
+ stream << "\tSource File Path : " << source_path << "\n";
+ if (source_path == target_path)
+ {
+ stream << "\tTarget File Path (overwrite) : " << target_path << "\n";
+ }
+ else
+ {
+ stream << "\tTarget File Path : " << target_path << "\n";
+ }
+ stream << "\tResolution : " << resolution_mm << "mm (+-" << std::setprecision(5) << resolution_mm / 2.0 << "mm)\n";
+ stream << "\tPath Tolerance : " << std::setprecision(3) << path_tolerance_percent * 100.0 << "%\n";
+ stream << "\tMaximum Arc Radius : " << std::setprecision(0) << max_radius_mm << "mm\n";
+ stream << "\tMin Arc Segments : " << std::setprecision(0) << min_arc_segments << "\n";
+ stream << "\tMM Per Arc Segment : " << std::setprecision(3) << mm_per_arc_segment << "\n";
+ stream << "\tAllow 3D Arcs : " << (allow_3d_arcs ? "True" : "False") << "\n";
+ stream << "\tAllow Travel Arcs : " << (allow_travel_arcs ? "True" : "False") << "\n";
+ stream << "\tAllow Dynamic Precision : " << (allow_dynamic_precision ? "True" : "False") << "\n";
+ stream << "\tDefault XYZ Precision : " << std::setprecision(0) << static_cast<int>(default_xyz_precision) << "\n";
+ stream << "\tDefault E Precision : " << std::setprecision(0) << static_cast<int>(default_e_precision) << "\n";
+ stream << "\tExtrusion Rate Variance % : " << std::setprecision(3) << extrusion_rate_variance_percent * 100.0 << "%\n";
+ stream << "\tG90/G91 Influences Extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n";
+ if (max_gcode_length == 0)
+ {
+ stream << "\tMax Gcode Length : Unlimited\n";
+ }
+ else {
+ stream << "\tMax Gcode Length : " << std::setprecision(0) << max_gcode_length << " characters\n";
+ }
+ stream << "\tLog Level : " << log_level_name << "\n";
+ stream << "\tHide Progress Updates : " << (callback == NULL ? "True" : "False");
+ return stream.str();
+ };
+
+};
struct arc_welder_results {
arc_welder_results() : progress()
@@ -415,12 +540,7 @@ struct arc_welder_results {
std::string message;
arc_welder_progress progress;
};
-#define DEFAULT_GCODE_BUFFER_SIZE 10
-#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
-#define DEFAULT_ALLOW_DYNAMIC_PRECISION false
-#define DEFAULT_ALLOW_TRAVEL_ARCS false
-#define DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT 0.05
-#define DEFAULT_CONVERT_TRAVEL_MOVES false
+
class arc_welder
{
public:
@@ -440,8 +560,32 @@ public:
unsigned char default_xyz_precision,
unsigned char default_e_precision,
double extrusion_rate_variance_percent,
+ int max_gcode_length,
int buffer_size,
progress_callback callback);
+
+ arc_welder(arc_welder_args args) : arc_welder(
+ args.source_path,
+ args.target_path,
+ args.log,
+ 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_travel_arcs,
+ args.allow_dynamic_precision,
+ args.default_xyz_precision,
+ args.default_e_precision,
+ args.extrusion_rate_variance_percent,
+ args.max_gcode_length,
+ args.buffer_size,
+ args.callback
+ ){};
+
+
void set_logger_type(int logger_type);
virtual ~arc_welder();
arc_welder_results process();
@@ -455,10 +599,9 @@ private:
static gcode_position_args get_args_(bool g90_g91_influences_extruder, int buffer_size);
progress_callback progress_callback_;
int process_gcode(parsed_command cmd, bool is_end, bool is_reprocess);
- void write_arc_gcodes(bool is_extruder_relative, double current_feedrate);
+ void write_arc_gcodes(double current_feedrate);
int write_gcode_to_file(std::string gcode);
- std::string get_arc_gcode_relative(double f, const std::string comment);
- std::string get_arc_gcode_absolute(double e, double f, const std::string comment);
+ std::string get_arc_gcode(const std::string comment);
std::string get_comment_for_arc();
int write_unwritten_gcodes_to_file();
std::string create_g92_e(double absolute_e);
@@ -477,6 +620,7 @@ private:
int arcs_created_;
int arcs_aborted_by_flow_rate_;
source_target_segment_statistics segment_statistics_;
+ source_target_segment_statistics travel_statistics_;
long get_file_size(const std::string& file_path);
double get_time_elapsed(double start_clock, double end_clock);
double get_next_update_time() const;
diff --git a/ArcWelder/segmented_arc.cpp b/ArcWelder/segmented_arc.cpp
index 51ef57e..531c9e5 100644
--- a/ArcWelder/segmented_arc.cpp
+++ b/ArcWelder/segmented_arc.cpp
@@ -38,7 +38,10 @@ segmented_arc::segmented_arc() : segmented_shape(DEFAULT_MIN_SEGMENTS, DEFAULT_M
min_arc_segments_ = DEFAULT_MIN_ARC_SEGMENTS,
mm_per_arc_segment_ = DEFAULT_MM_PER_ARC_SEGMENT;
allow_3d_arcs_ = DEFAULT_ALLOW_3D_ARCS;
+ max_gcode_length_ = DEFAULT_MAX_GCODE_LENGTH;
+ num_gcode_length_exceptions_ = 0;
num_firmware_compensations_ = 0;
+
}
segmented_arc::segmented_arc(
@@ -51,7 +54,8 @@ segmented_arc::segmented_arc(
double mm_per_arc_segment,
bool allow_3d_arcs,
unsigned char default_xyz_precision,
- unsigned char default_e_precision
+ unsigned char default_e_precision,
+ int max_gcode_length
) : segmented_shape(min_segments, max_segments, resolution_mm, path_tolerance_percent, default_xyz_precision, default_e_precision)
{
max_radius_mm_ = max_radius_mm;
@@ -69,7 +73,15 @@ segmented_arc::segmented_arc(
min_arc_segments_ = 0;
}
allow_3d_arcs_ = allow_3d_arcs;
+ max_gcode_length_ = max_gcode_length;
+ if (max_gcode_length_ < 1)
+ {
+ max_gcode_length_ = 0;
+ }
num_firmware_compensations_ = 0;
+ num_gcode_length_exceptions_ = 0;
+
+
}
segmented_arc::~segmented_arc()
@@ -108,7 +120,10 @@ int segmented_arc::get_num_firmware_compensations() const
{
return num_firmware_compensations_;
}
-
+int segmented_arc::get_num_gcode_length_exceptions() const
+{
+ return num_gcode_length_exceptions_;
+}
double segmented_arc::get_mm_per_arc_segment() const
{
return mm_per_arc_segment_;
@@ -143,7 +158,7 @@ bool segmented_arc::try_add_point(printer_point p)
}
// Need to separate travel moves from moves with extrusion
- if (points_.count() > 2)
+ if (points_.count() > 1)
{
// We already have at least an initial point and a second point. Make cure the current point and the previous are either both
// travel moves, or both extrusion
@@ -217,6 +232,11 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
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_tolerance(), allow_3d_arcs_))
{
bool abort_arc = false;
+ if (max_gcode_length_ > 0 && get_shape_gcode_length() > max_gcode_length_)
+ {
+ abort_arc = true;
+ num_gcode_length_exceptions_++;
+ }
if (min_arc_segments_ > 0 && mm_per_arc_segment_ > 0)
{
// Apply firmware compensation
@@ -252,7 +272,7 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
// or because both I and J == 0
current_arc_ = original_arc;
}
- else if (!abort_arc)
+ else
{
if (!is_shape())
{
@@ -267,22 +287,12 @@ bool segmented_arc::try_add_point_internal_(printer_point p)
return false;
}
-std::string segmented_arc::get_shape_gcode_absolute(double e, double f)
-{
- bool has_e = e_relative_ != 0;
- return get_shape_gcode_(has_e, e, f);
-}
-
-std::string segmented_arc::get_shape_gcode_relative(double f)
-{
- bool has_e = e_relative_ != 0;
- return get_shape_gcode_(has_e, e_relative_, f);
-}
-
-std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) const
+std::string segmented_arc::get_shape_gcode() const
{
std::string gcode;
- // Calculate gcode size
+ double e = current_arc_.end_point.is_extruder_relative ? e_relative_ : current_arc_.end_point.e_offset;
+ double f = current_arc_.start_point.f == current_arc_.end_point.f ? 0 : current_arc_.end_point.f;
+ bool has_e = e_relative_ != 0;
bool has_f = utilities::greater_than_or_equal(f, 1);
bool has_z = allow_3d_arcs_ && !utilities::is_equal(
current_arc_.start_point.z, current_arc_.end_point.z, get_xyz_tolerance()
@@ -298,6 +308,9 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons
gcode += "G3";
}
+ // TODO: Limit Gcode Precision based on max_gcode_length
+
+
// Add X, Y, I and J
gcode += " X";
gcode += utilities::dtos(current_arc_.end_point.x, get_xyz_precision());
@@ -340,6 +353,40 @@ std::string segmented_arc::get_shape_gcode_(bool has_e, double e, double f) cons
}
+int segmented_arc::get_shape_gcode_length()
+{
+ double e = current_arc_.end_point.is_extruder_relative ? e_relative_ : current_arc_.end_point.e_offset;
+ double f = current_arc_.start_point.f == current_arc_.end_point.f ? 0 : current_arc_.end_point.f;
+ bool has_e = e_relative_ != 0;
+ bool has_f = utilities::greater_than_or_equal(f, 1);
+ bool has_z = allow_3d_arcs_ && !utilities::is_equal(
+ current_arc_.start_point.z, current_arc_.end_point.z, get_xyz_tolerance()
+ );
+
+ int xyz_precision = get_xyz_precision();
+ int e_precision = get_e_precision();
+
+ double i = current_arc_.get_i();
+ double j = current_arc_.get_j();
+
+ int num_spaces = 3 + (has_z ? 1 : 0) + (has_e ? 1 : 0) + (has_f ? 1 : 0);
+ int num_decimal_points = 4 + (has_z ? 1 : 0) + (has_e ? 1 : 0); // note f has no decimal point
+ int num_decimals = xyz_precision * (4 + (has_z ? 1 : 0) + (has_e ? 1 : 0)); // Note f is an int
+ int num_digits = (
+ utilities::get_num_digits(current_arc_.end_point.x) +
+ utilities::get_num_digits(current_arc_.end_point.y) +
+ (has_z ? utilities::get_num_digits(current_arc_.end_point.z) : 0) +
+ utilities::get_num_digits(i) +
+ utilities::get_num_digits(j) +
+ (has_f ? utilities::get_num_digits(f) : 0)
+ );
+ // Return the length of the gcode.
+ return 3 + num_spaces + num_decimal_points + num_decimal_points + num_digits;
+
+
+
+}
+
/*
* This is an older implementation using ostringstream. It is substantially slower.
* Keep this around in case there are problems with the custom dtos function
diff --git a/ArcWelder/segmented_arc.h b/ArcWelder/segmented_arc.h
index c67c071..2c7b240 100644
--- a/ArcWelder/segmented_arc.h
+++ b/ArcWelder/segmented_arc.h
@@ -42,14 +42,14 @@ public:
double mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT,
bool allow_3d_arcs = DEFAULT_ALLOW_3D_ARCS,
unsigned char default_xyz_precision = DEFAULT_XYZ_PRECISION,
- unsigned char default_e_precision = DEFAULT_E_PRECISION
+ unsigned char default_e_precision = DEFAULT_E_PRECISION,
+ int max_gcode_length = DEFAULT_MAX_GCODE_LENGTH
);
virtual ~segmented_arc();
virtual bool try_add_point(printer_point p);
virtual double get_shape_length();
- std::string get_shape_gcode_absolute(double e, double f);
- std::string get_shape_gcode_relative(double f);
-
+ std::string get_shape_gcode() const;
+ int get_shape_gcode_length();
virtual bool is_shape() const;
printer_point pop_front(double e_relative);
printer_point pop_back(double e_relative);
@@ -57,15 +57,16 @@ public:
int get_min_arc_segments() const;
double get_mm_per_arc_segment() const;
int get_num_firmware_compensations() const;
-
+ int get_num_gcode_length_exceptions() const;
private:
bool try_add_point_internal_(printer_point p);
- std::string get_shape_gcode_(bool has_e, double e, double f) const;
arc current_arc_;
double max_radius_mm_;
int min_arc_segments_;
double mm_per_arc_segment_;
int num_firmware_compensations_;
bool allow_3d_arcs_;
+ int max_gcode_length_;
+ int num_gcode_length_exceptions_;
};
diff --git a/ArcWelder/segmented_shape.cpp b/ArcWelder/segmented_shape.cpp
index 4e17d3c..447cfbe 100644
--- a/ArcWelder/segmented_shape.cpp
+++ b/ArcWelder/segmented_shape.cpp
@@ -359,7 +359,7 @@ bool circle::is_over_deviation(const array_list<printer_point>& points, const do
double distance = utilities::get_cartesian_distance(point_to_test.x, point_to_test.y, center.x, center.y);
if (std::fabs(distance - radius) > resolution_mm)
{
- return true;
+ return true;
}
}
}
@@ -380,9 +380,9 @@ double arc::get_j() const
bool arc::try_create_arc(
const circle& c,
- const point& start_point,
- const point& mid_point,
- const point& end_point,
+ const printer_point& start_point,
+ const printer_point& mid_point,
+ const printer_point& end_point,
arc& target_arc,
double approximate_length,
double resolution,
diff --git a/ArcWelder/segmented_shape.h b/ArcWelder/segmented_shape.h
index ec4bde9..d6e7218 100644
--- a/ArcWelder/segmented_shape.h
+++ b/ArcWelder/segmented_shape.h
@@ -36,7 +36,7 @@
#define DEFAULT_XYZ_TOLERANCE 0.001
#define DEFAULT_E_PRECISION 5
#define ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT 0.05 // one percent
-
+#define DEFAULT_MAX_GCODE_LENGTH 0 // the maximum gcode length ( < 1 = unlimited)
struct point
{
public:
@@ -53,9 +53,13 @@ public:
struct printer_point : point
{
public:
- printer_point() :point(0, 0, 0), e_relative(0), distance(0) {}
- printer_point(double x, double y, double z, double e_relative, double distance) :point(x,y,z), e_relative(e_relative), distance(distance) {}
+ printer_point() :point(0, 0, 0), e_relative(0), distance(0), is_extruder_relative(false), e_offset(0), f(0) {}
+ printer_point(double x, double y, double z, double e_offset, double e_relative, double f, double distance, bool is_extruder_relative)
+ : point(x,y,z), e_offset(e_offset), e_relative(e_relative), f(f), distance(distance), is_extruder_relative(is_extruder_relative) {}
+ bool is_extruder_relative;
+ double e_offset;
double e_relative;
+ double f;
double distance;
};
@@ -164,8 +168,8 @@ struct arc : circle
double polar_start_theta;
double polar_end_theta;
double max_deviation;
- point start_point;
- point end_point;
+ printer_point start_point;
+ printer_point end_point;
DirectionEnum direction;
double get_i() const;
double get_j() const;
@@ -185,9 +189,9 @@ struct arc : circle
private:
static bool try_create_arc(
const circle& c,
- const point& start_point,
- const point& mid_point,
- const point& end_point,
+ const printer_point& start_point,
+ const printer_point& mid_point,
+ const printer_point& end_point,
arc& target_arc,
double approximate_length,
double resolution = DEFAULT_RESOLUTION_MM,
diff --git a/ArcWelder/unwritten_command.h b/ArcWelder/unwritten_command.h
index 8f85a50..d1ed490 100644
--- a/ArcWelder/unwritten_command.h
+++ b/ArcWelder/unwritten_command.h
@@ -29,34 +29,18 @@ struct unwritten_command
{
unwritten_command() {
is_extruder_relative = false;
- e_relative = 0;
- offset_e = 0;
- extrusion_length = 0;
- is_g1_g2 = false;
+ length = 0;
+ is_g0_g1 = false;
}
- unwritten_command(parsed_command &cmd, bool is_relative, double command_length) {
- is_extruder_relative = is_relative;
- is_g1_g2 = cmd.command == "G0" || cmd.command == "G1";
- gcode = cmd.gcode;
- comment = cmd.comment;
- extrusion_length = command_length;
+ unwritten_command(parsed_command &cmd, bool is_relative, bool is_travel, double command_length)
+ : is_extruder_relative(is_relative), is_travel(is_travel), is_g0_g1(cmd.command == "G0" || cmd.command == "G1"), gcode(cmd.gcode), comment(cmd.comment), length(command_length)
+ {
+
}
- /*
- unwritten_command(position* p, double command_length) {
-
- e_relative = p->get_current_extruder().e_relative;
- offset_e = p->get_current_extruder().get_offset_e();
- is_extruder_relative = p->is_extruder_relative;
- is_g1_g2 = p->command.command == "G0" || p->command.command == "G1";
- gcode = p->command.gcode;
- comment = p->command.comment;
- extrusion_length = command_length;
- } */
- bool is_g1_g2;
+ bool is_g0_g1;
bool is_extruder_relative;
- double e_relative;
- double offset_e;
- double extrusion_length;
+ bool is_travel;
+ double length;
std::string gcode;
std::string comment;