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-11-25 22:36:18 +0300
committerFormerLurker <hochgebe@gmail.com>2021-11-25 22:36:18 +0300
commit9d1d644013ea74e89ac81f42006b115474cf955e (patch)
treeb35b72771f470e3af304cc60d3558957180eb162
parent274b33a225485571a012471e997738e437607fcc (diff)
Clean up error correction and debug parameters for the console applications. Update readme.md.
-rw-r--r--ArcWelder/arc_welder.cpp7
-rw-r--r--ArcWelder/arc_welder.h26
-rw-r--r--ArcWelderConsole/ArcWelderConsole.cpp398
-rw-r--r--ArcWelderConsole/ArcWelderConsole.vcxproj3
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp486
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.h3
-rw-r--r--ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj3
-rw-r--r--ArcWelderInverseProcessor/arc_interpolation.cpp6
-rw-r--r--ArcWelderInverseProcessor/arc_interpolation.h2
-rw-r--r--ArcWelderInverseProcessor/firmware.cpp33
-rw-r--r--ArcWelderInverseProcessor/firmware.h302
-rw-r--r--ArcWelderInverseProcessor/marlin_1.cpp9
-rw-r--r--ArcWelderInverseProcessor/marlin_2.cpp25
-rw-r--r--ArcWelderInverseProcessor/prusa.cpp36
-rw-r--r--ArcWelderInverseProcessor/prusa.h16
-rw-r--r--ArcWelderInverseProcessor/repetier.cpp18
-rw-r--r--ArcWelderInverseProcessor/smoothieware.cpp3
-rw-r--r--GcodeProcessorLib/fpconv.h3
-rw-r--r--GcodeProcessorLib/utilities.cpp26
-rw-r--r--GcodeProcessorLib/utilities.h4
-rw-r--r--TCLAP/TCLAP.vcxproj1
-rw-r--r--TCLAP/TCLAP.vcxproj.filters3
-rw-r--r--TCLAP/tclap/tclap_version.h3
-rw-r--r--readme.md133
24 files changed, 923 insertions, 626 deletions
diff --git a/ArcWelder/arc_welder.cpp b/ArcWelder/arc_welder.cpp
index 2103763..e9a9ddd 100644
--- a/ArcWelder/arc_welder.cpp
+++ b/ArcWelder/arc_welder.cpp
@@ -981,8 +981,11 @@ void arc_welder::add_arcwelder_comment_to_target()
}
stream << "; default_xyz_precision=" << std::setprecision(0) << static_cast<int>(current_arc_.get_xyz_precision()) << "\n";
stream << "; default_e_precision=" << std::setprecision(0) << static_cast<int>(current_arc_.get_e_precision()) << "\n";
- stream << "; extrusion_rate_variance_percent=" << std::setprecision(1) << (extrusion_rate_variance_percent_ * 100.0) << "%\n\n";
-
+ if (extrusion_rate_variance_percent_ > 0)
+ {
+ stream << "; extrusion_rate_variance=" << std::setprecision(1) << (extrusion_rate_variance_percent_ * 100.0) << "%\n";
+ }
+ stream << "\n";
output_file_ << stream.str();
}
diff --git a/ArcWelder/arc_welder.h b/ArcWelder/arc_welder.h
index ec07e7d..7535bf0 100644
--- a/ArcWelder/arc_welder.h
+++ b/ArcWelder/arc_welder.h
@@ -44,6 +44,8 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
+#define ARC_WELDER_INFO_STRING "Arc Welder: Anti-Stutter\nConverts G0/G1 commands to G2/G3 (arc) commands. Reduces the number of gcodes per second sent to a 3D printer, which can reduce stuttering.";
+
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 };
@@ -623,15 +625,31 @@ struct arc_welder_args
}
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 << "\tMaximum Arc Radius : " << std::setprecision(1) << max_radius_mm << "mm\n";
+ bool firmware_compensation_enabled = min_arc_segments > 0 && mm_per_arc_segment > 0.0;
+ stream << "\tFirmware Compensation : " << (firmware_compensation_enabled ? "True" : "False") << "\n";
+ if (firmware_compensation_enabled)
+ {
+ 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 << "\tExtrusion Rate Variance : ";
+ if (extrusion_rate_variance_percent == 0)
+ {
+ stream << "Unlimited";
+ }
+ else
+ {
+ stream << extrusion_rate_variance_percent * 100.0 << "%";
+ }
+ stream << "\n";
+
stream << "\tG90/G91 Influences Extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n";
if (max_gcode_length == 0)
{
diff --git a/ArcWelderConsole/ArcWelderConsole.cpp b/ArcWelderConsole/ArcWelderConsole.cpp
index a9245ad..dbc6085 100644
--- a/ArcWelderConsole/ArcWelderConsole.cpp
+++ b/ArcWelderConsole/ArcWelderConsole.cpp
@@ -32,6 +32,7 @@
#include <iomanip>
#include "gcode_position.h"
#include <tclap/CmdLine.h>
+#include <tclap/tclap_version.h>
#define DEFAULT_ARG_DOUBLE_PRECISION 4
#define PROGRESS_TYPE_NONE "NONE"
@@ -44,161 +45,157 @@ int main(int argc, char* argv[])
std::string log_level_string;
std::string log_level_string_default = "INFO";
std::string progress_type;
- std::string progress_type_default_string = PROGRESS_TYPE_SIMPLE;
int log_level_value;
bool hide_progress = false;
- // Add info about the application
- std::string info = "Arc Welder: Anti-Stutter - Reduces the number of gcodes per second sent to a 3D printer that supports arc commands (G2 G3).";
+ // Add info about the application
+ std::string info = "Arc Welder: Anti-Stutter\nConverts G0/G1 commands to G2/G3 (arc) commands. Reduces the number of gcodes per second sent to a 3D printer, which can reduce stuttering.";
// Add the current vesion information
info.append("\nVersion: ").append(GIT_TAGGED_VERSION);
info.append(", Branch: ").append(GIT_BRANCH);
info.append(", BuildDate: ").append(BUILD_DATE);
info.append("\n").append("Copyright(C) ").append(COPYRIGHT_DATE).append(" - ").append(AUTHOR);
- info.append("\n").append("An algorithm for producing fast floating point strings, fpconv, was added with the following notice: Copyright (C) 2014 Milo Yip");
- info.append("\n").append("The original fpconv algorithm provides the following notice: Copyright(c) 2013 Andreas Samoljuk");
+ info.append("\n").append("Includes source code derived from fpconv. ").append(FPCONV_COPYRIGHT_STRING);
+ info.append("\n").append("Includes TCLAP v").append(TCLAP_VERSION_STRING).append(". ").append(TCLAP_COPYRIGHT_STRING);
std::stringstream arg_description_stream;
arg_description_stream << std::fixed << std::setprecision(5);
- // Extract arguments
- try {
- // Define the command line object
- TCLAP::CmdLine cmd(info, '=', GIT_TAGGED_VERSION);
-
- // Define Arguments
-
+ // Define the command line object
+ TCLAP::CmdLine cmd(info, '=', GIT_TAGGED_VERSION);
+ // Define Arguments
// <SOURCE>
- TCLAP::UnlabeledValueArg<std::string> source_arg("source", "The source gcode file to convert.", true, "", "path to source gcode file");
-
- // <TARGET>
- TCLAP::UnlabeledValueArg<std::string> target_arg("target", "The target gcode file containing the converted code. If this is not supplied, the source path will be used and the source file will be overwritten.", false, "", "path to target gcode file");
-
- // -g --g90-influences-extruder
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "If supplied, G90/G91 influences the extruder axis. Default Value: " << DEFAULT_G90_G91_INFLUENCES_EXTRUDER;
- TCLAP::SwitchArg g90_arg("g", "g90-influences-extruder", arg_description_stream.str(), DEFAULT_G90_G91_INFLUENCES_EXTRUDER);
-
- // -r --resolution-mm
- arg_description_stream << "The resolution in mm of the of the output. Determines the maximum tool path deviation allowed during conversion. Default Value: " << DEFAULT_RESOLUTION_MM;
- TCLAP::ValueArg<double> resolution_arg("r", "resolution-mm", arg_description_stream.str(), false, DEFAULT_RESOLUTION_MM, "float");
-
- // -t --path-tolerance-percent
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "This is the maximum allowable difference between the arc path and the original toolpath.";
- arg_description_stream << " Expressed as a decimal percent, where 0.05 = 5.0%. The lower this value is, the more arcs will be aborted, but values over 0.25 (25%) are not recommended, as they could negatively impact print quality. Default Value: " << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT << " (" << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT * 100 << "%)";
- TCLAP::ValueArg<double> path_tolerance_percent_arg("t", "path-tolerance-percent", arg_description_stream.str(), false, DEFAULT_RESOLUTION_MM, "float");
-
- // -m --max-radius-mm
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The maximum radius of any arc in mm. Default Value: " << DEFAULT_MAX_RADIUS_MM;
- TCLAP::ValueArg<double> max_radius_arg("m", "max-radius-mm", arg_description_stream.str(), false, DEFAULT_MAX_RADIUS_MM, "float");
-
- // -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);
-
- // -y --allow-travel-arcs
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "(experimental) - If supplied, travel arcs will be allowed. Default Value: " << DEFAULT_ALLOW_TRAVEL_ARCS;
- TCLAP::SwitchArg allow_travel_arcs_arg("y", "allow-travel-arcs", arg_description_stream.str(), DEFAULT_ALLOW_TRAVEL_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 int> default_xyz_precision_arg("x", "default-xyz-precision", arg_description_stream.str(), false, DEFAULT_XYZ_PRECISION, "unsigned int");
-
- // -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 int> default_e_precision_arg("e", "default-e-precision", arg_description_stream.str(), false, DEFAULT_E_PRECISION, "unsigned int");
-
- // -s --mm-per-arc-segment
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The mm per arc segment as defined in your firmware. Used to compensate for firmware without min-arc-segments setting. Requires that min-arc-segments be set. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
- TCLAP::ValueArg<double> mm_per_arc_segment_arg("s", "mm-per-arc-segment", arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
-
- // -a --min-arc-segments
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The minimum number of segments in a full circle of the same radius as any given arc. Can only be used if --mm-per-arc-segment is also set. Used to compensate for firmware without min-arc-segments setting. Default: " << DEFAULT_MIN_ARC_SEGMENTS;
- TCLAP::ValueArg<int> min_arc_segments_arg("a", "min-arc-segments", arg_description_stream.str(), false, DEFAULT_MIN_ARC_SEGMENTS, "int");
-
- // -v --extrusion-rate-variance
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "(experimental) - The allowed variance in extrusion rate by percent, where 0.05 = 5.0%. A value of 0 will disable this feature. Default Value: " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT << " (" << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT * 100 << "%)";
- TCLAP::ValueArg<double> extrusion_rate_variance_percent_arg("v", "extrusion-rate-variance-percent", arg_description_stream.str(), false, DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT, "double");
-
- // -c --max-gcode-length
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The maximum length allowed for a generated G2/G3 command, not including any comments. 0 = no limit. Default Value: " << DEFAULT_MAX_GCODE_LENGTH;
- TCLAP::ValueArg<int> max_gcode_length_arg("c", "max-gcode-length", arg_description_stream.str(), false, DEFAULT_MAX_GCODE_LENGTH, "int");
-
- // -p --progress-type
- std::vector<std::string> progress_type_vector;
- std::string progress_type_default_string = PROGRESS_TYPE_SIMPLE;
- progress_type_vector.push_back(PROGRESS_TYPE_NONE);
- progress_type_vector.push_back(PROGRESS_TYPE_SIMPLE);
- progress_type_vector.push_back(PROGRESS_TYPE_FULL);
- TCLAP::ValuesConstraint<std::string> progress_type_constraint(progress_type_vector);
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Sets the progress type display. Default Value " << progress_type_default_string;
- TCLAP::ValueArg<std::string> progress_type_arg("p", "progress-type", arg_description_stream.str(), false, progress_type_default_string, &progress_type_constraint);
-
- // -l --log-level
- std::vector<std::string> log_levels_vector;
- log_levels_vector.push_back("NOSET");
- log_levels_vector.push_back("VERBOSE");
- log_levels_vector.push_back("DEBUG");
- log_levels_vector.push_back("INFO");
- log_levels_vector.push_back("WARNING");
- log_levels_vector.push_back("ERROR");
- log_levels_vector.push_back("CRITICAL");
- log_levels_vector.push_back("");
- TCLAP::ValuesConstraint<std::string> log_levels_constraint(log_levels_vector);
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Sets console log level. Default Value: " << log_level_string_default;
- TCLAP::ValueArg<std::string> log_level_arg("l", "log-level", arg_description_stream.str(), false, log_level_string_default, &log_levels_constraint);
+ TCLAP::UnlabeledValueArg<std::string> source_arg("source", "The source gcode file to convert.", true, "", "path to source gcode file");
+
+ // <TARGET>
+ TCLAP::UnlabeledValueArg<std::string> target_arg("target", "The target gcode file containing the converted code. If this is not supplied, the source path will be used and the source file will be overwritten.", false, "", "path to target gcode file");
+
+ // -g --g90-influences-extruder
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "If supplied, G90/G91 influences the extruder axis. Default Value: " << DEFAULT_G90_G91_INFLUENCES_EXTRUDER;
+ TCLAP::SwitchArg g90_arg("g", "g90-influences-extruder", arg_description_stream.str(), DEFAULT_G90_G91_INFLUENCES_EXTRUDER);
+
+ // -r --resolution-mm
+ arg_description_stream << "The resolution in mm of the of the output. Determines the maximum tool path deviation allowed during conversion. Restrictions: Only values greater than 0 are allowed. Default Value: " << DEFAULT_RESOLUTION_MM;
+ TCLAP::ValueArg<double> resolution_arg("r", "resolution-mm", arg_description_stream.str(), false, DEFAULT_RESOLUTION_MM, "float");
+
+ // -t --path-tolerance-percent
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "This is the maximum allowable difference between the arc path and the original toolpath.";
+ arg_description_stream << " Expressed as a decimal percent, where 0.05 = 5.0%. The lower this value is, the more arcs will be aborted, but values over 0.25 (25%) are not recommended, as they could negatively impact print quality. Restrictions: Only values greater than 0 (0%) and less than 1.0 (100%) are allowed. Default Value: " << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT << " (" << ARC_LENGTH_PERCENT_TOLERANCE_DEFAULT * 100 << "%)";
+ TCLAP::ValueArg<double> path_tolerance_percent_arg("t", "path-tolerance-percent", arg_description_stream.str(), false, DEFAULT_RESOLUTION_MM, "float");
+
+ // -m --max-radius-mm
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The maximum radius of any arc in mm. Restrictions: Only values greater than 0.0 are allowed. Default Value: " << DEFAULT_MAX_RADIUS_MM;
+ TCLAP::ValueArg<double> max_radius_arg("m", "max-radius-mm", arg_description_stream.str(), false, DEFAULT_MAX_RADIUS_MM, "float");
+
+ // -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);
+
+ // -y --allow-travel-arcs
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "(experimental) - If supplied, travel arcs will be allowed. Default Value: " << DEFAULT_ALLOW_TRAVEL_ARCS;
+ TCLAP::SwitchArg allow_travel_arcs_arg("y", "allow-travel-arcs", arg_description_stream.str(), DEFAULT_ALLOW_TRAVEL_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. Restrictions: Allowed values are 3, 4, 5, or 6. Default Value: " << DEFAULT_XYZ_PRECISION;
+ TCLAP::ValueArg<unsigned int> default_xyz_precision_arg("x", "default-xyz-precision", arg_description_stream.str(), false, DEFAULT_XYZ_PRECISION, "unsigned int");
+
+ // -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. Restrictions: Allowed values are 3, 4, 5, or 6. Default Value: " << DEFAULT_E_PRECISION;
+ TCLAP::ValueArg<unsigned int> default_e_precision_arg("e", "default-e-precision", arg_description_stream.str(), false, DEFAULT_E_PRECISION, "unsigned int");
+
+ // -s --mm-per-arc-segment
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The mm per arc segment as defined in your firmware. Used to compensate for firmware without min-arc-segments setting. Restrictions: Only values greater than or equal to 0.0 are allowed. If set greater than 0, min-arc-segments must also be set. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
+ TCLAP::ValueArg<double> mm_per_arc_segment_arg("s", "mm-per-arc-segment", arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
+
+ // -a --min-arc-segments
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The minimum number of segments in a full circle of the same radius as any given arc. Used to compensate for firmware without min-arc-segments setting. Restrictions: Only values greater than or equal to 0.0 are allowed. If set greater than 0, mm-per-arc-segment must also be set. Default Value: " << DEFAULT_MIN_ARC_SEGMENTS;
+ TCLAP::ValueArg<int> min_arc_segments_arg("a", "min-arc-segments", arg_description_stream.str(), false, DEFAULT_MIN_ARC_SEGMENTS, "int");
+
+ // -v --extrusion-rate-variance
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "(experimental) - The allowed variance in extrusion rate by percent, where 0.05 = 5.0%. A value of 0 will disable this feature. Restrictions: Only values greater than or equal to 0.0 are allowed. Default Value: " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT << " (" << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT * 100 << "%)";
+ TCLAP::ValueArg<double> extrusion_rate_variance_percent_arg("v", "extrusion-rate-variance-percent", arg_description_stream.str(), false, DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT, "double");
+
+ // -c --max-gcode-length
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The maximum length allowed for a generated G2/G3 command, not including any comments. 0 = no limit. Restrictions: Can be set to 0, or values > 30. Default Value: " << DEFAULT_MAX_GCODE_LENGTH;
+ TCLAP::ValueArg<int> max_gcode_length_arg("c", "max-gcode-length", arg_description_stream.str(), false, DEFAULT_MAX_GCODE_LENGTH, "int");
+
+ // -p --progress-type
+ std::vector<std::string> progress_type_vector;
+ std::string progress_type_default_string = PROGRESS_TYPE_SIMPLE;
+ progress_type_vector.push_back(PROGRESS_TYPE_NONE);
+ progress_type_vector.push_back(PROGRESS_TYPE_SIMPLE);
+ progress_type_vector.push_back(PROGRESS_TYPE_FULL);
+ TCLAP::ValuesConstraint<std::string> progress_type_constraint(progress_type_vector);
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets the progress type display. Default Value " << progress_type_default_string;
+ TCLAP::ValueArg<std::string> progress_type_arg("p", "progress-type", arg_description_stream.str(), false, progress_type_default_string, &progress_type_constraint);
+
+ // -l --log-level
+ std::vector<std::string> log_levels_vector;
+ log_levels_vector.push_back("NOSET");
+ log_levels_vector.push_back("VERBOSE");
+ log_levels_vector.push_back("DEBUG");
+ log_levels_vector.push_back("INFO");
+ log_levels_vector.push_back("WARNING");
+ log_levels_vector.push_back("ERROR");
+ log_levels_vector.push_back("CRITICAL");
+ TCLAP::ValuesConstraint<std::string> log_levels_constraint(log_levels_vector);
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets console log level. Default Value: " << log_level_string_default;
+ TCLAP::ValueArg<std::string> log_level_arg("l", "log-level", arg_description_stream.str(), false, log_level_string_default, &log_levels_constraint);
+
+
+ // Add all arguments
+ cmd.add(source_arg);
+ cmd.add(target_arg);
+ cmd.add(resolution_arg);
+ cmd.add(path_tolerance_percent_arg);
+ cmd.add(max_radius_arg);
+ cmd.add(min_arc_segments_arg);
+ cmd.add(mm_per_arc_segment_arg);
+ cmd.add(allow_3d_arcs_arg);
+ cmd.add(allow_travel_arcs_arg);
+ cmd.add(allow_dynamic_precision_arg);
+ cmd.add(default_xyz_precision_arg);
+ cmd.add(default_e_precision_arg);
+ cmd.add(extrusion_rate_variance_percent_arg);
+ cmd.add(max_gcode_length_arg);
+ cmd.add(g90_arg);
+ cmd.add(progress_type_arg);
+ cmd.add(log_level_arg);
+ try {
- // Add all arguments
- cmd.add(source_arg);
- cmd.add(target_arg);
- cmd.add(resolution_arg);
- cmd.add(path_tolerance_percent_arg);
- cmd.add(max_radius_arg);
- cmd.add(min_arc_segments_arg);
- cmd.add(mm_per_arc_segment_arg);
- cmd.add(allow_3d_arcs_arg);
- cmd.add(allow_travel_arcs_arg);
- cmd.add(allow_dynamic_precision_arg);
- cmd.add(default_xyz_precision_arg);
- cmd.add(default_e_precision_arg);
- cmd.add(extrusion_rate_variance_percent_arg);
- cmd.add(max_gcode_length_arg);
- cmd.add(g90_arg);
- cmd.add(progress_type_arg);
- cmd.add(log_level_arg);
-
// Parse the argv array.
cmd.parse(argc, argv);
@@ -220,108 +217,114 @@ int main(int argc, char* argv[])
args.allow_travel_arcs = allow_travel_arcs_arg.getValue();
args.g90_g91_influences_extruder = g90_arg.getValue();
args.allow_dynamic_precision = allow_dynamic_precision_arg.getValue();
- unsigned int xyz_precision = default_xyz_precision_arg.getValue();
- unsigned int e_precision = default_e_precision_arg.getValue();
+ args.default_xyz_precision = static_cast<unsigned char>(default_xyz_precision_arg.getValue());
+ args.default_e_precision = static_cast<unsigned char>(default_e_precision_arg.getValue());
args.extrusion_rate_variance_percent = extrusion_rate_variance_percent_arg.getValue();
args.max_gcode_length = max_gcode_length_arg.getValue();
progress_type = progress_type_arg.getValue();
log_level_string = log_level_arg.getValue();
log_level_value = -1;
+
+ // ensure the source file exists
+ if (!utilities::does_file_exist(args.source_path))
+ {
+ throw TCLAP::ArgException("The source file does not exist at the specified path.", source_arg.getName(), "File does not exist error");
+ }
- // Check the entered values
- bool has_error = false;
if (args.resolution_mm <= 0)
{
- std::cerr << "error: The provided resolution of " << args.resolution_mm << " is negative, which is not allowed." <<std::endl;
- has_error = true;
+ throw TCLAP::ArgException("The provided value is less than or equal to 0.", resolution_arg.toString());
}
- if (args.path_tolerance_percent < 0)
+ if (args.path_tolerance_percent <= 0)
{
- std::cerr << "error: The provided path tolerance percentage of " << args.path_tolerance_percent << " is negative, which is not allowed." << std::endl;
- has_error = true;
+ throw TCLAP::ArgException("The provided value is less than or equal to 0.", path_tolerance_percent_arg.toString());
}
- if (args.max_radius_mm > 1000000)
+ if (args.path_tolerance_percent >= 1.0)
{
- // warning
- std::cout << "warning: The provided path max radius of " << args.max_radius_mm << "mm is greater than 1000000 (1km), which is not recommended." << std::endl;
+ throw TCLAP::ArgException("The provided value is greater than or equal to 1 (100%).", path_tolerance_percent_arg.toString());
}
- if (args.min_arc_segments < 0)
+ if (args.mm_per_arc_segment < 0)
{
- // warning
- std::cout << "warning: The provided min_arc_segments " << args.min_arc_segments << " is less than zero. Setting to 0." << std::endl;
- args.min_arc_segments = 0;
+ throw TCLAP::ArgException("The provided value is negative.", mm_per_arc_segment_arg.toString());
}
- if (args.mm_per_arc_segment < 0)
+ if (args.min_arc_segments < 0)
{
- // warning
- std::cout << "warning: The provided mm_per_arc_segment " << args.mm_per_arc_segment << "mm is less than zero. Setting to 0." << std::endl;
- args.mm_per_arc_segment = 0;
+ throw TCLAP::ArgException("The provided value is negative.", min_arc_segments_arg.toString());
}
- if (args.path_tolerance_percent > 0.25)
+ if (args.mm_per_arc_segment != 0.0 && args.min_arc_segments == 0)
{
- // warning
- std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is greater than 0.25 (25%), which is not recommended." << std::endl;
+ throw TCLAP::ArgException("You must also specify a non zero value for the " + min_arc_segments_arg.toString() + " argument.", mm_per_arc_segment_arg.toString());
}
- else if (args.path_tolerance_percent < 0.001 && args.path_tolerance_percent > 0)
+ else if (args.mm_per_arc_segment == 0.0 && args.min_arc_segments != 0)
{
- // warning
- std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is less than 0.001 (0.1%), which is not recommended, and will result in very few arcs being generated." << std::endl;
+ throw TCLAP::ArgException("You must also specify a non zero value for the " + mm_per_arc_segment_arg.toString() + " argument.", min_arc_segments_arg.toString());
}
- if (xyz_precision < 3)
+ if (args.default_xyz_precision < 3)
{
- // warning
- std::cout << "warning: The provided default_xyz_precision " << xyz_precision << "mm is less than 3, with will cause issues printing arcs. A value of 3 will be used instead." << std::endl;
- xyz_precision = 3;
+ throw TCLAP::ArgException("The provided value is less than 3.", default_xyz_precision_arg.toString());
}
- if (e_precision < DEFAULT_E_PRECISION)
+ if (args.default_e_precision < 3)
{
- // warning
- std::cout << "warning: The provided default_e_precision " << e_precision << "mm is less than 3, with will cause extrusion issues. A value of 3 will be used instead." << std::endl;
- e_precision = 3;
+ throw TCLAP::ArgException("The provided value is less than 3.", default_e_precision_arg.toString());
}
- if (xyz_precision > 6)
+ if (args.default_xyz_precision > 6)
{
- // warning
- std::cout << "warning: The provided default_xyz_precision " << 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;
- xyz_precision = 6;
+ throw TCLAP::ArgException("The provided value is greater than 6.", default_xyz_precision_arg.toString());
}
- if (e_precision > 6)
+ if (args.default_e_precision > 6)
{
- // warning
- std::cout << "warning: The provided default_e_precision " << 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;
- e_precision = 6;
+ throw TCLAP::ArgException("The provided value is greater than 6.", default_e_precision_arg.toString());
}
-
- // Fill in the adjusted precisions
- args.default_e_precision = (unsigned char)e_precision;
- args.default_xyz_precision = (unsigned char)xyz_precision;
-
+
if (args.extrusion_rate_variance_percent < 0)
{
- // warning
- std::cout << "warning: The provided extrusion_rate_variance_percent " << args.extrusion_rate_variance_percent << " is less than 0. Applying the default setting of " << DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT*100 << "%." << std::endl;
- args.extrusion_rate_variance_percent = DEFAULT_EXTRUSION_RATE_VARIANCE_PERCENT;
+ throw TCLAP::ArgException("The provided value is negative.", extrusion_rate_variance_percent_arg.toString());
}
if (args.max_gcode_length < 0)
{
- // warning
- std::cout << "warning: The provided max_gcode_length " << args.max_gcode_length << " is less than 0. Setting to the default (no limit)." << std::endl;
- args.max_gcode_length = DEFAULT_MAX_GCODE_LENGTH;
+ throw TCLAP::ArgException("The provided value is negative.", max_gcode_length_arg.toString());
+ }
+
+ if (args.max_gcode_length > 0 && args.max_gcode_length < 31)
+ {
+ throw TCLAP::ArgException("The provided value is greater than 0 and less than 31.", max_gcode_length_arg.toString());
+ }
+ if (args.max_radius_mm <= 0)
+ {
+ throw TCLAP::ArgException("The provided value is less than or equal to 0.", max_radius_arg.toString());
+ }
+
+ if (args.extrusion_rate_variance_percent == 0)
+ {
+ // warning
+ std::cout << "warning: The provided path max radius of " << args.max_radius_mm << "mm is greater than 1000000 (1km), which is not recommended.\n";
}
- if (has_error)
+ if (args.max_radius_mm > 1000000)
+ {
+ // warning
+ std::cout << "warning: The provided path max radius of " << args.max_radius_mm << "mm is greater than 1000000 (1km), which is not recommended.\n";
+ }
+
+ if (args.path_tolerance_percent > 0.25)
+ {
+ // warning
+ std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is greater than 0.25 (25%), which is not recommended.\n";
+ }
+ else if (args.path_tolerance_percent < 0.001 && args.path_tolerance_percent > 0)
{
- return 1;
+ // warning
+ std::cout << "warning: The provided path tolerance percent of " << args.path_tolerance_percent << " is less than 0.001 (0.1%), which is not recommended, and will result in very few arcs being generated.\n";
}
for (unsigned int log_name_index = 0; log_name_index < log_level_names_size; log_name_index++)
@@ -335,14 +338,15 @@ int main(int argc, char* argv[])
if (log_level_value == -1)
{
// TODO: Does this work?
- throw new TCLAP::ArgException("Unknown log level");
+ throw new TCLAP::ArgException("Unknown log level", log_level_arg.toString());
}
}
// catch argument exceptions
catch (TCLAP::ArgException& e)
{
- std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
+ // This will raise an exit exception
+ cmd.getOutput()->failure(cmd, e);
return 1;
}
diff --git a/ArcWelderConsole/ArcWelderConsole.vcxproj b/ArcWelderConsole/ArcWelderConsole.vcxproj
index 9bfc6c5..c7b54b2 100644
--- a/ArcWelderConsole/ArcWelderConsole.vcxproj
+++ b/ArcWelderConsole/ArcWelderConsole.vcxproj
@@ -106,10 +106,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\TCLAP\</IncludePath>
+ <TargetName>ArcWelder</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Remote_Pi|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\TCLAP\</IncludePath>
+ <TargetName>ArcWelder</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -119,6 +121,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\GcodeProcessorLib\;$(SolutionDir)\ArcWelder\;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\TCLAP\</IncludePath>
+ <TargetName>ArcWelder</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
index f3d35c3..9a82f76 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.cpp
@@ -46,7 +46,13 @@
#include "version.h"
#include "utilities.h"
#include <tclap/CmdLine.h>
+#include <tclap/tclap_version.h>
#define DEFAULT_ARG_DOUBLE_PRECISION 4
+#define COMMAND_LINE_ARGUMENT_SEPARATOR ","
+#define COMMAND_LINE_ARGUMENT_PREFIX "--"
+#define COMMAND_LINE_ARGUMENT_PREFIX_SHORT "-"
+#define COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING "_"
+#define COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE "-"
int main(int argc, char* argv[])
{
try {
@@ -59,13 +65,13 @@ int main(int argc, char* argv[])
}
int run_arc_straightener(int argc, char* argv[])
{
- std::string info = "Arc Straightener - Converts G2/G3 commands to G1/G2 commands..";
+ std::string info = "Arc Straightener\nConverts G2/G3 commands to G1/G2 commands..";
info.append("\nVersion: ").append(GIT_TAGGED_VERSION);
info.append(", Branch: ").append(GIT_BRANCH);
info.append(", BuildDate: ").append(BUILD_DATE);
info.append("\n").append("Copyright(C) ").append(COPYRIGHT_DATE).append(" - ").append(AUTHOR);
-
+ info.append("\n").append("Includes TCLAP v").append(TCLAP_VERSION_STRING).append(". ").append(TCLAP_COPYRIGHT_STRING);
std::stringstream arg_description_stream;
arg_description_stream << std::fixed << std::setprecision(5);
@@ -82,196 +88,252 @@ int run_arc_straightener(int argc, char* argv[])
repetier repetier_firmware(args.firmware_args);
prusa prusa_firmware(args.firmware_args);
smoothieware smoothieware_firmware(args.firmware_args);
-
- // Extract arguments
- try {
- // Define the command line object
- TCLAP::CmdLine cmd(info, '=', GIT_TAGGED_VERSION);
- // Define a special command line object for various help requests
- TCLAP::CmdLine help_cmd(info, '=', GIT_TAGGED_VERSION, false);
+
+ // Define the command line object
+ TCLAP::CmdLine cmd(info, '=', GIT_TAGGED_VERSION);
+ // Define a special command line object for various help requests
+ TCLAP::CmdLine help_cmd(info, '=', GIT_TAGGED_VERSION, false);
- // <SOURCE>
- TCLAP::UnlabeledValueArg<std::string> source_arg("source", "The source gcode file to convert.", true, "", "path to source gcode file");
+ // <SOURCE>
+ TCLAP::UnlabeledValueArg<std::string> source_arg("source", "The source gcode file to convert.", true, "", "path to source gcode file");
- // <TARGET>
- TCLAP::UnlabeledValueArg<std::string> target_arg("target", "The target gcode file containing the converted code. If this is not supplied, the source path will be used and the source file will be overwritten.", false, "", "path to target gcode file");
+ // <TARGET>
+ TCLAP::UnlabeledValueArg<std::string> target_arg("target", "The target gcode file containing the converted code. If this is not supplied, the source path will be used and the source file will be overwritten.", false, "", "path to target gcode file");
- // -f --firmware-type
- std::vector<std::string> firmware_types_vector;
- for (int i = 0; i < NUM_FIRMWARE_TYPES; i++)
- {
+ // -f --firmware-type
+ std::vector<std::string> firmware_types_vector;
+ for (int i = 0; i < NUM_FIRMWARE_TYPES; i++)
+ {
firmware_types_vector.push_back(firmware_type_names[i]);
- }
- TCLAP::ValuesConstraint<std::string> firmware_type_constraint(firmware_types_vector);
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Sets the firmware to emulate. Default Value: " << firmware_type_names[DEFAULT_FIRMWARE_TYPE];
- TCLAP::ValueArg<std::string> firmware_type_arg("f", "firmware-type", arg_description_stream.str(), false, firmware_type_names[DEFAULT_FIRMWARE_TYPE], &firmware_type_constraint);
-
- // -v --firmware-version
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Sets the firmware version to use. The available versions depend on the firmware type selected. " << DEFAULT_FIRMWARE_VERSION_NAME << " will select the most recent version available.\n";
- arg_description_stream << "\tMARLIN 1 versions: " << utilities::join(marlin_1_firmware.get_version_names(), ", ") << "\n";
- arg_description_stream << "\tMARLIN 2 versions: " << utilities::join(marlin_2_firmware.get_version_names(), ", ") << "\n";
- arg_description_stream << "\tREPETIER versions: " << utilities::join(repetier_firmware.get_version_names(), ", ") << "\n";
- arg_description_stream << "\tPRUSA versions: " << utilities::join(prusa_firmware.get_version_names(), ", ") << "\n";
- arg_description_stream << "\tSMOOTHIEWARE versions: " << utilities::join(smoothieware_firmware.get_version_names(), ", ") << "\n";
- arg_description_stream << "\tDefault Value: " << DEFAULT_FIRMWARE_VERSION_NAME;
- TCLAP::ValueArg<std::string> firmware_version_arg("v", "firmware-version", arg_description_stream.str(), false, DEFAULT_FIRMWARE_VERSION_NAME, "string");
-
- // -p --print-firmware-defaults
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Prints all available settings and defaults for the provided firmware type and version. If provided, all other parameters will be ignored except for " << firmware_type_arg.getName() << " and " << firmware_version_arg.getName() << ".";
- TCLAP::SwitchArg print_firmware_defaults_arg("p", "print-firmware-defaults", arg_description_stream.str());
-
- // -g --g90-influences-extruder
- std::string g90_g91_influences_extruder_default_value = "DEFAULT";
- std::vector<std::string> g90_g91_influences_extruder_vector;
- g90_g91_influences_extruder_vector.push_back("TRUE");
- g90_g91_influences_extruder_vector.push_back("FALSE");
- g90_g91_influences_extruder_vector.push_back(g90_g91_influences_extruder_default_value);
- TCLAP::ValuesConstraint<std::string> g90_g91_influences_extruder_constraint(g90_g91_influences_extruder_vector);
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Sets the firmware's G90/G91 influences extruder axis behavior. By default this is determined by the firmware's behavior. Default Value: " << g90_g91_influences_extruder_default_value;
- TCLAP::ValueArg<std::string> g90_arg("g", "g90-influences-extruder", arg_description_stream.str(), false, g90_g91_influences_extruder_default_value, &g90_g91_influences_extruder_constraint);
-
- // -m --mm-per-arc-segment
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The default segment length. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
- TCLAP::ValueArg<double> mm_per_arc_segment_arg("m", "mm-per-arc-segment", arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
-
- // max_arc_segment_mm_arg
- // -d --max-arc-segment-mm
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The maximum length of an arc segment. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
- TCLAP::ValueArg<double> max_arc_segment_mm_arg("d", "max-arc-segment-mm", arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
-
- // -n --min-mm-per-arc-segment
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The minimum mm per arc segment. Used to prevent unnecessarily small segments from being generated. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_MM_PER_ARC_SEGMENT;
- TCLAP::ValueArg<double> min_mm_per_arc_segment_arg("n", "min-mm-per-arc-segment", arg_description_stream.str(), false, DEFAULT_MIN_MM_PER_ARC_SEGMENT, "float");
+ }
+ TCLAP::ValuesConstraint<std::string> firmware_type_constraint(firmware_types_vector);
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets the firmware to emulate. Default Value: " << firmware_type_names[DEFAULT_FIRMWARE_TYPE];
+ std::string arg_name_firmare_type = "firmware-type";
+ std::string arg_short_name_firmare_type = "f";
+ TCLAP::ValueArg<std::string> firmware_type_arg("f", "firmware-type", arg_description_stream.str(), false, firmware_type_names[DEFAULT_FIRMWARE_TYPE], &firmware_type_constraint);
+
+ // -v --firmware-version
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets the firmware version to use. The available versions depend on the firmware type selected. " << DEFAULT_FIRMWARE_VERSION_NAME << " will select the most recent version available.\n";
+ arg_description_stream << "\tMARLIN 1 versions: " << utilities::join(marlin_1_firmware.get_version_names(), ", ") << "\n";
+ arg_description_stream << "\tMARLIN 2 versions: " << utilities::join(marlin_2_firmware.get_version_names(), ", ") << "\n";
+ arg_description_stream << "\tREPETIER versions: " << utilities::join(repetier_firmware.get_version_names(), ", ") << "\n";
+ arg_description_stream << "\tPRUSA versions: " << utilities::join(prusa_firmware.get_version_names(), ", ") << "\n";
+ arg_description_stream << "\tSMOOTHIEWARE versions: " << utilities::join(smoothieware_firmware.get_version_names(), ", ") << "\n";
+ arg_description_stream << "\tDefault Value: " << DEFAULT_FIRMWARE_VERSION_NAME;
+ std::string arg_name_firmare_version = "firmware-version";
+ std::string arg_short_name_firmare_version = "v";
+ TCLAP::ValueArg<std::string> firmware_version_arg(arg_short_name_firmare_version, arg_name_firmare_version, arg_description_stream.str(), false, DEFAULT_FIRMWARE_VERSION_NAME, "string");
+
+ // -p --print-firmware-defaults
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Prints all available settings and defaults for the provided firmware type and version. If provided, all other parameters will be ignored except for " << firmware_type_arg.getName() << " and " << firmware_version_arg.getName() << ".";
+ std::string arg_name_print_firmware_defaults = "print-firmware-defaults";
+ std::string arg_short_name_print_firmware_defaults = "p";
+ TCLAP::SwitchArg print_firmware_defaults_arg(arg_short_name_print_firmware_defaults, arg_name_print_firmware_defaults, arg_description_stream.str());
+
+ // -g --g90-influences-extruder
+ std::string g90_g91_influences_extruder_default_value = "DEFAULT";
+ std::vector<std::string> g90_g91_influences_extruder_vector;
+ g90_g91_influences_extruder_vector.push_back("TRUE");
+ g90_g91_influences_extruder_vector.push_back("FALSE");
+ g90_g91_influences_extruder_vector.push_back(g90_g91_influences_extruder_default_value);
+ TCLAP::ValuesConstraint<std::string> g90_g91_influences_extruder_constraint(g90_g91_influences_extruder_vector);
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets the firmware's G90/G91 influences extruder axis behavior. By default this is determined by the firmware's behavior. Default Value: " << g90_g91_influences_extruder_default_value;
+ std::string arg_name_g90_g91_influences_extruder = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<std::string> g90_arg("g", arg_name_g90_g91_influences_extruder, arg_description_stream.str(), false, g90_g91_influences_extruder_default_value, &g90_g91_influences_extruder_constraint);
+
+ // -m --mm-per-arc-segment
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The default segment length. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
+ std::string arg_name_mm_per_arc_segment = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> mm_per_arc_segment_arg("m", arg_name_mm_per_arc_segment, arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
+
+ // max_arc_segment_mm_arg -- same funciton as max_arc_segment_mm
+ // -d --max-arc-segment-mm
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The maximum length of an arc segment. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
+ std::string arg_name_max_arc_segment_mm = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> max_arc_segment_mm_arg("d", arg_name_max_arc_segment_mm, arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
+
+ // arc_segments_per_r -- same funciton as max_arc_segment_mm
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The maximum length of an arc segment. Default Value: " << DEFAULT_MM_PER_ARC_SEGMENT;
+ std::string arg_name_arc_segments_per_r = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> arc_segments_per_r_arg("i", arg_name_arc_segments_per_r, arg_description_stream.str(), false, DEFAULT_MM_PER_ARC_SEGMENT, "float");
+
+ // -n --min-mm-per-arc-segment
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The minimum mm per arc segment. Used to prevent unnecessarily small segments from being generated. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_MM_PER_ARC_SEGMENT;
+ std::string arg_name_min_mm_per_arc_segment = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> min_mm_per_arc_segment_arg("n", arg_name_min_mm_per_arc_segment, arg_description_stream.str(), false, DEFAULT_MIN_MM_PER_ARC_SEGMENT, "float");
+
+ // min_arc_segment_mm
+ // -b --min-arc-segment-mm
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The minimum mm per arc segment. Used to prevent unnecessarily small segments from being generated. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_MM_PER_ARC_SEGMENT;
+ std::string arg_name_min_arc_segment_mm = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> min_arc_segment_mm_arg("b", arg_name_min_arc_segment_mm, arg_description_stream.str(), false, DEFAULT_MIN_MM_PER_ARC_SEGMENT, "float");
+
+ // -r --min-arc-segments
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The minimum number of segments within a circle of the same radius as the arc. Can be used to increase detail on small arcs. The smallest segment generated will be no larger than min_mm_per_arc_segment. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_ARC_SEGMENTS;
+ std::string arg_name_min_arc_segments = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<int> min_arc_segments_arg("r", arg_name_min_arc_segments, arg_description_stream.str(), false, DEFAULT_MIN_ARC_SEGMENTS, "int");
+
+ // min_circle_segments_arg
+ // -a --min-circle-segments-arg
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The minimum number of segments within a circle of the same radius as the arc. Can be used to increase detail on small arcs. The smallest segment generated will be no larger than min_mm_per_arc_segment. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_ARC_SEGMENTS;
+ std::string arg_name_min_circle_segments = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<int> min_circle_segments_arg("a", arg_name_min_circle_segments, arg_description_stream.str(), false, DEFAULT_MIN_CIRCLE_SEGMENTS, "int");
+
+ // -c --n-arc-correction
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The number of segments that will be interpolated using a small angle approximation before true sin/cos corrections are applied. A value less than or equal to 1 will disable this feature. Default Value: " << DEFAULT_N_ARC_CORRECTIONS;
+ std::string arg_name_n_arc_correction = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_N_ARC_CORRECTION, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<int> n_arc_correction_arg("c", arg_name_n_arc_correction, arg_description_stream.str(), false, DEFAULT_N_ARC_CORRECTIONS, "int");
+
+ // -s --arc-segments-per-second
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "The number of segments per second. This will produce a constant number of arcs, clamped between mm-per-arc-segment and min-mm-per-arc-segment. Can be used to prevent stuttering when printing very quickly. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_ARC_SEGMENTS_PER_SEC;
+ std::string arg_name_arc_segments_per_sec = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> arc_segments_per_sec_arg("s", arg_name_arc_segments_per_sec, arg_description_stream.str(), false, DEFAULT_MIN_MM_PER_ARC_SEGMENT, "float");
+
+ // -e --mm-max-arc-error
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "This currently is only used in Smoothieware. The maximum error for line segments that divide arcs. Set to 0 to disable. Default Value: " << DEFAULT_MM_MAX_ARC_ERROR;
+ std::string arg_name_mm_max_arc_error = firmware_arguments::get_argument_string(FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR, "", COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
+ TCLAP::ValueArg<double> mm_max_arc_error_arg("e", arg_name_mm_max_arc_error, arg_description_stream.str(), false, DEFAULT_MM_MAX_ARC_ERROR, "float");
+
+ // -l --log-level
+ std::vector<std::string> log_levels_vector;
+ log_levels_vector.push_back("NOSET");
+ log_levels_vector.push_back("VERBOSE");
+ log_levels_vector.push_back("DEBUG");
+ log_levels_vector.push_back("INFO");
+ log_levels_vector.push_back("WARNING");
+ log_levels_vector.push_back("ERROR");
+ log_levels_vector.push_back("CRITICAL");
+ log_levels_vector.push_back("");
+ TCLAP::ValuesConstraint<std::string> log_levels_constraint(log_levels_vector);
+ arg_description_stream.clear();
+ arg_description_stream.str("");
+ arg_description_stream << "Sets console log level. Possible values: Default Value: " << log_level_string_default;
+ TCLAP::ValueArg<std::string> log_level_arg("l", "log-level", arg_description_stream.str(), false, log_level_string_default, &log_levels_constraint);
+
+
+ // Add all arguments
+ cmd.add(source_arg);
+ cmd.add(target_arg);
+ cmd.add(firmware_type_arg);
+ cmd.add(firmware_version_arg);
+ cmd.add(g90_arg);
+ cmd.add(mm_per_arc_segment_arg);
+ cmd.add(min_mm_per_arc_segment_arg);
+ cmd.add(min_arc_segments_arg);
+ cmd.add(n_arc_correction_arg);
+ cmd.add(arc_segments_per_sec_arg);
+ cmd.add(log_level_arg);
+ cmd.add(min_circle_segments_arg);
+ cmd.add(min_arc_segment_mm_arg);
+ cmd.add(max_arc_segment_mm_arg);
+ cmd.add(arc_segments_per_r_arg);
+ cmd.add(print_firmware_defaults_arg);
+ cmd.add(mm_max_arc_error_arg);
+
+ // First, we need to see if the user wants to print firmware defaults
+ help_cmd.add(firmware_type_arg);
+ help_cmd.add(firmware_version_arg);
+ help_cmd.add(print_firmware_defaults_arg);
+ help_cmd.ignoreUnmatched(true);
+ help_cmd.setExceptionHandling(false);
+
+
- // min_arc_segment_mm
- // -b --min-arc-segment-mm
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The minimum mm per arc segment. Used to prevent unnecessarily small segments from being generated. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_MM_PER_ARC_SEGMENT;
- TCLAP::ValueArg<double> min_arc_segment_mm_arg("b", "min-arc-segment-mm", arg_description_stream.str(), false, DEFAULT_MIN_MM_PER_ARC_SEGMENT, "float");
-
- // -r --min-arc-segments
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The minimum number of segments within a circle of the same radius as the arc. Can be used to increase detail on small arcs. The smallest segment generated will be no larger than min_mm_per_arc_segment. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_ARC_SEGMENTS;
- TCLAP::ValueArg<int> min_arc_segments_arg("r", "min-arc-segments", arg_description_stream.str(), false, DEFAULT_MIN_ARC_SEGMENTS, "int");
-
- // min_circle_segments_arg
- // -a --min-circle-segments-arg
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The minimum number of segments within a circle of the same radius as the arc. Can be used to increase detail on small arcs. The smallest segment generated will be no larger than min_mm_per_arc_segment. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_MIN_ARC_SEGMENTS;
- TCLAP::ValueArg<int> min_circle_segments_arg("a", "min-circle-segments", arg_description_stream.str(), false, DEFAULT_MIN_CIRCLE_SEGMENTS, "int");
-
- // -c --n-arc-correction
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The number of segments that will be interpolated using a small angle approximation before true sin/cos corrections are applied. A value less than or equal to 1 will disable this feature. Default Value: " << DEFAULT_N_ARC_CORRECTIONS;
- TCLAP::ValueArg<int> n_arc_correction_arg("c", "n-arc-correction", arg_description_stream.str(), false, DEFAULT_N_ARC_CORRECTIONS, "int");
-
- // -s --arc-segments-per-second
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "The number of segments per second. This will produce a constant number of arcs, clamped between mm-per-arc-segment and min-mm-per-arc-segment. Can be used to prevent stuttering when printing very quickly. A value less than or equal to 0 will disable this feature. Default Value: " << DEFAULT_ARC_SEGMENTS_PER_SEC;
- TCLAP::ValueArg<double> arc_segments_per_sec_arg("s", "arc-segments-per-second", arg_description_stream.str(), false, DEFAULT_MIN_MM_PER_ARC_SEGMENT, "float");
-
- // -e --mm-max-arc-error
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "This currently is only used in Smoothieware. The maximum error for line segments that divide arcs. Set to 0 to disable. Default Value: " << DEFAULT_MM_MAX_ARC_ERROR;
- TCLAP::ValueArg<double> mm_max_arc_error_arg("e", "mm-max-arc-error", arg_description_stream.str(), false, DEFAULT_MM_MAX_ARC_ERROR, "float");
-
- // -l --log-level
- std::vector<std::string> log_levels_vector;
- log_levels_vector.push_back("NOSET");
- log_levels_vector.push_back("VERBOSE");
- log_levels_vector.push_back("DEBUG");
- log_levels_vector.push_back("INFO");
- log_levels_vector.push_back("WARNING");
- log_levels_vector.push_back("ERROR");
- log_levels_vector.push_back("CRITICAL");
- log_levels_vector.push_back("");
- TCLAP::ValuesConstraint<std::string> log_levels_constraint(log_levels_vector);
- arg_description_stream.clear();
- arg_description_stream.str("");
- arg_description_stream << "Sets console log level. Possible values: Default Value: " << log_level_string_default;
- TCLAP::ValueArg<std::string> log_level_arg("l", "log-level", arg_description_stream.str(), false, log_level_string_default, &log_levels_constraint);
-
- // Add all arguments
- cmd.add(source_arg);
- cmd.add(target_arg);
- cmd.add(firmware_type_arg);
- cmd.add(firmware_version_arg);
- cmd.add(g90_arg);
- cmd.add(mm_per_arc_segment_arg);
- cmd.add(min_mm_per_arc_segment_arg);
- cmd.add(min_arc_segments_arg);
- cmd.add(n_arc_correction_arg);
- cmd.add(arc_segments_per_sec_arg);
- cmd.add(log_level_arg);
- cmd.add(min_circle_segments_arg);
- cmd.add(min_arc_segment_mm_arg);
- cmd.add(max_arc_segment_mm_arg);
- cmd.add(print_firmware_defaults_arg);
-
- // First, we need to see if the user wants to print firmware defaults
- help_cmd.add(firmware_type_arg);
- help_cmd.add(firmware_version_arg);
- help_cmd.add(print_firmware_defaults_arg);
- help_cmd.setExceptionHandling(false);
+ try {
+
+
// parse the help requests
try {
help_cmd.parse(argc, argv);
if (print_firmware_defaults_arg.isSet())
{
+ help_cmd.ignoreUnmatched(false);
+ help_cmd.reset();
+ help_cmd.parse(argc, argv);
std::string firmware_type_string = firmware_type_arg.getValue();
std::string firmware_version_string = firmware_version_arg.getValue();
print_firmware_defaults(firmware_type_string, firmware_version_string, firmware_version_arg.getName());
return 0;
}
}
+
catch (TCLAP::ArgException& exc)
{
- if (exc.argId() == "Argument: " + firmware_type_arg.toString()
- || exc.argId() == "Argument: " + firmware_version_arg.toString())
+ std::string argument_prefix = "Argument: ";
+ std::string firmware_type_arg_id = argument_prefix + arg_name_firmare_type;
+ std::string firmware_type_arg_id_short = argument_prefix + COMMAND_LINE_ARGUMENT_PREFIX_SHORT + arg_short_name_firmare_type + " (" + COMMAND_LINE_ARGUMENT_PREFIX + arg_name_firmare_type + ")";
+ std::string firmware_version_arg_id = argument_prefix + arg_name_firmare_version;
+ std::string firmware_version_arg_id_short = argument_prefix + COMMAND_LINE_ARGUMENT_PREFIX_SHORT + arg_short_name_firmare_version + " (" + COMMAND_LINE_ARGUMENT_PREFIX + arg_name_firmare_version + ")";;
+ std::string exception_arg_id = exc.argId();
+
+ // If this is an exception related to the firmware-type or firmware-version args, print an error message for the
+ // thrown exception. Else, an invalid or extra argument must have been added, so add additional detail.
+ TCLAP::ArgException detailed_exception;
+ if (exception_arg_id == firmware_type_arg_id
+ || exception_arg_id == firmware_type_arg_id_short
+ || exception_arg_id == firmware_version_arg_id
+ || exception_arg_id == firmware_version_arg_id_short
+ )
{
- // This will raise an exit exception
- cmd.getOutput()->failure(cmd, exc);
+ detailed_exception = exc;
}
+ else {
+
+ std::string print_defaults_error_text = exc.error() + ". When the --" + arg_name_print_firmware_defaults + " (-" + arg_short_name_print_firmware_defaults + ") argument is supplied, only the --" + arg_name_firmare_type + " (-" + arg_short_name_firmare_type + ") and --" + arg_name_firmare_version + " (-" + arg_short_name_firmare_version + ") parameters are supported.";
+ TCLAP::ArgException print_defaults_parse_exception(print_defaults_error_text, exc.argId(), "Print Firmware Defaults Exception");
+ detailed_exception = print_defaults_parse_exception;
+ // This will raise an exit exception
+
+ }
+ cmd.getOutput()->failure(cmd, detailed_exception);
+ return 1;
}
// End print firmware defaults
// Parse the argv array after resetting any used parameters.
- firmware_type_arg.reset();
- firmware_version_arg.reset();
+ cmd.reset();
cmd.parse(argc, argv);
// Ok! Now let's see what firmware and version were selected, then we can start adding parameters
// First, Set the firmware type
std::string firmware_type_string = firmware_type_arg.getValue();
- firmware_types firmware_type = static_cast<firmware_types>(get_firmware_type_from_string(firmware_type_string));
+ args.firmware_args.firmware_type = static_cast<firmware_types>(get_firmware_type_from_string(firmware_type_string));
// Now set the version
// Set the firmware version, and check to make sure that the version supplied is supported.
std::string firmware_version_string = firmware_version_arg.getValue();
- is_firmware_version_valid_for_type(firmware_type_string, firmware_version_string, firmware_version_arg.getName());
+ check_firmware_version_for_type(firmware_type_string, firmware_version_string, firmware_version_arg.getName());
args.firmware_args.version = firmware_version_string;
// now that we have the firmware type and version, we can extract the default arguments and override any settings that are supplied
@@ -318,67 +380,73 @@ int run_arc_straightener(int argc, char* argv[])
args.target_path = args.source_path;
}
+ // ensure the source file exists
+ if (!utilities::does_file_exist(args.source_path))
+ {
+ throw TCLAP::ArgException("The source file does not exist at the specified path.", source_arg.getName());
+ }
+ std::string available_arguments_string = args.firmware_args.get_available_arguments_string(COMMAND_LINE_ARGUMENT_SEPARATOR, COMMAND_LINE_ARGUMENT_PREFIX, COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
// If the arguments are set, apply them. If not, don't.
if (mm_per_arc_segment_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("mm_per_arc_segment"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", mm_per_arc_segment_arg.getName(), "The argument does not apply to the " + firmware_type_string +" " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, mm_per_arc_segment_arg.toString());
}
args.firmware_args.mm_per_arc_segment = mm_per_arc_segment_arg.getValue();
}
if (min_mm_per_arc_segment_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("min_mm_per_arc_segment"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", min_mm_per_arc_segment_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, min_mm_per_arc_segment_arg.toString());
}
args.firmware_args.min_mm_per_arc_segment = min_mm_per_arc_segment_arg.getValue();
}
if (min_arc_segments_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("min_arc_segments"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", min_arc_segments_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, min_arc_segments_arg.toString());
}
args.firmware_args.min_arc_segments = min_arc_segments_arg.getValue();
}
if (arc_segments_per_sec_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("arc_segments_per_sec"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", arc_segments_per_sec_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, arc_segments_per_sec_arg.toString() );
}
args.firmware_args.arc_segments_per_sec = arc_segments_per_sec_arg.getValue();
}
if (g90_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("g90_g91_influences_extruder"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", g90_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, g90_arg.toString());
}
args.firmware_args.g90_g91_influences_extruder = g90_arg.getValue() == "TRUE";
}
if (n_arc_correction_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("n_arc_correction"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_N_ARC_CORRECTION))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", n_arc_correction_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, n_arc_correction_arg.toString());
}
args.firmware_args.n_arc_correction = n_arc_correction_arg.getValue();
}
if (mm_max_arc_error_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("mm_max_arc_error"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", mm_max_arc_error_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, mm_max_arc_error_arg.toString());
}
args.firmware_args.mm_max_arc_error = mm_max_arc_error_arg.getValue();
}
@@ -387,32 +455,43 @@ int run_arc_straightener(int argc, char* argv[])
if (min_circle_segments_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("min_circle_segments"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", min_circle_segments_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, min_circle_segments_arg.toString());
}
- args.firmware_args.set_min_circle_segments(min_circle_segments_arg.getValue());
+ args.firmware_args.min_circle_segments = min_circle_segments_arg.getValue();
}
// min_arc_segment_mm
if (min_arc_segment_mm_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("min_arc_segment_mm"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", min_arc_segment_mm_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, min_arc_segment_mm_arg.toString());
}
- args.firmware_args.set_min_arc_segment_mm(min_arc_segment_mm_arg.getValue());
+ args.firmware_args.min_arc_segment_mm = min_arc_segment_mm_arg.getValue();
}
// max_arc_segment_mm
if (max_arc_segment_mm_arg.isSet())
{
// See if this argument is supported
- if (!args.firmware_args.is_argument_used("max_arc_segment_mm"))
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM))
{
- throw new TCLAP::ArgException("Invalid Argument For Firmware", max_arc_segment_mm_arg.getName(), "The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + get_available_arguments_string(args.firmware_args.get_available_arguments()));
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, max_arc_segment_mm_arg.toString());
}
- args.firmware_args.set_max_arc_segment_mm(max_arc_segment_mm_arg.getValue());
+ args.firmware_args.max_arc_segment_mm = max_arc_segment_mm_arg.getValue();
+ }
+ //arc_segments_per_r
+ if (arc_segments_per_r_arg.isSet())
+ {
+ // See if this argument is supported
+ if (!args.firmware_args.is_argument_used(FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R))
+ {
+ throw TCLAP::ArgException("The argument does not apply to the " + firmware_type_string + " " + firmware_version_arg.getValue() + " firmware. Only the following parameters are supported: " + available_arguments_string, arc_segments_per_r_arg.toString());
+ }
+ args.firmware_args.arc_segments_per_r = arc_segments_per_r_arg.getValue();
}
+
log_level_string = log_level_arg.getValue();
log_level_value = -1;
@@ -427,16 +506,21 @@ int run_arc_straightener(int argc, char* argv[])
if (log_level_value == -1)
{
// TODO: Does this work?
- throw new TCLAP::ArgException("Unknown log level");
+ throw TCLAP::ArgException("Unknown log level", log_level_arg.toString());
}
}
// catch argument exceptions
catch (TCLAP::ArgException& e)
{
- std::cerr << "error: " << e.error() << " for arg " << e.argId() << std::endl;
+ // This will raise an exit exception
+ cmd.getOutput()->failure(cmd, e);
return 1;
}
+ catch (TCLAP::ExitException exc)
+ {
+ exit(exc.getExitStatus());
+ }
// Ensure the log level name is valid
@@ -489,7 +573,8 @@ int run_arc_straightener(int argc, char* argv[])
}
arc_interpolation interpolator(args);
- log_messages << interpolator.get_firmware_argument_description();
+
+ log_messages << interpolator.get_firmware_arguments_description(COMMAND_LINE_ARGUMENT_SEPARATOR, COMMAND_LINE_ARGUMENT_PREFIX, COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
p_logger->log(0, log_levels::INFO, log_messages.str());
p_logger->log(0, log_levels::INFO, "Running interpolation...");
@@ -523,22 +608,6 @@ int run_arc_straightener(int argc, char* argv[])
}
-
-std::string get_available_arguments_string(std::vector<std::string> firmware_arguments)
-{
- std::string available_argument_string = "";
-
- for (std::vector<std::string>::iterator it = firmware_arguments.begin(); it != firmware_arguments.end(); it++)
- {
- if (available_argument_string.size() > 0)
- {
- available_argument_string += ", ";
- }
- available_argument_string += "--" +utilities::replace(*it, "_", "-");
- }
- return available_argument_string;
-}
-
int get_firmware_type_from_string(std::string firmware_type)
{
for (int i = 0; i < NUM_FIRMWARE_TYPES; i++)
@@ -552,7 +621,7 @@ int get_firmware_type_from_string(std::string firmware_type)
return static_cast<firmware_types>(DEFAULT_FIRMWARE_TYPE);
}
-bool is_firmware_version_valid_for_type(std::string firmware_type_string, std::string firmware_version, std::string firmware_version_arg_name)
+void check_firmware_version_for_type(std::string firmware_type_string, std::string firmware_version, std::string firmware_version_arg_name)
{
firmware_types firmware_type = static_cast<firmware_types>(get_firmware_type_from_string(firmware_type_string));
// Create an instance of all supported firmware types using the default args
@@ -568,33 +637,36 @@ bool is_firmware_version_valid_for_type(std::string firmware_type_string, std::s
case firmware_types::MARLIN_1:
if (!marlin_1_firmware.is_valid_version(firmware_version))
{
- throw new TCLAP::ArgException("Unknown Version Exception", firmware_version_arg_name, "'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type.");
+
+ throw TCLAP::ArgException("'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type. The available versions are: " + marlin_1_firmware.get_version_names_string(), firmware_version_arg_name);
}
break;
case firmware_types::MARLIN_2:
if (!marlin_2_firmware.is_valid_version(firmware_version))
{
- throw new TCLAP::ArgException("Unknown Version Exception", firmware_version_arg_name, "'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type.");
+ throw TCLAP::ArgException("'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type. The available versions are: " + marlin_2_firmware.get_version_names_string(), firmware_version_arg_name );
}
break;
case firmware_types::REPETIER:
if (!repetier_firmware.is_valid_version(firmware_version))
{
- throw new TCLAP::ArgException("Unknown Version Exception", firmware_version_arg_name, "'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type.");
+ throw TCLAP::ArgException("'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type. The available versions are: " + repetier_firmware.get_version_names_string(), firmware_version_arg_name);
}
break;
case firmware_types::PRUSA:
if (!prusa_firmware.is_valid_version(firmware_version))
{
- throw new TCLAP::ArgException("Unknown Version Exception", firmware_version_arg_name, "'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type.");
+ throw TCLAP::ArgException("'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type. The available versions are: " + prusa_firmware.get_version_names_string(), firmware_version_arg_name );
}
break;
case firmware_types::SMOOTHIEWARE:
if (!smoothieware_firmware.is_valid_version(firmware_version))
{
- throw new TCLAP::ArgException("Unknown Version Exception", firmware_version_arg_name, "'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type.");
+ throw TCLAP::ArgException("'" + firmware_version + "' is not a valid version for " + firmware_type_string + " firmware type. The available versions are: " + smoothieware_firmware.get_version_names_string(), firmware_version_arg_name);
}
break;
+ default:
+ throw TCLAP::ArgException("The supplied firmmware type " + firmware_type_string + " is unknown. The available versions are: " + smoothieware_firmware.get_version_names_string(), firmware_version_arg_name);
}
}
@@ -610,7 +682,7 @@ void print_firmware_defaults(std::string firmware_type_string, std::string firmw
firmware_types firmware_type = static_cast<firmware_types>(get_firmware_type_from_string(firmware_type_string));
args.firmware_args.firmware_type = firmware_type;
- is_firmware_version_valid_for_type(firmware_type_string, firmware_version_string, firmware_version_arg_name);
+ check_firmware_version_for_type(firmware_type_string, firmware_version_string, firmware_version_arg_name);
args.firmware_args.version = firmware_version_string;
// now that we have the firmware type and version, we can extract the default arguments and override any settings that are supplied
@@ -639,6 +711,6 @@ void print_firmware_defaults(std::string firmware_type_string, std::string firmw
}
std::cout << "Showing arguments and defaults for " << firmware_type_string << " (" << firmware_version_string << ")\n";
- std::cout << "Available argument for firmware: " << get_available_arguments_string(args.firmware_args.get_available_arguments()) << "\n";
- std::cout << "Default " << args.firmware_args.get_argument_description();
+ std::cout << "Available argument for firmware: " << args.firmware_args.get_available_arguments_string(COMMAND_LINE_ARGUMENT_SEPARATOR, COMMAND_LINE_ARGUMENT_PREFIX, COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE) << "\n";
+ std::cout << "Default " << args.firmware_args.get_arguments_description(COMMAND_LINE_ARGUMENT_SEPARATOR, COMMAND_LINE_ARGUMENT_PREFIX, COMMAND_LINE_ARGUMENT_REPLACEMENT_STRING, COMMAND_LINE_ARGUMENT_REPLACEMENT_VALUE);
} \ No newline at end of file
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.h b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.h
index 0b2ca1a..f128e33 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.h
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.h
@@ -35,8 +35,7 @@
#include <string>
#include <vector>
int run_arc_straightener(int argc, char* argv[]);
-static std::string get_available_arguments_string(std::vector<std::string> firmware_arguments);
-static bool is_firmware_version_valid_for_type(std::string firmware_type_string, std::string firmware_version, std::string firmware_version_arg_name);
+static void check_firmware_version_for_type(std::string firmware_type_string, std::string firmware_version, std::string firmware_version_arg_name);
static int get_firmware_type_from_string(std::string firmware_type);
static void print_firmware_defaults(std::string firmware_type_string, std::string firmware_version_string, std::string firmware_version_arg_name);
diff --git a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj
index 334d94e..b6dc2d2 100644
--- a/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj
+++ b/ArcWelderInverseProcessor/ArcWelderInverseProcessor.vcxproj
@@ -106,10 +106,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\GcodeProcessorLib\;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\TCLAP\</IncludePath>
+ <TargetName>ArcStraightener</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Remote_Pi|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)\GcodeProcessorLib\;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\TCLAP\</IncludePath>
+ <TargetName>ArcStraightener</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
@@ -119,6 +121,7 @@
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(SolutionDir)\GcodeProcessorLib\;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\TCLAP\</IncludePath>
<ExecutablePath>$(VC_ExecutablePath_x64);$(CommonExecutablePath)</ExecutablePath>
+ <TargetName>ArcStraightener</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
diff --git a/ArcWelderInverseProcessor/arc_interpolation.cpp b/ArcWelderInverseProcessor/arc_interpolation.cpp
index c5cde1a..feb045b 100644
--- a/ArcWelderInverseProcessor/arc_interpolation.cpp
+++ b/ArcWelderInverseProcessor/arc_interpolation.cpp
@@ -152,6 +152,8 @@ void arc_interpolation::process()
{
if (output_file_.is_open())
{
+ // Add the gcode file header
+ output_file_ << p_current_firmware_->get_gcode_header_comment()<<"\n";
parsed_command cmd;
// Communicate every second
while (std::getline(gcode_file, line))
@@ -273,7 +275,7 @@ void arc_interpolation::process()
std::cout << stream.str();
}
-std::string arc_interpolation::get_firmware_argument_description() const
+std::string arc_interpolation::get_firmware_arguments_description(std::string separator, std::string argument_prefix, std::string replacement_string, std::string replacement_value) const
{
- return p_current_firmware_->get_argument_description();
+ return p_current_firmware_->get_arguments_description(separator, argument_prefix, replacement_string, replacement_value);
} \ No newline at end of file
diff --git a/ArcWelderInverseProcessor/arc_interpolation.h b/ArcWelderInverseProcessor/arc_interpolation.h
index d3eb306..e1eed16 100644
--- a/ArcWelderInverseProcessor/arc_interpolation.h
+++ b/ArcWelderInverseProcessor/arc_interpolation.h
@@ -74,7 +74,7 @@ class arc_interpolation
/// Outputs a string description of the firmware arguments.
/// </summary>
/// <returns></returns>
- std::string get_firmware_argument_description() const;
+ std::string get_firmware_arguments_description(std::string separator = "", std::string argument_prefix = "", std::string replacement_string = "", std::string replacement_value = "") const;
private:
arc_interpolation_args args_;
gcode_position_args get_args_(bool g90_g91_influences_extruder, int buffer_size);
diff --git a/ArcWelderInverseProcessor/firmware.cpp b/ArcWelderInverseProcessor/firmware.cpp
index 5025c2f..bab3968 100644
--- a/ArcWelderInverseProcessor/firmware.cpp
+++ b/ArcWelderInverseProcessor/firmware.cpp
@@ -105,7 +105,7 @@ std::string firmware::g1_command(firmware_position& target)
if (has_e)
{
gcode += is_first_parameter ? "E" : " E";
- gcode += utilities::dtos(state_.is_extruder_relative ? target.e - position_.e : target.e, 3);
+ gcode += utilities::dtos(state_.is_extruder_relative ? target.e - position_.e : target.e, 5);
is_first_parameter = false;
}
@@ -139,14 +139,41 @@ std::vector<std::string> firmware::get_version_names()
return version_names_;
}
+std::string firmware::get_version_names_string()
+{
+ std::vector<std::string> version_names_with_release_info;
+ bool foundLatestRelease = false;
+ for (int index = 0; index < version_names_.size(); index++)
+ {
+ std::string version_name = version_names_[index];
+
+ if (foundLatestRelease)
+ {
+ version_name.append(" (").append("NON_RELEASE_VERSION").append(")");
+ }
+ else if (version_name == args_.latest_release_version)
+ {
+ version_name.append(" (").append(LATEST_FIRMWARE_VERSION_NAME).append(")");
+ foundLatestRelease = true;
+ }
+ version_names_with_release_info.push_back(version_name);
+ }
+ return utilities::join(version_names_with_release_info, ",");
+}
+
bool firmware::get_g90_g91_influences_extruder()
{
return args_.g90_g91_influences_extruder;
}
-std::string firmware::get_argument_description() {
+std::string firmware::get_arguments_description(std::string separator, std::string argument_prefix, std::string replacement_string, std::string replacement_value) {
- return args_.get_argument_description();
+ return args_.get_arguments_description(separator, argument_prefix, replacement_string, replacement_value);
+}
+
+std::string firmware::get_gcode_header_comment()
+{
+ return args_.get_gcode_header_comment();
}
void firmware::set_versions(std::vector<std::string> version_names, std::string latest_release_version_name)
diff --git a/ArcWelderInverseProcessor/firmware.h b/ArcWelderInverseProcessor/firmware.h
index d2f7f2d..3113539 100644
--- a/ArcWelderInverseProcessor/firmware.h
+++ b/ArcWelderInverseProcessor/firmware.h
@@ -37,25 +37,29 @@
#include <sstream>
#include <iomanip>
#include <algorithm>
+#include <utilities.h>
+#include "version.h"
#define DEFAULT_FIRMWARE_TYPE firmware_types::MARLIN_2
#define LATEST_FIRMWARE_VERSION_NAME "LATEST_RELEASE"
#define DEFAULT_FIRMWARE_VERSION_NAME LATEST_FIRMWARE_VERSION_NAME
// Arc interpretation settings:
-#define DEFAULT_MM_PER_ARC_SEGMENT 1.0 // REQUIRED - The enforced maximum length of an arc segment
-#define DEFAULT_ARC_SEGMENTS_PER_R 0;
+#define DEFAULT_MM_PER_ARC_SEGMENT 0 // REQUIRED - The enforced maximum length of an arc segment
+#define DEFAULT_ARC_SEGMENTS_PER_R 0; // 0 to disable
+#define DEFAULT_MAX_MM_PER_ARC_SEGMENT 0 // Required - The enforced maximum length of an arc segment
+#define DEFAULT_MIN_ARC_SEGMENT_MM 0; // 0 to disable
#define DEFAULT_MIN_MM_PER_ARC_SEGMENT 0 /* OPTIONAL - the enforced minimum length of an interpolated segment. Must be smaller than
MM_PER_ARC_SEGMENT. Only has an effect if MIN_ARC_SEGMENTS > 0 or ARC_SEGMENTS_PER_SEC > 0 */
- // If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum calculated segment length is used.
-#define DEFAULT_MIN_ARC_SEGMENTS 24 // OPTIONAL - The enforced minimum segments in a full circle of the same radius.
-#define DEFAULT_MIN_CIRCLE_SEGMENTS 72 // OPTIONAL - The enforced minimum segments in a full circle of the same radius.
+ // If both MIN_ARC_SEGMENTS and ARC_SEGMENTS_PER_SEC is defined, the minimum calculated segment length is used. Set to 0 to disable
+#define DEFAULT_MIN_ARC_SEGMENTS 0 // OPTIONAL - The enforced minimum segments in a full circle of the same radius. Set to 0 to disable.
+#define DEFAULT_MIN_CIRCLE_SEGMENTS 0 // OPTIONAL - The enforced minimum segments in a full circle of the same radius.
#define DEFAULT_ARC_SEGMENTS_PER_SEC 0 // OPTIONAL - Use feedrate to choose segment length.
-// approximation will not be used for the first segment. Subsequent segments will be corrected following DEFAULT_N_ARC_CORRECTION.
-#define DEFAULT_N_ARC_CORRECTIONS 24
+// approximation will not be used for the first segment. Subsequent segments will be corrected following DEFAULT_N_ARC_CORRECTION. Set to 0 to disable.
+#define DEFAULT_N_ARC_CORRECTIONS 0
// This setting is for the gcode position processor to help interpret G90/G91 behavior
#define DEFAULT_G90_G91_INFLUENCES_EXTRUDER false
// This currently is only used in Smoothieware. The maximum error for line segments that divide arcs. Set to 0 to disable.
-#define DEFAULT_MM_MAX_ARC_ERROR 0.01
+#define DEFAULT_MM_MAX_ARC_ERROR 0
struct firmware_state {
firmware_state() {
@@ -81,13 +85,29 @@ struct firmware_position {
double f;
};
+// parameter name defines
+#define FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT "mm_per_arc_segment"
+#define FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R "arc_segments_per_r"
+#define FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT "min_mm_per_arc_segment"
+#define FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS "min_arc_segments"
+#define FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC "arc_segments_per_sec"
+#define FIRMWARE_ARGUMENT_N_ARC_CORRECTION "n_arc_correction"
+#define FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER "g90_g91_influences_extruder"
+#define FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR "mm_max_arc_error"
+#define FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS "min_circle_segments"
+#define FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM "min_arc_segment_mm"
+#define FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM "max_arc_segment_mm"
+
struct firmware_arguments {
public:
-
+
firmware_arguments() {
mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT;
+ min_arc_segment_mm = DEFAULT_MIN_ARC_SEGMENT_MM;
+ max_arc_segment_mm = DEFAULT_MAX_MM_PER_ARC_SEGMENT;
arc_segments_per_r = DEFAULT_ARC_SEGMENTS_PER_R;
min_mm_per_arc_segment = DEFAULT_MIN_MM_PER_ARC_SEGMENT;
+ min_circle_segments = DEFAULT_MIN_CIRCLE_SEGMENTS;
min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS;
arc_segments_per_sec = DEFAULT_ARC_SEGMENTS_PER_SEC;
n_arc_correction = DEFAULT_N_ARC_CORRECTIONS;
@@ -99,17 +119,17 @@ public:
// add a list of all possible arguments, including aliases
all_arguments_.clear();
- all_arguments_.push_back("mm_per_arc_segment");
- all_arguments_.push_back("arc_segments_per_r");
- all_arguments_.push_back("min_mm_per_arc_segment");
- all_arguments_.push_back("min_arc_segments");
- all_arguments_.push_back("arc_segments_per_sec");
- all_arguments_.push_back("n_arc_correction");
- all_arguments_.push_back("g90_g91_influences_extruder");
- all_arguments_.push_back("mm_max_arc_error");
- all_arguments_.push_back("min_circle_segments");
- all_arguments_.push_back("min_arc_segment_mm");
- all_arguments_.push_back("max_arc_segment_mm");
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_N_ARC_CORRECTION);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM);
+ all_arguments_.push_back(FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM);
};
/// <summary>
@@ -125,9 +145,20 @@ public:
/// </summary>
double min_mm_per_arc_segment;
/// <summary>
+ /// The minimum mm per arc segment. If less than or equal to 0, this is disabled
+ /// </summary>
+ double min_arc_segment_mm;
+ /// <summary>
+ /// The maximum mm per arc segment.
+ /// </summary>
+ double max_arc_segment_mm;
+
+
+ /// <summary>
/// The number of arc segments that will be drawn per second based on the given feedrate.
/// If less than or equal to zero, this is disabled.
/// </summary>
+
double arc_segments_per_sec;
/// <summary>
/// This currently is only used in Smoothieware. The maximum error for line segments that divide arcs. Set to 0 to disable.
@@ -138,6 +169,12 @@ public:
/// If less than or equal to zero, this is disabled
/// </summary>
int min_arc_segments;
+
+ /// <summary>
+ /// The minimum number of arc segments in a full circle of the arc's radius.
+ /// If less than or equal to zero, this is disabled
+ /// </summary>
+ int min_circle_segments;
/// <summary>
/// // Number of interpolated segments before true sin and cos corrections will be applied.
/// If less than or equal to zero, true sin and cos will always be used.
@@ -160,36 +197,7 @@ public:
/// True if the current version is the latest release. For informational purposes only
/// </summary>
std::string latest_release_version;
- /// Aliases for variour parameters
- int get_min_circle_segments() const
- {
- return min_arc_segments;
- }
- void set_min_circle_segments(int segments)
- {
- min_arc_segments = segments;
- }
-
- double get_min_arc_segment_mm() const
- {
- return min_mm_per_arc_segment;
- }
-
- void set_min_arc_segment_mm(double mm)
- {
- min_mm_per_arc_segment = mm;
- }
-
- double get_max_arc_segment_mm() const
- {
- return mm_per_arc_segment;
- }
-
- void set_max_arc_segment_mm(double mm)
- {
- mm_per_arc_segment = mm;
- }
-
+
void set_used_arguments(std::vector<std::string> arguments)
{
used_arguments_ = arguments;
@@ -208,91 +216,180 @@ public:
return unused_arguments;
}
- std::string get_unused_arguments_string()
+ std::string get_unused_arguments_string(std::string separator = "", std::string argument_prefix = "", std::string replacement_string = "", std::string replacement_value = "")
{
+ return get_arguments_string_(get_unused_arguments(), separator, argument_prefix, replacement_string, replacement_value);
std::string unusaed_argument_string = "";
std::vector<std::string> unused_argumnts = get_unused_arguments();
for (std::vector<std::string>::iterator it = unused_argumnts.begin(); it != unused_argumnts.end(); it++)
{
if (unusaed_argument_string.size() > 0)
{
- unusaed_argument_string += ", ";
+ unusaed_argument_string += separator;
}
unusaed_argument_string += *it;
}
return unusaed_argument_string;
}
+ std::string get_available_arguments_string(std::string separator = "", std::string argument_prefix = "", std::string replacement_string = "", std::string replacement_value = "")
+ {
+ return get_arguments_string_(used_arguments_, separator, argument_prefix, replacement_string, replacement_value);
+ }
+
std::vector<std::string> get_available_arguments()
{
return used_arguments_;
}
+ std::string get_gcode_header_comment()
+ {
+ std::string comment_start = "; ";
+ std::stringstream stream;
+ stream << comment_start << "Postprocessed by [ArcStraightener](https://github.com/FormerLurker/ArcWelderLib)\n";
+ stream << comment_start << "Copyright(C) " << COPYRIGHT_DATE << " - " << AUTHOR << "\n";
+ stream << comment_start << "Version: " << GIT_TAGGED_VERSION << ", Branch: " << GIT_BRANCH << ", BuildDate: " << BUILD_DATE << "\n";
+
+ stream << comment_start << "firmware_type=" << firmware_type_names[firmware_type] << "\n";
+ stream << comment_start << "firmware_version=" << (version == LATEST_FIRMWARE_VERSION_NAME || version == latest_release_version ? latest_release_version + " (" + LATEST_FIRMWARE_VERSION_NAME + ")" : version) << "\n";
+
+ stream << std::fixed << std::setprecision(0);
+ std::string argument_string;
+
+ // Bool values
+ argument_string = FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << (g90_g91_influences_extruder ? "True" : "False") << "\n";
+ }
+
+ // Int values
+ argument_string = FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << min_arc_segments << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << min_circle_segments << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_N_ARC_CORRECTION;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << n_arc_correction << "\n";
+ }
+
+ stream << std::fixed << std::setprecision(2);
+ // Double values
+ argument_string = FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << mm_per_arc_segment << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << arc_segments_per_r << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << arc_segments_per_sec << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << mm_max_arc_error << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << min_mm_per_arc_segment << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << min_arc_segment_mm << "\n";
+ }
+ argument_string = FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM;
+ if (is_argument_used(argument_string))
+ {
+ stream << comment_start << argument_string << "=" << max_arc_segment_mm << "\n";
+ }
+
+ return stream.str();
+ }
- std::string get_argument_description() {
+ std::string get_arguments_description(std::string separator="", std::string argument_prefix = "", std::string replacement_string = "", std::string replacement_value = "") {
std::stringstream stream;
stream << "Firmware Arguments:\n";
stream << "\tFirmware Type : " << firmware_type_names[firmware_type] << "\n";
stream << "\tFirmware Version : " << (version == LATEST_FIRMWARE_VERSION_NAME || version == latest_release_version ? latest_release_version + " (" + LATEST_FIRMWARE_VERSION_NAME + ")" : version) <<"\n";
stream << std::fixed << std::setprecision(0);
+ std::string argument_string;
+
// Bool values
- if (is_argument_used("g90_g91_influences_extruder"))
+ argument_string = FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER;
+ if (is_argument_used(argument_string))
{
- stream << "\tg90_g91_influences_extruder : " << (g90_g91_influences_extruder ? "True" : "False") << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << (g90_g91_influences_extruder ? "True" : "False") << "\n";
}
// Int values
- if (is_argument_used("min_arc_segments"))
+ argument_string = FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS;
+ if (is_argument_used(argument_string))
{
- stream << "\tmin_arc_segments : " << min_arc_segments << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << min_arc_segments << "\n";
}
- if (is_argument_used("min_circle_segments"))
+ argument_string = FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS;
+ if (is_argument_used(argument_string))
{
- stream << "\tmin_circle_segments : " << get_min_circle_segments() << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << min_circle_segments << "\n";
}
- if (is_argument_used("n_arc_correction"))
+ argument_string = FIRMWARE_ARGUMENT_N_ARC_CORRECTION;
+ if (is_argument_used(argument_string))
{
- stream << "\tn_arc_correction : " << n_arc_correction << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << n_arc_correction << "\n";
}
stream << std::fixed << std::setprecision(2);
// Double values
- //
- if (is_argument_used("mm_per_arc_segment"))
+ argument_string = FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT;
+ if (is_argument_used(argument_string))
{
- stream << "\tmm_per_arc_segment : " << mm_per_arc_segment << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << mm_per_arc_segment << "\n";
}
- //
- if (is_argument_used("arc_segments_per_r"))
+ argument_string = FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R;
+ if (is_argument_used(argument_string))
{
- stream << "\tarc_segments_per_r : " << arc_segments_per_r << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << arc_segments_per_r << "\n";
}
- //
- if (is_argument_used("min_mm_per_arc_segment"))
+ argument_string = FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC;
+ if (is_argument_used(argument_string))
{
- stream << "\tmin_mm_per_arc_segment : " << min_mm_per_arc_segment << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << arc_segments_per_sec << "\n";
}
- //
- if (is_argument_used("arc_segments_per_sec"))
+ argument_string = FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR;
+ if (is_argument_used(argument_string))
{
- stream << "\tarc_segments_per_sec : " << arc_segments_per_sec << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << mm_max_arc_error << "\n";
}
- //
- if (is_argument_used("mm_max_arc_error"))
+ argument_string = FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT;
+ if (is_argument_used(argument_string))
{
- stream << "\tmm_max_arc_error : " << mm_max_arc_error << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << min_mm_per_arc_segment << "\n";
}
- //
- if (is_argument_used("min_arc_segment_mm"))
+ argument_string = FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM;
+ if (is_argument_used(argument_string))
{
- stream << "\tmin_arc_segment_mm : " << get_min_arc_segment_mm() << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << min_arc_segment_mm << "\n";
}
- //
- if (is_argument_used("max_arc_segment_mm"))
+ argument_string = FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM;
+ if (is_argument_used(argument_string))
{
- stream << "\tmax_arc_segment_mm : " << get_max_arc_segment_mm() << "\n";
+ stream << "\t" << get_argument_string(argument_string, "", replacement_string, replacement_value) << " : " << max_arc_segment_mm << "\n";
}
-
- std::string unused_argument_string = get_unused_arguments_string();
+ std::string unused_argument_string = get_unused_arguments_string(separator, argument_prefix, replacement_string, replacement_value);
if (unused_argument_string.size() > 0)
{
stream << "The following parameters do not apply to this firmware version: " << unused_argument_string << "\n";
@@ -304,9 +401,29 @@ public:
{
return (std::find(used_arguments_.begin(), used_arguments_.end(), argument_name) != used_arguments_.end());
}
+ static std::string get_argument_string(std::string argument_name, std::string argument_prefix, std::string replacement_string = "", std::string replacement_value = "")
+ {
+ return argument_prefix + utilities::replace(argument_name, replacement_string, replacement_value);
+ }
+
private:
std::vector<std::string> all_arguments_;
std::vector<std::string> used_arguments_;
+ std::string get_arguments_string_(std::vector<std::string> string_values, std::string separator, std::string argument_prefix, std::string replacement_string = "", std::string replacement_value = "")
+ {
+ std::string available_argument_string = "";
+
+ for (std::vector<std::string>::iterator it = string_values.begin(); it != string_values.end(); it++)
+ {
+ if (available_argument_string.size() > 0)
+ {
+ available_argument_string += separator;
+ }
+ available_argument_string += get_argument_string(*it, argument_prefix , replacement_string, replacement_value);
+ }
+ return available_argument_string;
+ }
+
};
@@ -364,6 +481,12 @@ public:
std::vector<std::string> get_version_names();
/// <summary>
+ /// Returns all valid versions for this firmware in one comma separated string.
+ /// </summary>
+ /// <returns>Vector of strings, one for each supported version</returns>
+ std::string get_version_names_string();
+
+ /// <summary>
/// Returns the current g90_g91_influences_extruder value for the firmware.
/// </summary>
/// <returns></returns>
@@ -379,7 +502,13 @@ public:
/// Outputs a string description of the firmware arguments.
/// </summary>
/// <returns></returns>
- std::string get_argument_description();
+ std::string get_arguments_description(std::string separator , std::string argument_prefix = "", std::string replacement_string = "", std::string replacement_value = "");
+
+ /// <summary>
+ /// Returns a gcode comment containing the current settings
+ /// </summary>
+ /// <returns></returns>
+ std::string get_gcode_header_comment();
/// <summary>
/// Sets all available versions names and the version index based on args_.version
@@ -387,8 +516,7 @@ public:
/// <returns></returns>
void set_versions(std::vector<std::string> version_names, std::string latest_release_version_name);
- virtual firmware_arguments get_default_arguments_for_current_version()const;
-
+ virtual firmware_arguments get_default_arguments_for_current_version() const;
void set_arguments(firmware_arguments args);
diff --git a/ArcWelderInverseProcessor/marlin_1.cpp b/ArcWelderInverseProcessor/marlin_1.cpp
index b807abd..3bdf86f 100644
--- a/ArcWelderInverseProcessor/marlin_1.cpp
+++ b/ArcWelderInverseProcessor/marlin_1.cpp
@@ -58,7 +58,7 @@ void marlin_1::apply_arguments()
{
default:*/
plan_arc_ = &marlin_1::plan_arc_1_1_9_1;
- used_arguments = { "mm_per_arc_segment", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
//break;
//}
@@ -78,14 +78,7 @@ firmware_arguments marlin_1::get_default_arguments_for_current_version() const
//default:
// Active Settings
default_args.mm_per_arc_segment = 1.0f;
- default_args.min_arc_segments = 24;
default_args.n_arc_correction = 25;
- // Inactive Settings
- default_args.arc_segments_per_r = 0;
- default_args.min_mm_per_arc_segment = 0;
- default_args.arc_segments_per_sec = 0;
- // Settings that do not apply
- default_args.mm_max_arc_error = 0;
//break;
//}
diff --git a/ArcWelderInverseProcessor/marlin_2.cpp b/ArcWelderInverseProcessor/marlin_2.cpp
index fe66486..e70c043 100644
--- a/ArcWelderInverseProcessor/marlin_2.cpp
+++ b/ArcWelderInverseProcessor/marlin_2.cpp
@@ -55,11 +55,11 @@ void marlin_2::apply_arguments()
switch (marlin_2_version_)
{
case marlin_2::marlin_2_firmware_versions::V2_0_9_2:
- used_arguments = {"min_arc_segment_mm", "max_arc_segment_mm", "min_circle_segments", "arc_segments_per_sec", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MIN_ARC_SEGMENT_MM, FIRMWARE_ARGUMENT_MAX_ARC_SEGMENT_MM, FIRMWARE_ARGUMENT_MIN_CIRCLE_SEGMENTS, FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
plan_arc_ = &marlin_2::plan_arc_2_0_9_2;
break;
default:
- used_arguments = { "mm_per_arc_segment", "arc_segments_per_r", "min_arc_segments", "arc_segments_per_sec", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_ARC_SEGMENT_PER_R, FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS, FIRMWARE_ARGUMENT_ARC_SEGMENTS_PER_SEC, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
plan_arc_ = &marlin_2::plan_arc_2_0_9_1;
break;
}
@@ -78,15 +78,13 @@ firmware_arguments marlin_2::get_default_arguments_for_current_version() const
{
case marlin_2::marlin_2_firmware_versions::V2_0_9_2:
// Active Settings
- default_args.set_min_arc_segment_mm(0.1f);
- default_args.set_max_arc_segment_mm(1.0f);
- default_args.set_min_circle_segments(72);
+ default_args.min_arc_segment_mm = 0.1f;
+ default_args.max_arc_segment_mm = 1.0f;
+ default_args.min_circle_segments = 72;
default_args.n_arc_correction = 25;
// Inactive Settings
default_args.arc_segments_per_r = 0;
default_args.arc_segments_per_sec = 0;
- // Settings that do not apply
- default_args.mm_max_arc_error = 0;
break;
default:
// Active Settings
@@ -95,10 +93,7 @@ firmware_arguments marlin_2::get_default_arguments_for_current_version() const
default_args.n_arc_correction = 25;
// Inactive Settings
default_args.arc_segments_per_r = 0;
- default_args.min_mm_per_arc_segment = 0;
default_args.arc_segments_per_sec = 0;
- // Settings that do not apply
- default_args.mm_max_arc_error = 0;
break;
}
return default_args;
@@ -340,7 +335,7 @@ void marlin_2::plan_arc_2_0_9_1(
/// <summary>
-/// This function was adapted from the 2.0.9.1 release of Marlin firmware, which can be found at the following link:
+/// This function was adapted from the 2.0.9.2 release of Marlin firmware, which can be found at the following link:
/// https://github.com/MarlinFirmware/Marlin/blob/b878127ea04cc72334eb35ce0dca39ccf7d73a68/Marlin/src/gcode/motion/G2_G3.cpp
/// Copyright Notice found on that page:
///
@@ -374,7 +369,7 @@ void marlin_2::plan_arc_2_0_9_2(
const uint8_t circles // Take the scenic route
)
{
- int min_circle_segments = args_.get_min_circle_segments() > 0 ? args_.get_min_circle_segments() : 1;
+ int min_circle_segments = args_.min_circle_segments > 0 ? args_.min_circle_segments : 1;
uint8_t p_axis = X_AXIS, q_axis = Y_AXIS, l_axis = Z_AXIS;
// Radius vector from center to current location
@@ -436,16 +431,16 @@ void marlin_2::plan_arc_2_0_9_2(
// Get the nominal segment length based on settings
float nominal_segment_mm;
if (args_.arc_segments_per_sec > 0) {
- nominal_segment_mm = utilities::constrainf(scaled_fr_mm_s * utilities::reciprocalf((float)args_.arc_segments_per_sec), (float)args_.get_min_arc_segment_mm(), (float)args_.get_max_arc_segment_mm());
+ nominal_segment_mm = utilities::constrainf(scaled_fr_mm_s * utilities::reciprocalf((float)args_.arc_segments_per_sec), (float)args_.min_arc_segment_mm, (float)args_.max_arc_segment_mm);
}
else {
- nominal_segment_mm = (float)args_.get_max_arc_segment_mm();
+ nominal_segment_mm = (float)args_.max_arc_segment_mm;
}
// Number of whole segments based on the nominal segment length
const float nominal_segments = utilities::maxf(utilities::floorf(flat_mm / nominal_segment_mm), min_segments);
// A new segment length based on the required minimum
- const float segment_mm = utilities::constrainf(flat_mm / nominal_segments, (float)args_.get_min_arc_segment_mm(), (float)args_.get_max_arc_segment_mm());
+ const float segment_mm = utilities::constrainf(flat_mm / nominal_segments, (float)args_.min_arc_segment_mm, (float)args_.max_arc_segment_mm);
// The number of whole segments in the arc, ignoring the remainder
uint16_t segments = (uint16_t)utilities::floorf(flat_mm / segment_mm);
diff --git a/ArcWelderInverseProcessor/prusa.cpp b/ArcWelderInverseProcessor/prusa.cpp
index b1d5ac3..085977e 100644
--- a/ArcWelderInverseProcessor/prusa.cpp
+++ b/ArcWelderInverseProcessor/prusa.cpp
@@ -52,20 +52,14 @@ void prusa::apply_arguments()
{
case prusa::prusa_firmware_versions::V3_11_0:
mc_arc_ = &prusa::mc_arc_3_11_0;
- used_arguments = { "mm_per_arc_segment", "min_arc_segments", "min_mm_per_arc_segment", "mm_per_arc_segment", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_MIN_ARC_SEGMENTS, FIRMWARE_ARGUMENT_MIN_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
break;
default:
mc_arc_ = &prusa::mc_arc_3_10_0;
- used_arguments = { "mm_per_arc_segment", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
break;
}
args_.set_used_arguments(used_arguments);
- cs.arc_segments_per_sec = args_.arc_segments_per_sec;
- cs.min_arc_segments = args_.min_arc_segments;
- cs.min_mm_per_arc_segment = (float)args_.min_mm_per_arc_segment;
- cs.mm_per_arc_segment = (float)args_.mm_per_arc_segment;
- cs.n_arc_correction = args_.n_arc_correction;
-
}
@@ -196,7 +190,7 @@ void prusa::mc_arc_3_10_0(float* position, float* target, float* offset, float f
float millimeters_of_travel = (float)utilities::hypot((double)angular_travel * radius, utilities::absf(linear_travel));
if (millimeters_of_travel < 0.001) { return; }
- uint16_t segments = (uint16_t)utilities::floorf(millimeters_of_travel / cs.mm_per_arc_segment);
+ uint16_t segments = (uint16_t)utilities::floorf(millimeters_of_travel / static_cast<float>(args_.mm_per_arc_segment));
if (segments == 0) segments = 1;
/*
@@ -252,7 +246,7 @@ void prusa::mc_arc_3_10_0(float* position, float* target, float* offset, float f
for (i = 1; i < segments; i++) { // Increment (segments-1)
- if (count < cs.n_arc_correction) {
+ if (count < args_.n_arc_correction) {
// Apply vector rotation matrix
r_axisi = r_axis0 * sin_T + r_axis1 * cos_T;
r_axis0 = r_axis0 * cos_T - r_axis1 * sin_T;
@@ -327,39 +321,39 @@ void prusa::mc_arc_3_11_0(float* position, float* target, float* offset, float f
float rt_x = target[X_AXIS] - center_axis_x;
float rt_y = target[Y_AXIS] - center_axis_y;
// 20200419 - Add a variable that will be used to hold the arc segment length
- float mm_per_arc_segment = cs.mm_per_arc_segment;
+ float mm_per_arc_segment = static_cast<float>(args_.mm_per_arc_segment);
// 20210109 - Add a variable to hold the n_arc_correction value
- uint8_t n_arc_correction = cs.n_arc_correction;
+ uint8_t n_arc_correction = args_.n_arc_correction;
// CCW angle between position and target from circle center. Only one atan2() trig computation required.
float angular_travel_total = (float)utilities::atan2((double)r_axis_x * rt_y - (double)r_axis_y * rt_x, (double)r_axis_x * rt_x + (double)r_axis_y * rt_y);
if (angular_travel_total < 0) { angular_travel_total += 2.0f * PI_FLOAT; }
- if (cs.min_arc_segments > 0)
+ if (args_.min_arc_segments > 0)
{
// 20200417 - FormerLurker - Implement MIN_ARC_SEGMENTS if it is defined - from Marlin 2.0 implementation
// Do this before converting the angular travel for clockwise rotation
- mm_per_arc_segment = radius * ((2.0f * PI_FLOAT) / cs.min_arc_segments);
+ mm_per_arc_segment = radius * ((2.0f * PI_FLOAT) / args_.min_arc_segments);
}
- if (cs.arc_segments_per_sec > 0)
+ if (args_.arc_segments_per_sec > 0)
{
// 20200417 - FormerLurker - Implement MIN_ARC_SEGMENTS if it is defined - from Marlin 2.0 implementation
- float mm_per_arc_segment_sec = (feed_rate / 60.0f) * (1.0f / (float)cs.arc_segments_per_sec);
+ float mm_per_arc_segment_sec = (feed_rate / 60.0f) * (1.0f / (float)args_.arc_segments_per_sec);
if (mm_per_arc_segment_sec < mm_per_arc_segment)
mm_per_arc_segment = mm_per_arc_segment_sec;
}
// Note: no need to check to see if min_mm_per_arc_segment is enabled or not (i.e. = 0), since mm_per_arc_segment can never be below 0.
- if (mm_per_arc_segment < cs.min_mm_per_arc_segment)
+ if (mm_per_arc_segment < args_.min_mm_per_arc_segment)
{
// 20200417 - FormerLurker - Implement MIN_MM_PER_ARC_SEGMENT if it is defined
// This prevents a very high number of segments from being generated for curves of a short radius
- mm_per_arc_segment = cs.min_mm_per_arc_segment;
+ mm_per_arc_segment = static_cast<float>(args_.min_mm_per_arc_segment);
}
- else if (mm_per_arc_segment > cs.mm_per_arc_segment) {
+ else if (mm_per_arc_segment > args_.mm_per_arc_segment) {
// 20210113 - This can be implemented in an else if since we can't be below the min AND above the max at the same time.
// 20200417 - FormerLurker - Implement MIN_MM_PER_ARC_SEGMENT if it is defined
- mm_per_arc_segment = cs.mm_per_arc_segment;
+ mm_per_arc_segment = static_cast<float>(args_.mm_per_arc_segment);
}
// Adjust the angular travel if the direction is clockwise
@@ -420,7 +414,7 @@ void prusa::mc_arc_3_11_0(float* position, float* target, float* offset, float f
r_axis_x = -offset[X_AXIS] * cos_Ti + offset[Y_AXIS] * sin_Ti;
r_axis_y = -offset[X_AXIS] * sin_Ti - offset[Y_AXIS] * cos_Ti;
// reset n_arc_correction
- n_arc_correction = cs.n_arc_correction;
+ n_arc_correction = args_.n_arc_correction;
}
else {
// Calculate X and Y using the small angle approximation
diff --git a/ArcWelderInverseProcessor/prusa.h b/ArcWelderInverseProcessor/prusa.h
index 2a22edf..17ee97e 100644
--- a/ArcWelderInverseProcessor/prusa.h
+++ b/ArcWelderInverseProcessor/prusa.h
@@ -43,21 +43,6 @@
#include <iomanip>
#include <fstream>
-struct ConfigurationStore {
- ConfigurationStore() {
- mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT;
- min_mm_per_arc_segment = DEFAULT_MIN_MM_PER_ARC_SEGMENT;
- min_arc_segments = DEFAULT_MIN_ARC_SEGMENTS;
- arc_segments_per_sec = DEFAULT_ARC_SEGMENTS_PER_SEC;
- n_arc_correction = DEFAULT_N_ARC_CORRECTIONS;
- }
- float mm_per_arc_segment; // This value is ALWAYS used.
- float min_mm_per_arc_segment; // if less than or equal to 0, this is disabled
- int min_arc_segments; // If less than or equal to zero, this is disabled
- double arc_segments_per_sec; // If less than or equal to zero, this is disabled
- int n_arc_correction;
-
-};
class prusa :
public firmware
{
@@ -76,7 +61,6 @@ private:
/// <summary>
/// A struct representing the prusa configuration store. Note: I didn't add the trailing underscore so this variable name will match the original source algorithm name.
/// </summary>
- ConfigurationStore cs;
typedef void(prusa::*mc_arc_func)(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder);
void mc_arc_3_10_0(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder);
void mc_arc_3_11_0(float* position, float* target, float* offset, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder);
diff --git a/ArcWelderInverseProcessor/repetier.cpp b/ArcWelderInverseProcessor/repetier.cpp
index 2471478..f3feb61 100644
--- a/ArcWelderInverseProcessor/repetier.cpp
+++ b/ArcWelderInverseProcessor/repetier.cpp
@@ -48,11 +48,11 @@ void repetier::apply_arguments()
switch (repetier_version_)
{
case repetier::repetier_firmware_versions::V1_0_5:
- used_arguments = { "mm_per_arc_segment", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
arc_ = &repetier::arc_1_0_5;
break;
default:
- used_arguments = { "mm_per_arc_segment", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
arc_ = &repetier::arc_1_0_4;
break;
}
@@ -76,25 +76,11 @@ firmware_arguments repetier::get_default_arguments_for_current_version() const
default_args.mm_per_arc_segment = 1.0f;
default_args.n_arc_correction = 25;
default_args.min_arc_segments = 24;
- // Inactive Settings
- default_args.min_arc_segments = 0;
- default_args.arc_segments_per_r = 0;
- default_args.min_mm_per_arc_segment = 0;
- default_args.arc_segments_per_sec = 0;
- // Settings that do not apply
- default_args.mm_max_arc_error = 0;
break;
default:
// Active Settings
default_args.mm_per_arc_segment = 1.0f;
default_args.n_arc_correction = 25;
- // Inactive Settings
- default_args.min_arc_segments = 0;
- default_args.arc_segments_per_r = 0;
- default_args.min_mm_per_arc_segment = 0;
- default_args.arc_segments_per_sec = 0;
- // Settings that do not apply
- default_args.mm_max_arc_error = 0;
break;
}
return default_args;
diff --git a/ArcWelderInverseProcessor/smoothieware.cpp b/ArcWelderInverseProcessor/smoothieware.cpp
index a96c88d..43b8c3c 100644
--- a/ArcWelderInverseProcessor/smoothieware.cpp
+++ b/ArcWelderInverseProcessor/smoothieware.cpp
@@ -42,6 +42,7 @@ smoothieware::smoothieware(firmware_arguments args) : firmware(args) {
apply_arguments();
};
+
void smoothieware::apply_arguments()
{
static const std::vector<std::string> smoothieware_firmware_version_names{ "2021-06-19" };
@@ -53,7 +54,7 @@ void smoothieware::apply_arguments()
//{
//default:
append_arc_ = &smoothieware::append_arc_2021_06_19;
- used_arguments = { "mm_per_arc_segment", "mm_max_arc_error", "n_arc_correction", "g90_g91_influences_extruder" };
+ used_arguments = { FIRMWARE_ARGUMENT_MM_PER_ARC_SEGMENT, FIRMWARE_ARGUMENT_MM_MAX_ARC_ERROR, FIRMWARE_ARGUMENT_N_ARC_CORRECTION, FIRMWARE_ARGUMENT_G90_G91_INFLUENCES_EXTRUDER };
//break;
//}
diff --git a/GcodeProcessorLib/fpconv.h b/GcodeProcessorLib/fpconv.h
index 8afcb21..29af997 100644
--- a/GcodeProcessorLib/fpconv.h
+++ b/GcodeProcessorLib/fpconv.h
@@ -52,6 +52,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef FPCONV_H
#define FPCONV_H
+
+#define FPCONV_COPYRIGHT_STRING "Fpconv is an algorithm for producing fast floating point strings, which was added with the following notice: Copyright (C) 2014 Milo Yip. The original fpconv algorithm provides the following notice: Copyright(c) 2013 Andreas Samoljuk."
+
/* Fast and accurate double to string conversion based on Florian Loitsch's
* Grisu-algorithm[1].
*
diff --git a/GcodeProcessorLib/utilities.cpp b/GcodeProcessorLib/utilities.cpp
index c0cc6c8..d16f8f4 100644
--- a/GcodeProcessorLib/utilities.cpp
+++ b/GcodeProcessorLib/utilities.cpp
@@ -291,6 +291,11 @@ std::string utilities::join(const std::vector<std::string> strings, std::string
}
return output;
}
+/* Might need this later
+bool utilities::contains(const std::string source, const std::string substring)
+{
+ return source.find(substring, 0) != std::string::npos;
+}*/
std::istream& utilities::safe_get_line(std::istream& is, std::string& t)
{
@@ -471,6 +476,16 @@ bool utilities::get_temp_file_path_for_file(const std::string& file_path, std::s
return true;
}
+bool utilities::does_file_exist(const std::string& file_path)
+{
+ FILE* file;
+ if (file = fopen(file_path.c_str(), "r")) {
+ fclose(file);
+ return true;
+ }
+ return false;
+}
+
double utilities::hypot(double x, double y)
{
if (x < 0) x = -x;
@@ -703,10 +718,13 @@ bool case_insensitive_compare(std::string& str1, std::string& str2)
*/
std::string utilities::replace(std::string subject, const std::string& search, const std::string& replace) {
- size_t pos = 0;
- while ((pos = subject.find(search, pos)) != std::string::npos) {
- subject.replace(pos, search.length(), replace);
- pos += replace.length();
+ if (search.length() > 0)
+ {
+ size_t pos = 0;
+ while ((pos = subject.find(search, pos)) != std::string::npos) {
+ subject.replace(pos, search.length(), replace);
+ pos += replace.length();
+ }
}
return subject;
}
diff --git a/GcodeProcessorLib/utilities.h b/GcodeProcessorLib/utilities.h
index 7aa45b0..a71a36e 100644
--- a/GcodeProcessorLib/utilities.h
+++ b/GcodeProcessorLib/utilities.h
@@ -86,7 +86,7 @@ namespace utilities{
std::string join(const std::string* strings, size_t length, std::string sep);
std::string join(const std::vector<std::string> strings, std::string sep);
-
+ // bool contains(const std::string source, const std::string substring); // Might need this later
std::istream& safe_get_line(std::istream& is, std::string& t);
std::string center(std::string input, int width);
@@ -105,6 +105,8 @@ namespace utilities{
std::string create_uuid();
+ bool does_file_exist(const std::string& file_path);
+
bool get_temp_file_path_for_file(const std::string& file_path, std::string& temp_file_path);
double hypot(double x, double y);
diff --git a/TCLAP/TCLAP.vcxproj b/TCLAP/TCLAP.vcxproj
index 6b577ac..e6563e5 100644
--- a/TCLAP/TCLAP.vcxproj
+++ b/TCLAP/TCLAP.vcxproj
@@ -219,6 +219,7 @@
<ClInclude Include="tclap\StandardTraits.h" />
<ClInclude Include="tclap\StdOutput.h" />
<ClInclude Include="tclap\SwitchArg.h" />
+ <ClInclude Include="tclap\tclap_version.h" />
<ClInclude Include="tclap\UnlabeledMultiArg.h" />
<ClInclude Include="tclap\UnlabeledValueArg.h" />
<ClInclude Include="tclap\ValueArg.h" />
diff --git a/TCLAP/TCLAP.vcxproj.filters b/TCLAP/TCLAP.vcxproj.filters
index 3b2bed8..b9cc9ab 100644
--- a/TCLAP/TCLAP.vcxproj.filters
+++ b/TCLAP/TCLAP.vcxproj.filters
@@ -98,5 +98,8 @@
<ClInclude Include="tclap\ZshCompletionOutput.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="tclap\tclap_version.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/TCLAP/tclap/tclap_version.h b/TCLAP/tclap/tclap_version.h
new file mode 100644
index 0000000..ab366e8
--- /dev/null
+++ b/TCLAP/tclap/tclap_version.h
@@ -0,0 +1,3 @@
+#pragma once
+#define TCLAP_VERSION_STRING "1.4"
+#define TCLAP_COPYRIGHT_STRING "TCLAP: a templatized c++ command line parser, Copyright(C) 2017-2021 Google LLC, Copyright(C) 2012-2016 Daniel Aarno, Copyright(C) 2003-2012 Michael E. Smoot."
diff --git a/readme.md b/readme.md
index 2e8c947..66682e1 100644
--- a/readme.md
+++ b/readme.md
@@ -50,14 +50,29 @@ That will replace thing.gcode with a welded version of the file.
**Creating a new file**
-If you want your original file preserved, you can specify a target path like so:
+If you want your original file preserved, you can specify a target path.
+Windows example:
+
+```
+ArcWelder thing.gcode thing.aw.gcode
+```
+
+Linux/Raspbian example:
```
-C:\ArcWelder.exe C:\thing.gcode c:\thing.aw.gcode
+./ArcWelder thing.gcode thing.aw.gcode
```
That would create a new file called thing.aw.gcode and would leave the thing.gcode file alone.
+You can also supply a path for the source and target gcode files:
+
+```
+ArcWelder c:\my_gcode\thing.gcode c:\my_gcode\arc_welded_files\thing.aw.gcode
+```
+
+Note: You may need to enclose the paths in quotes, for example, if there are any spaces.
+
## ArcWelder Console Help
The console program will output all of the options with the following command for Windows:
@@ -86,7 +101,7 @@ For some printers, sending a G90 or G91 command also changes the E axis mode. T
* Default: Disabled
* Short Parameter: -g
* Long Parameter: --g90-influences-extruder
-* Example: ```ArcWelder -g "C:\thing.gcode"```
+* Example: ```ArcWelder "C:\thing.gcode" -g```
### Resolution (Maximum Path Deviation)
ArcWelder is able to compress line segments into gcode by taking advantage of the fact that a bunch of tiny line segments can, when viewed from a distance, approximate a curve. However, a true curved path will never match up exactly with a bunch of straight lines, so ArcWelder needs a bit of play in order to create arc commands. The *resolution argument* tells ArcWelder how much leeway it has with the original toolpath to make an arc. Increasing this value will result in more compression, and reducing it will improve accuracy. It is a trade-off, but one that most slicers implement anyway in order to prevent too many tiny movements from overwhelming your firmware. In fact, ArcWelder can produce toolpaths that are more accurate than simply merging short segments together, making it less 'lossy' than slicer resolution settings.
@@ -97,9 +112,10 @@ Values above 0.1 are not recommended, as you may encounter overlapping toolpaths
* Type: Value (millimeters)
* Default: 0.05 (+- 0.025)
+* Restrictions: Only values greater than 0 are allowed.
* Short Parameter: -r=<decimal_value>
* Long Parameter: --resolution-mm=<decimal_value>
-* Example: ```ArcWelder -r=0.1```
+* Example: ```ArcWelder "C:\thing.gcode" -r=0.1```
### Path Tolerance Percent (length)
This parameter allows you control how much the length of the final arc can deviate from the original toolpath. The default value of 5% is absolutely fine in most cases, even though that sounds like a lot. The key thing to remember here is that your firmware will break the G2/G3 commands into many small segments, essentially reversing the process, so the path length in your firmware will match the original path much more closely.
@@ -108,18 +124,20 @@ Originally, this setting was added as a safety feature to prevent prevent bad ar
* Type: Value (percent)
* Default: 0.05 (5%)
+* Restrictions: Only values greater than 0 (0%) and less than 1.0 (100%) are allowed.
* Short Parameter: -t=<decimal_value>
* Long Parameter: --path-tolerance-percent=<decimal_value>
-* Example: ```ArcWelder --path-tolerance-percent=0.10```
+* Example: ```ArcWelder "C:\thing.gcode" --path-tolerance-percent=0.10```
### Maximum Arc Radius
Allows you to control the maximum radius arc that will be generated with ArcWelder. This was added as a safety feature to prevent giant arcs from being generated for essentially straight lines. ArcWelder does have built-in detection to prevent colinear lines from being turned into arcs, but slight deviations due to the precision of the gcodes (usually fixed to 3 decimal places) can cause arcs to be generated where straight lines would do. Typically no adjustments are necessary from the defaults, but you can adjust this value if you want.
-* Type: Value (percent)
-* Default: 1000000.0 (1000000.0 millimeters or 1 kilometer)
+* Type: Value (decimal, millimeters)
+* Default: 9999.0mm
+* Restrictions: Only values greater than 0.0 are allowed.
* Short Parameter: -m=<decimal_value>
* Long Parameter: --max-radius-mm=<decimal_value>
-* Example: ```ArcWelder --max-radius-mm=1000.0```
+* Example: ```ArcWelder "C:\thing.gcode" --max-radius-mm=1000.0```
### Allow 3D Arcs
This option allows G2/G3 commands to be generated when using vase mode. This is an experimental option, and it's possible that there are some unknown firmware issues when adding Z coordinates to arc commands. That being said, I've gotten pretty good results from this option. At some point, this will be enabled by default.
@@ -128,49 +146,57 @@ This option allows G2/G3 commands to be generated when using vase mode. This is
* Default: Disabled
* Short Parameter: -z
* Long Parameter: --allow-3d-arcs
-* Example: ```ArcWelder --allow-3d-arcs```
+* Example: ```ArcWelder "C:\thing.gcode" --allow-3d-arcs```
### Allow Travel Arcs
-This option allows G2/G3 commands to be generated when for travel moves. In general, most travel moves will not be converted for the average 3D print. However, for plotters or CNC, or certain slicers that perform wipe actions while retracting, this feature can be useful. This is an experimental option.
+This option allows G2/G3 commands to be generated when for travel moves (moves without any extrusion). In general, most travel moves will not be converted for the average 3D print. However, for plotters or CNC, or certain slicers that perform wipe actions while retracting, this feature can be useful. This is an experimental option.
+
+Note: When using the allow-travel-arcs option, you will see separate statistics for the travel move conversion, or a message indicating that no travel moves were converted.
* Type: Flag
* Default: False
* Short Parameter: -y
* Long Parameter: --allow-travel-arcs
-* Example: ```ArcWelder --allow-travel-arcs```
+* Example: ```ArcWelder "C:\thing.gcode" --allow-travel-arcs```
### Allow Dynamic Precision
Not all gcode has the same precision for X, Y, and Z parameters. Enabling this option will cause the precision to grow as ArcWelder encounters gcodes with higher precision. This may increase gcode size somewhat, depending on the precision of the gcode commands in your file.
-**Important Note**: This option used to be the default, but in some cases I've seen files with unusually high precision. If it gets too high, the resulting gcode may overrun the gcode buffer size, causing prints to fail. For that reason, this option has been disabled by default. I've only seen a few cases where this happens, and it's always been due to custom start/end gcode with extremely high precision.
+**Important Note**: This option used to be the default, but in some cases I've seen files with unusually high precision. If it gets too high, the resulting gcode may overrun the gcode buffer size, causing prints to fail. For that reason, this option has been disabled by default. I've only seen a few cases where this happens, and it's always been due to custom start/end gcode with extremely high precision. See the Maximum Gcode Length section for more details.
* Type: Flag
* Default: Disabled
* Short Parameter: -d
* Long Parameter: --allow-dynamic-precision
-* Example: ```ArcWelder --allow-dynamic-precision```
+* Example: ```ArcWelder "C:\thing.gcode" --allow-dynamic-precision```
### Default XYZ Precision
-ArcWelder outputs fixed precision for X, Y, Z, I, and J parameters. 99% of the time the default of 3 decimal places is just fine. If you need (want) more or less precision, you can alter this value. In general, I do not recommend a value below 3 or above 5.
+ArcWelder outputs fixed precision for X, Y, Z, I, and J parameters. 99% of the time the default of 3 decimal places is just fine. If you need (want) more or less precision, you can alter this value.
+
+Note: that when combined with the --allow-dynamic-precision argument, this represents the minimum precision. It will grow if Arc Welder encounters gcode commands with a higher precision.
-Note that when combined with the --allow-dynamic-precision argument, this represents the minimum precision. It will grow if Arc Welder encounters gcode commands with a higher precision.
+**Important Note**: Some firmware isn't capable of executing gcodes that are too long. Increasing the precision will produce longer gcodes. See the Maximum Gcode Length section for more details.
* Type: Value (integer decimal places)
* Default: 3 (3 decimals, example: 1.001)
+* Restrictions: Allowed values are 3, 4, 5, or 6.
* Short Parameter: -x=<integer_value>
* Long Parameter: --default-xyz-precision=<integer_value>
-* Example: ```ArcWelder --default-xyz-precision=5```
+* Example: ```ArcWelder "C:\thing.gcode" --default-xyz-precision=5```
### Default E Precision
Arc Welder outputs fixed precision for the E parameter (extruder travel). 99% of the time the default of 5 decimal places is what you want. If you need (want) more or less precision, you can alter this value. In general, I do not recommend a value below 3 or above 5.
Note, that when combined with the --allow-dynamic-precision argument, this represents the minimum precision. It will grow if Arc Welder encounters gcode commands with a higher precision.
+**Important Note**: Some firmware isn't capable of executing gcodes that are too long. Increasing the precision will produce longer gcodes. See the Maximum Gcode Length section for more details.
+
* Type: Value (integer decimal places)
* Default: 5 (5 decimals, example: 1.00001)
+* Restrictions: Allowed values are 3, 4, 5, or 6.
* Short Parameter: -e=<integer_value>
* Long Parameter: --default-e-precision=<integer_value>
-* Example: ```ArcWelder --default-e-precision=3```
+* Example: ```ArcWelder "C:\thing.gcode" --default-e-precision=3```
### Firmware Compensation
**Important**: Do **NOT** enable firmware compensation unless you are sure you need it! Print quality and compression will suffer if it is enabled needlessly.
@@ -188,9 +214,10 @@ This is the default length of a segment in your firmware. This setting MUST mat
* Type: Value (millimeters)
* Default: 0 (disabled)
+* Restrictions: Only values greater than or equal to 0.0 are allowed. If set greater than 0, min-arc-segments must also be set.
* Short Parameter: -s=<decimal_value>
* Long Parameter: --mm-per-arc-segment=<decimal_value>
-* Example: ```ArcWelder --mm-per-arc-segment=1.0```
+* Example: ```ArcWelder "C:\thing.gcode" --mm-per-arc-segment=1.0 --min-arc-segments=14```
#### Minimum Arc Segments
This specifies the minimum number of segments that a circle of the same radius must have and is the parameter that determines how much compensation will be applied. This setting was inspired by the Marlin 2.0 arc interpolation algorithm and attempts to follow it as closely as possible. The higher the value, the more compensation will be applied, and the less compression you will get. A minimum of 14 is recommended. Values above 24 are NOT recommended. In general, this should be set as low as possible.
@@ -199,9 +226,10 @@ If ArcWelder detects that a generated arc would have fewer segments than specifi
* Type: Value
* Default: 0 (disabled)
+* Restrictions: Only values greater than or equal to 0.0 are allowed. If set greater than 0, mm-per-arc-segment must also be set.
* Short Parameter: -a=<integer_value>
* Long Parameter: --min-arc-segments=<integer_value>
-* Example: ```ArcWelder --min-arc-segments=14```
+* Example: ```ArcWelder "C:\thing.gcode" --mm-per-arc-segment=1.0 --min-arc-segments=14```
#### Firmware Compensation Example
If you need to enable firmware compensation because you notice that small arcs appear flat, I recommend you start with the following settings:
@@ -216,31 +244,47 @@ This feature allows ArcWelder to abort an arc if the extrusion rate changes by m
* Type: Value
* Default: 0.05 (5.0%)
+* Restrictions: Only values greater than or equal to 0.0 are allowed.
* Short Parameter: -v=<decimal_value> (0.05 = 5.0%, 0 to disable)
* Long Parameter: --extrusion-rate-variance-percent=<decimal_value>
-* Example: ```ArcWelder --extrusion-rate-variance-percent=0.025```
+* Example: ```ArcWelder "C:\thing.gcode" --extrusion-rate-variance-percent=0.025```
#### Maximum Gcode Length
Some firmware has a problem with long gcode commands, and G2/G3 commands are some of the longest. You can specify a maximum gcode length to prevent long commands from being generated, which will reduce compression by a tiny amount.
+Non-zero values less than 31 are not allowed.
+
* Type: Value
* Default: 0 (no limit)
+* Restrictions: Can be set to 0, or values > 30.
* Short Parameter: -c=<integer_value>
* Long Parameter: --max-gcode-length=<integer_value>
-* Example: ```ArcWelder --max-gcode-length=50```
+* Example: ```ArcWelder "C:\thing.gcode" --max-gcode-length=50```
-### Progress Type
+#### Progress Type
This setting allows you to control the type of progress messages the ArcWelder console application will display. There are three options:
* SIMPLE - This is the default setting. Here is a sample simple progress message: ```Progress: 21.9% complete - Estimated 35 of 45 seconds remaing.```
* FULL - This will show a much more detailed message, which is useful for any applications that which to scrape the detailed progress messages. Here is a sample full progress message: ```Progress: percent_complete:100.00, seconds_elapsed:0.01, seconds_remaining:0.00, gcodes_processed: 4320, current_file_line: 4320, points_compressed: 2092, arcs_created: 81, arcs_aborted_by_flowrate: 59, num_firmware_compensations: 0, num_gcode_length_exceptions: 0, compression_ratio: 2.27, size_reduction: 55.96%```
* NONE - No progress messages will be shown.
-* Type: Flag
+* Type: Value
* Default: SIMPLE
-* Short Parameter: -P
-* Long Parameter: --progress-type
-* Example: ```ArcWelder --progress-type=FULL```
+* Short Parameter: -P=<SIMPLE|FULL|NONE>
+* Long Parameter: --progress-type=<SIMPLE|FULL|NONE>
+* Example: ```ArcWelder "C:\thing.gcode" --progress-type=FULL```
+
+#### Log Level
+When set, ArcWelder will log to the console. This can be used to track down issues, or to figure out exactly what ArcWelder is doing.
+
+**Important Note:** Setting the log level could cause a huge amount of data to be outputted to the console, and will cause ArcWelder to be slow. I recommend you redirect the console output to speed things up if you use the DEBUG, VERBOSE or NOSET log levels.
+
+* Type: Value
+* Default: INFO
+* Short Parameter: -l=<NOSET|VERBOSE|DEBUG|INFO|WARNING|ERROR|CRITICAL>
+* Long Parameter: --log-level=<NOSET|VERBOSE|DEBUG|INFO|WARNING|ERROR|CRITICAL>
+* Example: ```ArcWelder "C:\thing.gcode" --log-level=DEBUG```
+
## Slicer Integrations
@@ -341,26 +385,28 @@ Currently there are 5 different firmware types available: MARLIN_1, MARLIN_2, R
* Default: MARLIN_2
* Short Parameter: -f=<string>
* Long Parameter: --firmware-type=<string>
-* Example: ```--firmware-type==PRUSA```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --firmware-type==MARLIN_1```
#### Firmware Version
Use this argument to specify the firmware version. Not all versions are supported. To see a list of available versions for each firmware type, use the --help argument. Note that the LATEST_RELEASE parameter does not always point to the most recent version, but rather the most recent stable release. Also, the PRUSA firmware version V3_11_0 is not yet released, but was added assuming new arc interpolation parameters from the roadmap will be included.
+Note: You may need to specify the firmware-type argument to choose the appropriate firmware version.
+
* Type: Value
* Default: LATEST_RELEASE
* Short Parameter: -V=<string>
* Long Parameter: --firmware_version=<string>
-* Example: ```--firmware_version==V1_1_9_1```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --firmware-type==MARLIN_1 --firmware_version==1.1.9.1```
#### Print Firmware Defaults and Supported Settings
Prints all avaliable settings and defaults for the provided firmware type and version. When using this parameter, all other valid parameters will be ignored.
-Note: Supply the --firmware_type and --firmware_version to see the defaults and supported settings.
+Note: Supply the --firmware_type and --firmware_version to see the defaults and supported settings. When printing firmware defaults, you don't need to supply a source file location.
* Type: Flag
* Short Parameter: -p
* Long Parameter: --print-firmware-defaults
-* Example: ```ArcStraightener --print-firmware-defaults --firmware_type=PRUSA --firmware_version==V1_1_9_1```
+* Example: ```ArcStraightener --print-firmware-defaults --firmware_type=MARLIN_1 --firmware_version==1.1.9.1```
## Firmware Specific Settings
The different firmware types and versions all support different arc interpolation settings. See the Print Firmware Defaults section for info on how to discover what paramaters a specific firmware version supports, as well as the defaults.
@@ -372,7 +418,7 @@ Sets the firmware's G90/G91 influences extruder axis behavior. By default this
* Default: Set By Firmware Type and Version
* Short Parameter: -g=<TRUE,FALSE>
* Long Parameter: --g90-influences-extruder=<string>
-* Example: ```ArcStraightener <SOURCE> --firmware_type=PRUSA --firmware_version==V1_1_9_1 --g90-influences-extruder=TRUE```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --firmware_type=PRUSA --firmware_version==V1_1_9_1 --g90-influences-extruder=TRUE```
Note, in the example above, the default behavior of the prusa firmware is overridden by the argument.
@@ -383,7 +429,7 @@ This is the default segment length for arc interpolation. Depending on the impl
* Default: 1.0
* Short Parameter: -m=<decimal_value>
* Long Parameter: --mm-per-arc-segment=<decimal_value>
-* Example: ```ArcStraightener <SOURCE> --mm-per-arc-segment=0.5```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --mm-per-arc-segment=0.5```
#### Max Arc Segment MM
This is the maximum length an arc segment can be.
@@ -392,7 +438,16 @@ This is the maximum length an arc segment can be.
* Default: 1.0
* Short Parameter: -d=<decimal_value>
* Long Parameter: --max-arc-segment-mm=<decimal_value>
-* Example: ```ArcStraightener <SOURCE> --max-arc-segment-mm=0.5```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --max-arc-segment-mm=0.5```
+
+#### Arc Segments Per R
+This is the maximum length an arc segment can be. It's basically the same as Max Arc Segment MM, but is used in different firmware
+
+* Type: Value (millimeters)
+* Default: 0 (disabled)
+* Short Parameter: -i=<decimal_value>
+* Long Parameter: --arc-segments-per-r=<decimal_value>
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --arc-segments-per-r=0.5```
#### Min Arc Segment MM
This is the Minimum length an arc segment can be.
@@ -401,7 +456,7 @@ This is the Minimum length an arc segment can be.
* Default: 1.0
* Short Parameter: -n=<decimal_value>
* Long Parameter: --min-mm-per-arc-segment=<decimal_value>
-* Example: ```ArcStraightener <SOURCE> --min-mm-per-arc-segment=0.5```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --min-mm-per-arc-segment=0.5```
#### Min Arc Segments
The minimum number of segments within a circle of the same radius as the arc. Can be used to increase detail on small arcs.
@@ -410,7 +465,7 @@ The minimum number of segments within a circle of the same radius as the arc. C
* Default: 24
* Short Parameter: -r=<integer_value>
* Long Parameter: --min-arc-segments=<integer_value>
-* Example: ```ArcStraightener <SOURCE> --min-arc-segments=24```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --min-arc-segments=24```
#### Min Circle Segments
This is a the same as the Min Arc Segments setting used in some firmware versions. Can be used to increase detail on small arcs.
@@ -419,7 +474,7 @@ This is a the same as the Min Arc Segments setting used in some firmware version
* Default: 72
* Short Parameter: -a=<integer_value>
* Long Parameter: --min-circle-segments=<integer_value>
-* Example: ```ArcStraightener <SOURCE> --min-circle-segments=24```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --min-circle-segments=24```
#### N Arc Correction
The number of segments that will be interpolated using a small angle approximation before true sin/cos corrections are applied. A value less than or equal to 1 will disable this feature. Note that enabling this can cause visible interpolation errors, especially on arcs with a very large radius. Disabling this setting could cause performance issues on slower hardware.
@@ -428,7 +483,7 @@ The number of segments that will be interpolated using a small angle approximati
* Default: 24
* Short Parameter: -c=<integer_value>
* Long Parameter: --n-arc-correction=<integer_value>
-* Example: ```ArcStraightener <SOURCE> --n-arc-correction=8```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --n-arc-correction=8```
#### Arc Segments Per Second
The number of segments per second. This will produce a constant number of arcs, clamped between mm-per-arc-segment and min-mm-per-arc-segment. Can be used to prevent stuttering when printing very quickly. A value less than or equal to 0 will disable this feature.
@@ -437,7 +492,7 @@ The number of segments per second. This will produce a constant number of arcs,
* Default: 0 (Disabled)
* Short Parameter: -s=<integer_value>
* Long Parameter: --arc-segments-per-second=<integer_value>
-* Example: ```ArcStraightener <SOURCE> --arc-segments-per-second=24```
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --arc-segments-per-second=24```
#### MM Max Arc Error
I'm not 100% sure exactly what this does, but I believe it attempts to limit the drift in the arc path to this value in MM. When I know more I will update this description. This currently is only used in Smoothieware. Set to 0 to disable.
@@ -446,4 +501,4 @@ I'm not 100% sure exactly what this does, but I believe it attempts to limit the
* Default: 0.01
* Short Parameter: -e=<decimal_value>
* Long Parameter: --mm-max-arc-error=<decimal_value>
-* Example: ```ArcStraightener <SOURCE> --mm-max-arc-error=0.25``` \ No newline at end of file
+* Example: ```ArcStraightener "C:\thing.aw.gcode" --mm-max-arc-error=0.25``` \ No newline at end of file