retraction.t 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. use Test::More tests => 16;
  2. use strict;
  3. use warnings;
  4. BEGIN {
  5. use FindBin;
  6. use lib "$FindBin::Bin/../lib";
  7. }
  8. use Slic3r;
  9. use Slic3r::Test qw(_eq);
  10. my $config = Slic3r::Config->new_from_defaults;
  11. my $duplicate = 1;
  12. my $test = sub {
  13. my ($conf) = @_;
  14. $conf ||= $config;
  15. my $print = Slic3r::Test::init_print('20mm_cube', config => $conf, duplicate => $duplicate);
  16. my $tool = 0;
  17. my @toolchange_count = (); # track first usages so that we don't expect retract_length_toolchange when extruders are used for the first time
  18. my @retracted = (1); # ignore the first travel move from home to first point
  19. my @retracted_length = (0);
  20. my $lifted = 0;
  21. my $changed_tool = 0;
  22. my $wait_for_toolchange = 0;
  23. Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
  24. my ($self, $cmd, $args, $info) = @_;
  25. if ($cmd =~ /^T(\d+)/) {
  26. $tool = $1;
  27. $changed_tool = 1;
  28. $wait_for_toolchange = 0;
  29. $toolchange_count[$tool] //= 0;
  30. $toolchange_count[$tool]++;
  31. } elsif ($cmd =~ /^G[01]$/ && !$args->{Z}) { # ignore lift taking place after retraction
  32. fail 'toolchange happens right after retraction' if $wait_for_toolchange;
  33. }
  34. if ($info->{dist_Z}) {
  35. # lift move or lift + change layer
  36. if (_eq($info->{dist_Z}, $print->config->get_at('retract_lift', $tool))
  37. || (_eq($info->{dist_Z}, $conf->layer_height + $print->config->get_at('retract_lift', $tool)) && $print->config->get_at('retract_lift', $tool) > 0)) {
  38. fail 'only lifting while retracted' if !$retracted[$tool] && !($conf->g0 && $info->{retracting});
  39. fail 'double lift' if $lifted;
  40. $lifted = 1;
  41. }
  42. if ($info->{dist_Z} < 0) {
  43. fail 'going down only after lifting' if !$lifted;
  44. fail 'going down by the same amount of the lift or by the amount needed to get to next layer'
  45. if !_eq($info->{dist_Z}, -$print->config->get_at('retract_lift', $tool))
  46. && !_eq($info->{dist_Z}, -$print->config->get_at('retract_lift', $tool) + $conf->layer_height);
  47. $lifted = 0;
  48. }
  49. fail 'move Z at travel speed' if ($args->{F} // $self->F) != $conf->travel_speed * 60;
  50. }
  51. if ($info->{retracting}) {
  52. $retracted[$tool] = 1;
  53. $retracted_length[$tool] += -$info->{dist_E};
  54. if (_eq($retracted_length[$tool], $print->config->get_at('retract_length', $tool))) {
  55. # okay
  56. } elsif (_eq($retracted_length[$tool], $print->config->get_at('retract_length_toolchange', $tool))) {
  57. $wait_for_toolchange = 1;
  58. } else {
  59. fail 'retracted by the correct amount';
  60. }
  61. fail 'combining retraction and travel with G0'
  62. if $cmd ne 'G0' && $conf->g0 && ($info->{dist_Z} || $info->{dist_XY});
  63. }
  64. if ($info->{extruding}) {
  65. fail 'only extruding while not lifted' if $lifted;
  66. if ($retracted[$tool]) {
  67. my $expected_amount = $retracted_length[$tool] + $print->config->get_at('retract_restart_extra', $tool);
  68. if ($changed_tool && $toolchange_count[$tool] > 1) {
  69. $expected_amount = $print->config->get_at('retract_length_toolchange', $tool) + $print->config->get_at('retract_restart_extra_toolchange', $tool);
  70. $changed_tool = 0;
  71. }
  72. fail 'unretracted by the correct amount'
  73. if !_eq($info->{dist_E}, $expected_amount);
  74. $retracted[$tool] = 0;
  75. $retracted_length[$tool] = 0;
  76. }
  77. }
  78. if ($info->{travel} && $info->{dist_XY} >= $print->config->get_at('retract_before_travel', $tool)) {
  79. fail 'retracted before long travel move' if !$retracted[$tool];
  80. }
  81. });
  82. 1;
  83. };
  84. $config->set('first_layer_height', $config->layer_height);
  85. $config->set('first_layer_speed', '100%');
  86. $config->set('start_gcode', ''); # to avoid dealing with the nozzle lift in start G-code
  87. $config->set('retract_length', [1.5]);
  88. $config->set('retract_before_travel', [3]);
  89. $config->set('only_retract_when_crossing_perimeters', 0);
  90. my $retract_tests = sub {
  91. my ($descr) = @_;
  92. ok $test->(), "retraction$descr";
  93. my $conf = $config->clone;
  94. $conf->set('retract_restart_extra', [1]);
  95. ok $test->($conf), "restart extra length$descr";
  96. $conf->set('retract_restart_extra', [-1]);
  97. ok $test->($conf), "negative restart extra length$descr";
  98. $conf->set('retract_lift', [1]);
  99. ok $test->($conf), "lift$descr";
  100. };
  101. $retract_tests->('');
  102. $duplicate = 2;
  103. $retract_tests->(' (duplicate)');
  104. $config->set('g0', 1);
  105. $retract_tests->(' (G0 and duplicate)');
  106. $duplicate = 1;
  107. $config->set('g0', 0);
  108. $config->set('infill_extruder', 2);
  109. $config->set('skirts', 4);
  110. $config->set('skirt_height', 3);
  111. $retract_tests->(' (dual extruder with multiple skirt layers)');
  112. __END__