retraction.t 5.0 KB

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