Refactoring: moved most of the low-level G-code to the Slic3r::GCode::Base class. Cleanup of the retraction and wipe logic.

This commit is contained in:
Alessandro Ranellucci 2014-10-21 20:16:45 +02:00
parent 33edda0a69
commit 167df0ab87
11 changed files with 403 additions and 177 deletions

View file

@ -2,6 +2,7 @@ package Slic3r::GCode::Base;
use Moo;
use List::Util qw(min max first);
use Slic3r::Geometry qw(X Y epsilon);
has 'gcode_config' => (is => 'ro', default => sub { Slic3r::Config::GCode->new });
has '_extrusion_axis' => (is => 'rw', default => sub { 'E' });
@ -10,6 +11,8 @@ has '_extruder' => (is => 'rw');
has '_multiple_extruders' => (is => 'rw', default => sub { 0 });
has '_last_acceleration' => (is => 'rw', default => sub { 0 });
has '_last_fan_speed' => (is => 'rw', default => sub { 0 });
has '_lifted' => (is => 'rw', default => sub { 0 });
has '_pos' => (is => 'rw', default => sub { Slic3r::Pointf3->new });
sub apply_print_config {
my ($self, $print_config) = @_;
@ -105,6 +108,15 @@ sub set_acceleration {
$acceleration, ($self->gcode_config->gcode_comments ? ' ; adjust acceleration' : '');
}
sub update_progress {
my ($self, $percent) = @_;
return "" if $self->gcode_config->gcode_flavor !~ /^(?:makerware|sailfish)$/;
return sprintf "M73 P%s%s\n",
int($percent),
$self->_comment('update progress');
}
sub need_toolchange {
my ($self, $extruder_id) = @_;
@ -138,17 +150,21 @@ sub _toolchange {
$extruder_id,
($self->gcode_config->gcode_comments ? ' ; change extruder' : '');
$gcode .= $self->reset_e;
$gcode .= $self->reset_e(1);
}
return $gcode;
}
sub reset_e {
my ($self) = @_;
my ($self, $force) = @_;
return "" if $self->config->gcode_flavor =~ /^(?:mach3|makerware|sailfish)$/;
$self->_extruder->set_E(0) if $self->_extruder;
if (defined $self->_extruder) {
return "" if $self->_extruder->E == 0 && !$force;
$self->_extruder->set_E(0) if $self->_extruder;
}
if ($self->_extrusion_axis ne '' && !$self->gcode_config->use_relative_e_distances) {
return sprintf "G92 %s0%s\n", $self->gcode_config->extrusion_axis, ($self->config->gcode_comments ? ' ; reset extrusion distance' : '');
} else {
@ -156,6 +172,224 @@ sub reset_e {
}
}
sub _comment {
my ($self, $comment) = @_;
return "" if (!defined $comment) || ($comment eq '') || !$self->config->gcode_comments;
return " ; $comment";
}
sub set_speed {
my ($self, $F, $comment) = @_;
return sprintf "G1 F%.3f%s\n",
$F,
$self->_comment($comment);
}
sub travel_to_xy {
my ($self, $pointf, $comment) = @_;
$self->_pos->set_x($pointf->x);
$self->_pos->set_y($pointf->y); # ))
return sprintf "G1 X%.3f Y%.3f F%.3f%s\n",
@$pointf,
$self->gcode_config->travel_speed*60,
$self->_comment($comment);
}
sub travel_to_xyz {
my ($self, $pointf3, $comment) = @_;
# If target Z is lower than current Z but higher than nominal Z we
# don't perform the Z move but we only move in the XY plane and
# adjust the nominal Z by reducing the lift amount that will be
# used for unlift.
if (!$self->will_move_z($pointf3->z)) {
my $nominal_z = $self->_pos->z - $self->_lifted;
$self->_lifted($self->_lifted - ($pointf3->z - $nominal_z));
return $self->travel_to_xy(Slic3r::Pointf->new(@$pointf3[X,Y]));
}
# In all the other cases, we perform an actual XYZ move and cancel
# the lift.
$self->_lifted(0);
return $self->_travel_to_xyz($pointf3, $comment);
}
sub _travel_to_xyz {
my ($self, $pointf3, $comment) = @_;
$self->_pos($pointf3);
return sprintf "G1 X%.3f Y%.3f Z%.3f F%.3f%s\n",
@$pointf3,
$self->gcode_config->travel_speed*60,
$self->_comment($comment);
}
sub travel_to_z {
my ($self, $z, $comment) = @_;
# If target Z is lower than current Z but higher than nominal Z
# we don't perform the move but we only adjust the nominal Z by
# reducing the lift amount that will be used for unlift.
if (!$self->will_move_z($z)) {
my $nominal_z = $self->_pos->z - $self->_lifted;
$self->_lifted($self->_lifted - ($z - $nominal_z));
return "";
}
# In all the other cases, we perform an actual Z move and cancel
# the lift.
$self->_lifted(0);
return $self->_travel_to_z($z, $comment);
}
sub _travel_to_z {
my ($self, $z, $comment) = @_;
$self->_pos->set_z($z);
return sprintf "G1 Z%.3f F%.3f%s\n",
$z,
$self->gcode_config->travel_speed*60,
$self->_comment($comment);
}
sub will_move_z {
my ($self, $z) = @_;
# If target Z is lower than current Z but higher than nominal Z
# we don't perform an actual Z move.
if ($self->_lifted > 0) {
my $nominal_z = $self->_pos->z - $self->_lifted;
if ($z >= $nominal_z && $z <= $self->_pos->z) {
return 0;
}
}
return 1;
}
sub extrude_to_xy {
my ($self, $pointf, $dE, $comment) = @_;
$self->_pos->set_x($pointf->x);
$self->_pos->set_y($pointf->y); # ))
$self->_extruder->extrude($dE);
return sprintf "G1 X%.3f Y%.3f %s%.5f%s\n",
@$pointf,
$self->_extrusion_axis,
$self->_extruder->E,
$self->_comment($comment);
}
sub extrude_to_xyz {
my ($self, $pointf3, $dE, $comment) = @_;
$self->_pos($pointf3);
$self->_lifted(0);
$self->_extruder->extrude($dE);
return sprintf "G1 X%.3f Y%.3f Z%.3f %s%.5f%s\n",
@$pointf3,
$self->_extrusion_axis,
$self->_extruder->E,
$self->_comment($comment);
}
sub retract {
my ($self) = @_;
return $self->_retract(
$self->_extruder->retract_length,
$self->_extruder->retract_restart_extra,
'retract',
);
}
sub retract_for_toolchange {
my ($self) = @_;
return $self->_retract(
$self->_extruder->retract_length_toolchange,
$self->_extruder->retract_restart_extra_toolchange,
'retract for toolchange',
);
}
sub _retract {
my ($self, $length, $restart_extra, $comment) = @_;
if ($self->gcode_config->use_firmware_retraction) {
return "G10 ; retract\n";
}
my $gcode = "";
my $dE = $self->_extruder->retract($length, $restart_extra);
if ($dE != 0) {
$gcode = sprintf "G1 %s%.5f F%.3f%s\n",
$self->_extrusion_axis,
$self->_extruder->E,
$self->_extruder->retract_speed_mm_min,
$self->_comment($comment . " dE = $dE");
}
$gcode .= "M103 ; extruder off\n"
if $self->gcode_config->gcode_flavor eq 'makerware';
return $gcode;
}
sub unretract {
my ($self, $comment) = @_;
my $gcode = "";
$gcode .= "M101 ; extruder on\n"
if $self->gcode_config->gcode_flavor eq 'makerware';
if ($self->gcode_config->use_firmware_retraction) {
$gcode .= "G11 ; unretract\n";
$gcode .= $self->reset_e;
return $gcode;
}
my $dE = $self->_extruder->unretract;
if ($dE != 0) {
# use G1 instead of G0 because G0 will blend the restart with the previous travel move
$gcode .= sprintf "G1 %s%.5f F%.3f%s\n",
$self->_extrusion_axis,
$self->_extruder->E,
$self->_extruder->retract_speed_mm_min,
$self->_comment($comment);
}
return $gcode;
}
# If this method is called more than once before calling unlift(),
# it will not perform subsequent lifts, even if Z was raised manually
# (i.e. with travel_to_z()) and thus _lifted was reduced.
sub lift {
my ($self) = @_;
if ($self->_lifted == 0 && $self->gcode_config->retract_lift->[0] > 0) {
my $to_lift = $self->gcode_config->retract_lift->[0];
$self->_lifted($to_lift);
return $self->_travel_to_z($self->_pos->z + $to_lift, 'lift Z');
}
return "";
}
sub unlift {
my ($self) = @_;
my $gcode = "";
if ($self->_lifted > 0) {
$gcode .= $self->_travel_to_z($self->_pos->z - $self->_lifted, 'restore layer Z');
$self->_lifted(0);
}
return $gcode;
}
sub has_multiple_extruders {
my ($self) = @_;
return $self->_multiple_extruders;