2012-12-09 17:33:25 +00:00
|
|
|
|
use Test::More tests => 9;
|
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
|
|
BEGIN {
|
|
|
|
|
use FindBin;
|
|
|
|
|
use lib "$FindBin::Bin/../lib";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
use Slic3r;
|
|
|
|
|
use Slic3r::Geometry qw(epsilon);
|
|
|
|
|
use Slic3r::Test;
|
|
|
|
|
|
|
|
|
|
my $config = Slic3r::Config->new_from_defaults;
|
|
|
|
|
|
|
|
|
|
# tolerance, in minutes
|
|
|
|
|
# (our time estimation differs from the internal one because of decimals truncation)
|
2014-12-21 11:39:19 +00:00
|
|
|
|
my $epsilon = 0.003;
|
2012-12-09 17:33:25 +00:00
|
|
|
|
|
|
|
|
|
my $test = sub {
|
|
|
|
|
my ($conf) = @_;
|
|
|
|
|
$conf ||= $config;
|
|
|
|
|
|
|
|
|
|
my $print = Slic3r::Test::init_print('2x20x10', config => $conf);
|
|
|
|
|
|
|
|
|
|
my $min_time = 1 / ($conf->vibration_limit * 60); # minimum time between direction changes in minutes
|
|
|
|
|
my %dir = (X => 0, Y => 0);
|
|
|
|
|
my %dir_time = (X => 0, Y => 0);
|
|
|
|
|
my %dir_sleep_time = (X => 0, Y => 0);
|
|
|
|
|
my $last_cmd_pause = 0;
|
2013-08-28 14:51:58 +00:00
|
|
|
|
Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub {
|
2012-12-09 17:33:25 +00:00
|
|
|
|
my ($self, $cmd, $args, $info) = @_;
|
|
|
|
|
|
|
|
|
|
if ($cmd !~ /^G[01]$/) {
|
|
|
|
|
if ($cmd eq 'G4') {
|
|
|
|
|
$last_cmd_pause = (($args->{P} // 0) / 1000 + ($args->{S} // 0)) / 60; # in minutes
|
|
|
|
|
$dir_sleep_time{$_} += $last_cmd_pause for qw(X Y);
|
|
|
|
|
$last_cmd_pause -= $epsilon; # error builds up
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Z moves are slow enough that we can consider any vibration interrupted
|
|
|
|
|
if ($info->{dist_Z}) {
|
|
|
|
|
$dir_time{$_} += 99999 for qw(X Y);
|
|
|
|
|
$last_cmd_pause = 0;
|
|
|
|
|
return;
|
|
|
|
|
} elsif ($info->{dist_E} != 0 && $info->{dist_XY} == 0) {
|
|
|
|
|
my $time = abs($info->{dist_E}) / ($args->{F} // $self->F); # in minutes
|
|
|
|
|
$dir_time{$_} += $time for qw(X Y);
|
|
|
|
|
$last_cmd_pause = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# compute move time (this assumes that the speed is XY-bound, which happens very likely)
|
|
|
|
|
my $time = abs($info->{dist_XY}) / ($args->{F} // $self->F); # in minutes
|
|
|
|
|
|
|
|
|
|
my $one_axis_would_trigger_limit_without_pause = 0;
|
|
|
|
|
foreach my $axis (qw(X Y)) {
|
|
|
|
|
# are we changing direction on this axis?
|
2013-08-28 16:12:20 +00:00
|
|
|
|
my $dir = $info->{"dist_$axis"} <=> ($args->{$axis} // $self->$axis);
|
2012-12-09 17:33:25 +00:00
|
|
|
|
if ($dir != 0 && $dir{$axis} != $dir) {
|
|
|
|
|
# this move changes direction on this axis
|
|
|
|
|
if ($dir{$axis} != 0) {
|
|
|
|
|
if (($dir_time{$axis} + $dir_sleep_time{$axis}) < ($min_time - $epsilon)) {
|
|
|
|
|
fail 'vibration limit exceeded';
|
|
|
|
|
}
|
|
|
|
|
$one_axis_would_trigger_limit_without_pause = 1
|
|
|
|
|
if ($dir_time{$axis} - $last_cmd_pause) < $min_time;
|
|
|
|
|
}
|
|
|
|
|
$dir{$axis} = $dir;
|
|
|
|
|
$dir_time{$axis} = 0;
|
|
|
|
|
$dir_sleep_time{$axis} = 0;
|
|
|
|
|
}
|
|
|
|
|
$dir_time{$axis} += $time;
|
|
|
|
|
}
|
|
|
|
|
fail 'no unnecessary pauses are added'
|
|
|
|
|
if $last_cmd_pause > $epsilon && !$one_axis_would_trigger_limit_without_pause;
|
|
|
|
|
|
|
|
|
|
$last_cmd_pause = 0;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$config->set('gcode_comments', 1);
|
|
|
|
|
$config->set('perimeters', 1);
|
|
|
|
|
foreach my $frequency (5, 10, 15) {
|
|
|
|
|
foreach my $gapfillspeed (20, 50, 100) {
|
|
|
|
|
$config->set('vibration_limit', $frequency);
|
|
|
|
|
ok $test->(), "vibrations limited to ${frequency}Hz (gap fill speed = ${gapfillspeed} mm/s)";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__END__
|