From f1a91d9d092a3b1edb48defcd41e5a55a4459dec Mon Sep 17 00:00:00 2001 From: supermerill Date: Mon, 29 Jan 2024 19:54:49 +0100 Subject: [PATCH] Fix fan_mover/gcodeprocessor with G2/G3 via new test case supermerill/SuperSlicer#4061 --- src/libslic3r/GCode/FanMover.cpp | 64 ++-- src/libslic3r/GCode/FanMover.hpp | 5 + src/libslic3r/GCodeReader.cpp | 2 +- tests/superslicerlibslic3r/test_fan_mover.cpp | 316 ++++++++++++++++++ 4 files changed, 365 insertions(+), 22 deletions(-) diff --git a/src/libslic3r/GCode/FanMover.cpp b/src/libslic3r/GCode/FanMover.cpp index b108bbc459a..989e08bdb8a 100644 --- a/src/libslic3r/GCode/FanMover.cpp +++ b/src/libslic3r/GCode/FanMover.cpp @@ -34,8 +34,7 @@ const std::string& FanMover::process_gcode(const std::string& gcode, bool flush) if (flush) { while (!m_buffer.empty()) { - m_process_output += m_buffer.front().raw + "\n"; - remove_from_buffer(m_buffer.begin()); + write_buffer_data(); } } @@ -282,6 +281,15 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode dist = std::sqrt(dist); time = dist / m_current_speed; } + } else if (::atoi(&cmd[1]) == 2 || ::atoi(&cmd[1]) == 3) { + // TODO: compute real dist + double distx = line.dist_X(reader); + double disty = line.dist_Y(reader); + double dist = distx * distx + disty * disty; + if (dist > 0) { + dist = std::sqrt(dist); + time = dist / m_current_speed; + } } break; } @@ -433,11 +441,18 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode } if (line.has(Axis::E)) { new_data.e = reader.e(); - if (relative_e) + if (relative_e) { + assert(new_data.e == 0); new_data.de = line.e(); - else + } else new_data.de = line.dist_E(reader); } + assert(new_data.dx == 0 || reader.x() == new_data.x); + assert(new_data.dx == 0 || reader.x() + new_data.dx == line.x()); + assert(new_data.dy == 0 ||reader.y() == new_data.y); + assert(new_data.dy == 0 || reader.y() + new_data.dy == line.y()); + assert(new_data.de == 0 || reader.e() == new_data.e); + assert(new_data.de == 0 || reader.e() + new_data.de == line.e()); if (m_current_kickstart.time > 0 && time > 0) { m_current_kickstart.time -= time; @@ -472,23 +487,7 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode //if buffer too big, flush it. if (time >= 0) { while (!m_buffer.empty() && (need_flush || m_buffer_time_size - m_buffer.front().time > nb_seconds_delay - EPSILON) ){ - BufferData& frontdata = m_buffer.front(); - if (frontdata.fan_speed < 0 || frontdata.fan_speed != m_front_buffer_fan_speed || frontdata.is_kickstart) { - if (frontdata.is_kickstart && frontdata.fan_speed < m_front_buffer_fan_speed) { - //you have to slow down! not kickstart! rewrite the fan speed. - m_process_output += _set_fan(frontdata.fan_speed);//m_writer.set_fan(frontdata.fan_speed,true); //FIXME extruder id (or use the gcode writer, but then you have to disable the multi-thread thing - - m_front_buffer_fan_speed = frontdata.fan_speed; - } else { - m_process_output += frontdata.raw + "\n"; - if (frontdata.fan_speed >= 0) { - //note that this is the only place where the fan_speed is set and we print from the buffer, as if the fan_speed >= 0 => time == 0 - //and as this flush all time == 0 lines from the back of the queue... - m_front_buffer_fan_speed = frontdata.fan_speed; - } - } - } - remove_from_buffer(m_buffer.begin()); + write_buffer_data(); } } #if _DEBUG @@ -498,5 +497,28 @@ void FanMover::_process_gcode_line(GCodeReader& reader, const GCodeReader::GCode #endif } +void FanMover::write_buffer_data() +{ + BufferData &frontdata = m_buffer.front(); + if (frontdata.fan_speed < 0 || frontdata.fan_speed != m_front_buffer_fan_speed || frontdata.is_kickstart) { + if (frontdata.is_kickstart && frontdata.fan_speed < m_front_buffer_fan_speed) { + // you have to slow down! not kickstart! rewrite the fan speed. + m_process_output += _set_fan( + frontdata.fan_speed); // m_writer.set_fan(frontdata.fan_speed,true); //FIXME extruder id (or use the + // gcode writer, but then you have to disable the multi-thread thing + + m_front_buffer_fan_speed = frontdata.fan_speed; + } else { + m_process_output += frontdata.raw + "\n"; + if (frontdata.fan_speed >= 0) { + // note that this is the only place where the fan_speed is set and we print from the buffer, as if the + // fan_speed >= 0 => time == 0 and as this flush all time == 0 lines from the back of the queue... + m_front_buffer_fan_speed = frontdata.fan_speed; + } + } + } + remove_from_buffer(m_buffer.begin()); +} + } // namespace Slic3r diff --git a/src/libslic3r/GCode/FanMover.hpp b/src/libslic3r/GCode/FanMover.hpp index 2d0c3ad6306..a5598df4bfe 100644 --- a/src/libslic3r/GCode/FanMover.hpp +++ b/src/libslic3r/GCode/FanMover.hpp @@ -15,11 +15,15 @@ namespace Slic3r { class BufferData { public: + //raw string, contains end position std::string raw; + // time to go from start to end float time; int16_t fan_speed; bool is_kickstart; + // start position float x = 0, y = 0, z = 0, e = 0; + // delta to go to end position float dx = 0, dy = 0, dz = 0, de = 0; BufferData(std::string line, float time = 0, int16_t fan_speed = 0, float is_kickstart = false) : raw(line), time(time), fan_speed(fan_speed), is_kickstart(is_kickstart){ //avoid double \n @@ -86,6 +90,7 @@ class FanMover void _put_in_middle_G1(std::list::iterator item_to_split, float nb_sec, BufferData&& line_to_write); void _print_in_middle_G1(BufferData& line_to_split, float nb_sec, const std::string& line_to_write); void _remove_slow_fan(int16_t min_speed, float past_sec); + void write_buffer_data(); std::string _set_fan(int16_t speed); }; diff --git a/src/libslic3r/GCodeReader.cpp b/src/libslic3r/GCodeReader.cpp index c8a9b790fcf..ef0c4bfa085 100644 --- a/src/libslic3r/GCodeReader.cpp +++ b/src/libslic3r/GCodeReader.cpp @@ -120,7 +120,7 @@ void GCodeReader::update_coordinates(GCodeLine &gline, std::pair std::string { + std::string s = ";LAYER_CHANGE\n"; + s += ";Z:18.4\n"; + s += ";HEIGHT:0.199999\n"; + s += "G92 E0\n"; + s += "G10 ; retract\n"; + s += "; stop printing object Star_face.stl id:0 copy 0\n"; + s += "EXCLUDE_OBJECT_END NAME=Star_face_stl_id_0_copy_0\n"; + s += "M204 S10000\n"; + s += "G1 Z18.4 F1800\n"; + s += "G92 E0\n"; + s += "; printing object Star_face.stl id:0 copy 0\n"; + s += "EXCLUDE_OBJECT_START NAME=Star_face_stl_id_0_copy_0\n"; + s += "; acceleration to travel\n"; + s += "G1 X163.229 Y127.604 F18000\n"; + s += "G1 X146.967 Y135.013\n"; + s += "G1 X146.61 Y135.175\n"; + s += "G1 X123.351 Y145.771\n"; + s += "G1 X122.18 Y146.428\n"; + s += "; decel to extrusion\n"; + s += "M204 S5000\n"; + s += "G1 X118.537 Y148.471\n"; + s += "G1 X117.236 Y148.733\n"; + s += "G1 X116.744 Y148.781\n"; + s += "G1 X116.452 Y148.95\n"; + s += "; end travel\n"; + s += "G11 ; unretract\n"; + s += "G92 E0\n"; + s += ";TYPE:External perimeter\n"; + s += ";WIDTH:0.698815\n"; + s += "M106 S25.5\n"; + s += "G1 F4650\n"; + s += "G1 X115.957 Y148.975 E0.02567\n"; + s += "G3 X105.872 Y142.185 I-.066 J-10.787 E.69483\n"; + s += "G1 X105.745 Y141.815 E0.71508\n"; + s += "G3 X106.128 Y133.713 I10.705 J-3.555 E1.14496\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.728025\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X108.063 Y130.539 I11.385 J4.764 E1.34692\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.75984\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X112.6 Y127.602 I6.872 J5.643 E1.65789\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.789218\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X125.102 Y132.013 I3.494 J10.021 E2.50206\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.755247\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X126.771 Y137.462 I-9.904 J6.012 E2.82604\n"; + if(!remove_useless) s += "M106 S25.5\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 X126.775 Y137.806 E2.84539\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.727549\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X123.57 Y145.764 I-11.051 J.175 E3.32189\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.698815\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X116.606 Y148.952 I-7.679 J-7.576 E3.72755\n"; + s += "G1 X116.527 Y148.951 E3.73167\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIPE_START\n"; + s += "M204 S10000\n"; + s += "G1 X116.189 Y148.524 F18000\n"; + s += ";WIPE_END\n"; + s += "; acceleration to travel\n"; + s += "G1 X115.678 Y148.359\n"; + s += "; decel to extrusion\n"; + s += "M204 S5000\n"; + s += "G1 X115.422 Y148.276\n"; + s += "; end travel\n"; + s += ";WIDTH:0.720254\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 F4650\n"; + s += "G1 X116.001 Y148.314 E3.76269\n"; + s += "G2 X122.624 Y145.725 I-.12 J-10.072 E4.15158\n"; + s += "G2 X123.751 Y144.568 I-8.904 J-9.799 E4.23803\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.748162\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X126.066 Y137.801 I-7.967 J-6.506 E4.64496\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.77744\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X124.935 Y133.225 I-11.113 J.321 E4.92054\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.805275\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X119.271 Y128.291 I-8.81 J4.395 E5.38463\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.773006\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X113.961 Y127.995 I-3.206 J9.712 E5.69495\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.76111\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 X113.76 Y128.037 E5.70656\n"; + s += "G2 X110.376 Y129.391 I2.27 J10.575 E5.91434\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.728025\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X108.025 Y131.708 I5.15 J7.579 E6.09394\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.692664\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X105.869 Y139.349 I8.98 J6.658 E6.51053\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.720254\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X115.208 Y148.292 I10.012 J-1.107 E7.26171\n"; + s += "G1 X115.348 Y148.282 E7.26918\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIPE_START\n"; + s += "M204 S10000\n"; + s += "G1 X115.664 Y148.713 F18000\n"; + s += ";WIPE_END\n"; + s += "G92 E0\n"; + s += "G10 ; retract\n"; + s += "; acceleration to travel\n"; + s += "G1 X115.662 Y148.808\n"; + s += "G1 X120.932 Y147.524\n"; + s += "G1 X121.226 Y147.362\n"; + s += "G1 X150.16 Y140.336\n"; + s += "; decel to extrusion\n"; + s += "M204 S5000\n"; + s += "G1 X156.209 Y138.866\n"; + s += "G1 X156.22 Y138.976\n"; + s += "; end travel\n"; + s += "G11 ; unretract\n"; + s += ";WIDTH:0.649924\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 F4650\n"; + s += "G1 X155.801 Y139.034 E0.02026\n"; + s += "G3 X153.702 Y138.948 I-.587 J-11.382 E.12117\n"; + s += "G3 X152.849 Y138.822 I.823 J-8.513 E.16252\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.683858\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X145.878 Y134.51 I2.171 J-11.301 E.58686\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.711771\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X143.804 Y130.663 I9.809 J-7.768 E.81894\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.74297\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X148.219 Y117.616 I10.583 J-3.69 E1.63918\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.711031\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X152.826 Y115.811 I6.908 J10.85 E1.90195\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.680045\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X154.402 Y115.729 I1.097 J5.903 E1.9816\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.643995\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G3 X157.534 Y116.615 I-.943 J9.313 E2.13698\n"; + s += "G3 X165.073 Y124.528 I-4.996 J12.307 E2.67179\n"; + s += "G1 X165.155 Y124.808 E2.68563\n"; + s += "G3 X165.6 Y127.286 I-12.334 J3.496 E2.80535\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.649924\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 X165.609 Y127.779 E2.82901\n"; + s += "G3 X163.67 Y134.419 I-11.681 J.192 E3.1657\n"; + s += "G3 X161.835 Y136.929 I-6.919 J-3.132 E3.31587\n"; + s += "G3 X156.616 Y138.963 I-6.621 J-9.277 E3.58724\n"; + s += "G1 X156.295 Y138.974 E3.60263\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIPE_START\n"; + s += "M204 S10000\n"; + s += "G1 X155.927 Y138.571 F18000\n"; + s += ";WIPE_END\n"; + s += "M204 S5000\n"; + s += "G1 X155.863 Y138.403\n"; + s += ";WIDTH:0.638248\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 F4650\n"; + s += "G1 X155.909 Y138.419 E3.60495\n"; + s += "G2 X161.549 Y136.388 I-.727 J-10.866 E3.89052\n"; + s += "G2 X163.15 Y134.126 I-4.753 J-5.062 E4.02169\n"; + s += "G2 X164.82 Y125.892 I-9.372 J-6.188 E4.42665\n"; + s += "G1 X164.74 Y125.556 E4.4429\n"; + s += "G2 X159.719 Y118.49 I-11.601 J2.927 E4.86006\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.667068\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X154.678 Y116.365 I-7.59 J10.96 E5.13167\n"; + if (move_useful) { + s += "G1 X154.511 Y116.36 E5.13992\n"; + s += "M106 S140.25\n"; + } + s += "G1 X154.256 Y116.352 E5.15251\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.707201\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X152.007 Y116.669 I.061 J8.587 E5.27203\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.741124\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X143.911 Y126.283 I2.509 J10.329 E6.01375\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.713385\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X144.261 Y129.843 I10.983 J.716 E6.20405\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.681374\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X146.03 Y133.648 I11.334 J-2.956 E6.41684\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.649924\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G2 X153.408 Y138.302 I9.116 J-6.276 E6.84676\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIDTH:0.638248\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 X153.561 Y138.322 E6.85401\n"; + s += "G2 X155.003 Y138.441 I1.621 J-10.769 E6.9221\n"; + s += "G1 X155.788 Y138.406 E6.95905\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += ";WIPE_START\n"; + s += "M204 S10000\n"; + s += "G1 X156.022 Y138.877 F18000\n"; + s += ";WIPE_END\n"; + s += "G92 E0\n"; + s += "G10 ; retract\n"; + s += "; acceleration to travel\n"; + s += "G1 X155.991 Y138.508\n"; + s += "G1 X163.054 Y127.686\n"; + s += "G1 X163.042 Y127.702\n"; + s += "; decel to extrusion\n"; + s += "M204 S500\n"; + s += "G1 X162.795 Y128.055\n"; + s += "; end travel\n"; + s += "G11 ; unretract\n"; + s += ";TYPE:Overhang perimeter\n"; + s += ";WIDTH:0.542919\n"; + s += ";HEIGHT:0.5\n"; + if(!move_useful) s += "M106 S140.25\n"; + s += "G1 F1800\n"; + s += "G3 X163.624 Y127.86 I.327 J-.467 E.10369\n"; + s += "G3 X163.258 Y128.142 I-.531 J-.312 E.1224\n"; + s += "G3 X162.86 Y128.094 I-.135 J-.555 E.13857\n"; + s += "M106 S25.5\n"; + s += "; acceleration to travel\n"; + s += "M204 S10000\n"; + s += "G1 X163.052 Y127.812 F18000\n"; + s += "; decel to extrusion\n"; + s += "M204 S5000\n"; + s += "G1 X163.2 Y127.595\n"; + s += "; end travel\n"; + s += ";TYPE:Internal perimeter\n"; + s += ";WIDTH:0.702708\n"; + s += ";HEIGHT:0.2\n"; + if(!remove_useless) s += "M106 S25.5\n"; + s += "G1 F4650\n"; + s += "G3 X163.159 Y127.523 I-.077 J-.003 E.15938\n"; + if(!remove_useless) s += "M106 S25.5\n"; + return s; + }; + + const std::string gcode = create_gcode(false, false); + //"M106 S25.5\n"; + GCodeWriter writer; + // what's used from the writer: + writer.config.gcode_flavor.value = gcfMarlinFirmware; + writer.config.gcode_comments.value = false; + writer.config.fan_percentage.value = false; // 0 -> 255 + // writer.tool[0] = nullptr; + assert(writer.tool() == nullptr); + assert(writer.get_tool(0) == nullptr); + + SECTION("disable evrything") + { + Slic3r::FanMover fan_mover(writer, + 0, // fan_speedup_time.value, + false, // with_D_option + false, // use_relative_e_distances.value, + false, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string processed_gcode = fan_mover.process_gcode(gcode, true); + std::string good_gcode = create_gcode(true, false); + //remove + REQUIRE(good_gcode == processed_gcode); + } + + SECTION("4061 bug") + { + Slic3r::FanMover fan_mover(writer, + .486, // fan_speedup_time.value, + false, // with_D_option + false, // use_relative_e_distances.value, + true, // fan_speedup_overhangs.value, + 0 // fan_kickstart.value)); + ); + std::string processed_gcode = fan_mover.process_gcode(gcode, true); + std::string good_gcode = create_gcode(true, true); + + REQUIRE(good_gcode == processed_gcode); + } +} +