diff options
author | Remco Burema <41987080+rburema@users.noreply.github.com> | 2022-11-01 22:09:51 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-01 22:09:51 +0300 |
commit | d98c06b6a987f36b78b19f7119067f0cca89eae2 (patch) | |
tree | 74a82cabeb4bb82d6c246b1be666859ab75596a1 | |
parent | 4585a7d3294aa49549de7f6f83ea30d0bcda2944 (diff) | |
parent | a09f6118682f6e25577679b0c570a123f36f1f3d (diff) |
Merge pull request #1742 from Ultimaker/CURA-7271_slow_lines_individually_minimum_layer_time
Cura 7271 slow lines individually minimum layer time
-rw-r--r-- | include/LayerPlan.h | 20 | ||||
-rw-r--r-- | include/pathPlanning/TimeMaterialEstimates.h | 2 | ||||
-rw-r--r-- | src/LayerPlan.cpp | 171 |
3 files changed, 107 insertions, 86 deletions
diff --git a/include/LayerPlan.h b/include/LayerPlan.h index 5c1290bd6..1c5e2f322 100644 --- a/include/LayerPlan.h +++ b/include/LayerPlan.h @@ -72,6 +72,7 @@ protected: std::optional<double> prev_extruder_standby_temp; //!< The temperature to which to set the previous extruder. Not used if the previous extruder plan was the same extruder. TimeMaterialEstimates estimates; //!< Accumulated time and material estimates for all planned paths within this extruder plan. + double slowest_path_speed; public: size_t extruder_nr; //!< The extruder used for this paths in the current plan. @@ -129,22 +130,6 @@ public: void processFanSpeedAndMinimalLayerTime(bool force_minimal_layer_time, Point starting_position); /*! - * Set the extrude speed factor. This is used for printing slower than normal. - * - * Leaves the extrusion speed as is for values of 1.0 - * - * \param speedFactor The factor by which to alter the extrusion move speed - */ - void setExtrudeSpeedFactor(const Ratio speed_factor); - - /*! - * Get the extrude speed factor. This is used for printing slower than normal. - * - * \return The factor by which to alter the extrusion move speed - */ - double getExtrudeSpeedFactor(); - - /*! * Get the fan speed computed for this extruder plan * * \warning assumes ExtruderPlan::processFanSpeedAndMinimalLayerTime has already been called @@ -175,10 +160,7 @@ protected: const RetractionConfig& retraction_config; //!< The retraction settings for the extruder of this plan - Ratio extrudeSpeedFactor; //!< The factor by which to alter the extrusion move speed - double extraTime; //!< Extra waiting time at the and of this extruder plan, so that the filament can cool - double totalPrintTime; //!< The total naive time estimate for this extruder plan double fan_speed; //!< The fan speed to be used during this extruder plan diff --git a/include/pathPlanning/TimeMaterialEstimates.h b/include/pathPlanning/TimeMaterialEstimates.h index a425dcedc..4a0052655 100644 --- a/include/pathPlanning/TimeMaterialEstimates.h +++ b/include/pathPlanning/TimeMaterialEstimates.h @@ -17,6 +17,8 @@ class TimeMaterialEstimates friend class ExtruderPlan; // cause there the naive estimates are calculated private: double extrude_time; //!< Time in seconds occupied by extrusion + double extrude_time_at_slowest_path_speed; //!< Time in seconds occupied by extrusion assuming paths are printed at slowest path speed, usually the outer wall speed + double extrude_time_at_minimum_speed; //!< Time in seconds occupied by extrusion assuming paths are printed at the user specified Minimum Speed double unretracted_travel_time; //!< Time in seconds occupied by non-retracted travel (non-extrusion) double retracted_travel_time; //!< Time in seconds occupied by retracted travel (non-extrusion) double material; //!< Material used (in mm^3) diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index ecc67cdb4..5de685cfa 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -1,7 +1,9 @@ // Copyright (c) 2022 Ultimaker B.V. // CuraEngine is released under the terms of the AGPLv3 or higher +#include <algorithm> #include <cstring> +#include <numeric> #include <optional> #include <spdlog/spdlog.h> @@ -28,25 +30,27 @@ namespace cura constexpr int MINIMUM_LINE_LENGTH = 5; // in uM. Generated lines shorter than this may be discarded constexpr int MINIMUM_SQUARED_LINE_LENGTH = MINIMUM_LINE_LENGTH * MINIMUM_LINE_LENGTH; -ExtruderPlan::ExtruderPlan(const size_t extruder, - const LayerIndex layer_nr, - const bool is_initial_layer, - const bool is_raft_layer, - const coord_t layer_thickness, - const FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, - const RetractionConfig& retraction_config) - : heated_pre_travel_time(0) - , required_start_temperature(-1) - , extruder_nr(extruder) - , layer_nr(layer_nr) - , is_initial_layer(is_initial_layer) - , is_raft_layer(is_raft_layer) - , layer_thickness(layer_thickness) - , fan_speed_layer_time_settings(fan_speed_layer_time_settings) - , retraction_config(retraction_config) - , extrudeSpeedFactor(1.0) - , extraTime(0.0) - , totalPrintTime(0) +ExtruderPlan::ExtruderPlan +( + const size_t extruder, + const LayerIndex layer_nr, + const bool is_initial_layer, + const bool is_raft_layer, + const coord_t layer_thickness, + const FanSpeedLayerTimeSettings& fan_speed_layer_time_settings, + const RetractionConfig& retraction_config +) : + heated_pre_travel_time(0), + required_start_temperature(-1), + extruder_nr(extruder), + layer_nr(layer_nr), + is_initial_layer(is_initial_layer), + is_raft_layer(is_raft_layer), + layer_thickness(layer_thickness), + fan_speed_layer_time_settings(fan_speed_layer_time_settings), + retraction_config(retraction_config), + extraTime(0.0), + slowest_path_speed(0.0) { } @@ -70,16 +74,6 @@ void ExtruderPlan::handleAllRemainingInserts(GCodeExport& gcode) } } -void ExtruderPlan::setExtrudeSpeedFactor(const Ratio speed_factor) -{ - extrudeSpeedFactor = speed_factor; -} - -double ExtruderPlan::getExtrudeSpeedFactor() -{ - return extrudeSpeedFactor; -} - void ExtruderPlan::setFanSpeed(double _fan_speed) { fan_speed = _fan_speed; @@ -1466,61 +1460,105 @@ void LayerPlan::spiralizeWallSlice(const GCodePathConfig& config, ConstPolygonRe void ExtruderPlan::forceMinimalLayerTime(double minTime, double minimalSpeed, double travelTime, double extrudeTime) { - double totalTime = travelTime + extrudeTime; - if (totalTime < minTime && extrudeTime > 0.0) + const double totalTime = travelTime + extrudeTime; + constexpr double epsilon = 0.01; + + double total_extrude_time_at_minimum_speed = 0.0; + double total_extrude_time_at_slowest_speed = 0.0; + for (GCodePath& path : paths) { - double minExtrudeTime = minTime - travelTime; - if (minExtrudeTime < 1) - minExtrudeTime = 1; - double factor = extrudeTime / minExtrudeTime; - for (GCodePath& path : paths) + total_extrude_time_at_minimum_speed += path.estimates.extrude_time_at_minimum_speed; + total_extrude_time_at_slowest_speed += path.estimates.extrude_time_at_slowest_path_speed; + } + + if (totalTime < minTime - epsilon && extrudeTime > 0.0) + { + const double minExtrudeTime = minTime - travelTime; + + double factor = 0.0; + double target_speed = 0.0; + std::function<double(const GCodePath&)> slow_down_func { - if (path.isTravelPath()) - continue; - double speed = path.config->getSpeed() * path.speed_factor * factor; - if (speed < minimalSpeed) - factor = minimalSpeed / (path.config->getSpeed() * path.speed_factor); - } + [&target_speed](const GCodePath& path) { return target_speed / (path.config->getSpeed() * path.speed_factor); } + }; - // Only slow down for the minimal time if that will be slower. - assert(getExtrudeSpeedFactor() == 1.0); // The extrude speed factor is assumed not to be changed yet - if (factor < 1.0) + if (minExtrudeTime >= total_extrude_time_at_minimum_speed) { - setExtrudeSpeedFactor(factor); + // Even at cool min speed extrusion is not taken enough time. So speed is set to cool min speed. + target_speed = minimalSpeed; + + // Update stored naive time estimates + estimates.extrude_time = total_extrude_time_at_minimum_speed; + if (minTime - total_extrude_time_at_minimum_speed - travelTime > epsilon) + { + extraTime = minTime - total_extrude_time_at_minimum_speed - travelTime; + } } - else + else if (minExtrudeTime >= total_extrude_time_at_slowest_speed && std::abs(total_extrude_time_at_minimum_speed - total_extrude_time_at_slowest_speed) >= epsilon) { - factor = 1.0; - } - - double inv_factor = 1.0 / factor; // cause multiplication is faster than division + // Slowing down to the slowest path speed is not sufficient, need to slow down further to the minimum speed. + // Linear interpolate between total_extrude_time_at_slowest_speed and total_extrude_time_at_minimum_speed + const double factor = (total_extrude_time_at_minimum_speed - minExtrudeTime) / (total_extrude_time_at_minimum_speed - total_extrude_time_at_slowest_speed); + target_speed = minimalSpeed * (1.0-factor) + slowest_path_speed * factor; - // Adjust stored naive time estimates - estimates.extrude_time *= inv_factor; - for (GCodePath& path : paths) + // Update stored naive time estimates + estimates.extrude_time = minExtrudeTime; + } + else { - path.estimates.extrude_time *= inv_factor; + // Slowing down to the slowest_speed is sufficient to respect the minimum layer time. + // Linear interpolate between extrudeTime and total_extrude_time_at_slowest_speed + factor = (total_extrude_time_at_slowest_speed - minExtrudeTime) / (total_extrude_time_at_slowest_speed - extrudeTime); + slow_down_func = + [&slowest_path_speed = slowest_path_speed, &factor](const GCodePath& path) + { + const double target_speed = slowest_path_speed * (1.0 - factor) + (path.config->getSpeed() * path.speed_factor) * factor; + return target_speed / (path.config->getSpeed() * path.speed_factor); + }; + + // Update stored naive time estimates + estimates.extrude_time = minExtrudeTime; } - if (minTime - (extrudeTime * inv_factor) - travelTime > 0.1) + for (GCodePath& path : paths) { - extraTime = minTime - (extrudeTime * inv_factor) - travelTime; + if (path.isTravelPath()) + { + continue; + } + path.speed_factor = slow_down_func(path); + path.estimates.extrude_time /= path.speed_factor; } - totalPrintTime = (extrudeTime * inv_factor) + travelTime; } } TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates(Point starting_position) { - TimeMaterialEstimates ret; Point p0 = starting_position; + const double min_path_speed = fan_speed_layer_time_settings.cool_min_speed; + slowest_path_speed = + std::accumulate + ( + paths.begin(), + paths.end(), + std::numeric_limits<double>::max(), + [](double value, const GCodePath& path) + { + return path.isTravelPath() ? value : std::min(value, path.config->getSpeed().value * path.speed_factor); + } + ); + bool was_retracted = false; // wrong assumption; won't matter that much. (TODO) for (GCodePath& path : paths) { bool is_extrusion_path = false; double* path_time_estimate; double& material_estimate = path.estimates.material; + + path.estimates.extrude_time_at_minimum_speed = 0.0; + path.estimates.extrude_time_at_slowest_path_speed = 0.0; + if (! path.isTravelPath()) { is_extrusion_path = true; @@ -1556,6 +1594,11 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates(Point starting_pos double length = vSizeMM(p0 - p1); if (is_extrusion_path) { + if (length > 0) + { + path.estimates.extrude_time_at_minimum_speed += length / min_path_speed; + path.estimates.extrude_time_at_slowest_path_speed += length / slowest_path_speed; + } material_estimate += length * INT2MM(layer_thickness) * INT2MM(path.config->getLineWidth()); } double thisTime = length / (path.config->getSpeed() * path.speed_factor); @@ -1570,7 +1613,6 @@ TimeMaterialEstimates ExtruderPlan::computeNaiveTimeEstimates(Point starting_pos void ExtruderPlan::processFanSpeedAndMinimalLayerTime(bool force_minimal_layer_time, Point starting_position) { TimeMaterialEstimates estimates = computeNaiveTimeEstimates(starting_position); - totalPrintTime = estimates.getTotalTime(); if (force_minimal_layer_time) { forceMinimalLayerTime(fan_speed_layer_time_settings.cool_min_layer_time, fan_speed_layer_time_settings.cool_min_speed, estimates.getTravelTime(), estimates.getExtrudeTime()); @@ -1865,11 +1907,6 @@ void LayerPlan::writeGCode(GCodeExport& gcode) // for some movements such as prime tower purge, the speed may get changed by this factor speed *= path.speed_factor; - // Apply the extrusion speed factor if it's an extrusion move. - if (! path.config->isTravelPath()) - { - speed *= extruder_plan.getExtrudeSpeedFactor(); - } // This seems to be the best location to place this, but still not ideal. if (path.mesh_id != current_mesh) { @@ -2052,7 +2089,7 @@ bool LayerPlan::writePathWithCoasting(GCodeExport& gcode, const size_t extruder_ coord_t coasting_min_dist_considered = MM2INT(0.1); // hardcoded setting for when to not perform coasting - const double extrude_speed = path.config->getSpeed() * extruder_plan.getExtrudeSpeedFactor() * path.speed_factor * path.speed_back_pressure_factor; + const double extrude_speed = path.config->getSpeed() * path.speed_factor * path.speed_back_pressure_factor; const coord_t coasting_dist = MM2INT(MM2_2INT(coasting_volume) / layer_thickness) / path.config->getLineWidth(); // closing brackets of MM2INT at weird places for precision issues const double coasting_min_volume = extruder.settings.get<double>("coasting_min_volume"); @@ -2140,7 +2177,7 @@ bool LayerPlan::writePathWithCoasting(GCodeExport& gcode, const size_t extruder_ for (size_t point_idx = point_idx_before_start + 1; point_idx < path.points.size(); point_idx++) { const Ratio coasting_speed_modifier = extruder.settings.get<Ratio>("coasting_speed"); - const Velocity speed = Velocity(coasting_speed_modifier * path.config->getSpeed() * extruder_plan.getExtrudeSpeedFactor()); + const Velocity speed = Velocity(coasting_speed_modifier * path.config->getSpeed()); gcode.writeTravel(path.points[point_idx], speed); } return true; |