Merge remote-tracking branch 'origin/master' into tm_colldetection_upgr

This commit is contained in:
tamasmeszaros 2019-03-12 15:22:00 +01:00
commit 5b7a325983
14 changed files with 316 additions and 118 deletions

View file

@ -487,7 +487,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
// starts analyzer calculations
if (m_enable_analyzer) {
BOOST_LOG_TRIVIAL(debug) << "Preparing G-code preview data";
m_analyzer.calc_gcode_preview_data(*preview_data);
m_analyzer.calc_gcode_preview_data(*preview_data, [print]() { print->throw_if_canceled(); });
m_analyzer.reset();
}

View file

@ -137,22 +137,22 @@ const std::string& GCodeAnalyzer::process_gcode(const std::string& gcode)
return m_process_output;
}
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data)
void GCodeAnalyzer::calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
{
// resets preview data
preview_data.reset();
// calculates extrusion layers
_calc_gcode_preview_extrusion_layers(preview_data);
_calc_gcode_preview_extrusion_layers(preview_data, cancel_callback);
// calculates travel
_calc_gcode_preview_travel(preview_data);
_calc_gcode_preview_travel(preview_data, cancel_callback);
// calculates retractions
_calc_gcode_preview_retractions(preview_data);
_calc_gcode_preview_retractions(preview_data, cancel_callback);
// calculates unretractions
_calc_gcode_preview_unretractions(preview_data);
_calc_gcode_preview_unretractions(preview_data, cancel_callback);
}
bool GCodeAnalyzer::is_valid_extrusion_role(ExtrusionRole role)
@ -676,7 +676,7 @@ bool GCodeAnalyzer::_is_valid_extrusion_role(int value) const
return ((int)erNone <= value) && (value <= (int)erMixed);
}
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data)
void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
{
struct Helper
{
@ -725,9 +725,18 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
GCodePreviewData::Range feedrate_range;
GCodePreviewData::Range volumetric_rate_range;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)extrude_moves->second.size() / 25;
unsigned int cancel_callback_curr = 0;
// constructs the polylines while traversing the moves
for (const GCodeMove& move : extrude_moves->second)
{
// to avoid to call the callback too often
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
if (cancel_callback_curr == 0)
cancel_callback();
if ((data != move.data) || (z != move.start_position.z()) || (position != move.start_position) || (volumetric_rate != move.data.feedrate * (float)move.data.mm3_per_mm))
{
// store current polyline
@ -769,7 +778,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
preview_data.ranges.volumetric_rate.update_from(volumetric_rate_range);
}
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
{
struct Helper
{
@ -797,9 +806,17 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
GCodePreviewData::Range width_range;
GCodePreviewData::Range feedrate_range;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)travel_moves->second.size() / 25;
unsigned int cancel_callback_curr = 0;
// constructs the polylines while traversing the moves
for (const GCodeMove& move : travel_moves->second)
{
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
if (cancel_callback_curr == 0)
cancel_callback();
GCodePreviewData::Travel::EType move_type = (move.delta_extruder < 0.0f) ? GCodePreviewData::Travel::Retract : ((move.delta_extruder > 0.0f) ? GCodePreviewData::Travel::Extrude : GCodePreviewData::Travel::Move);
GCodePreviewData::Travel::Polyline::EDirection move_direction = ((move.start_position.x() != move.end_position.x()) || (move.start_position.y() != move.end_position.y())) ? GCodePreviewData::Travel::Polyline::Generic : GCodePreviewData::Travel::Polyline::Vertical;
@ -840,28 +857,44 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(GCodePreviewData& preview_data)
preview_data.ranges.feedrate.update_from(feedrate_range);
}
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data)
void GCodeAnalyzer::_calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
{
TypeToMovesMap::iterator retraction_moves = m_moves_map.find(GCodeMove::Retract);
if (retraction_moves == m_moves_map.end())
return;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)retraction_moves->second.size() / 25;
unsigned int cancel_callback_curr = 0;
for (const GCodeMove& move : retraction_moves->second)
{
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
if (cancel_callback_curr == 0)
cancel_callback();
// store position
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
preview_data.retraction.positions.emplace_back(position, move.data.width, move.data.height);
}
}
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data)
void GCodeAnalyzer::_calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback)
{
TypeToMovesMap::iterator unretraction_moves = m_moves_map.find(GCodeMove::Unretract);
if (unretraction_moves == m_moves_map.end())
return;
// to avoid to call the callback too often
unsigned int cancel_callback_threshold = (unsigned int)unretraction_moves->second.size() / 25;
unsigned int cancel_callback_curr = 0;
for (const GCodeMove& move : unretraction_moves->second)
{
cancel_callback_curr = (cancel_callback_curr + 1) % cancel_callback_threshold;
if (cancel_callback_curr == 0)
cancel_callback();
// store position
Vec3crd position(scale_(move.start_position.x()), scale_(move.start_position.y()), scale_(move.start_position.z()));
preview_data.unretraction.positions.emplace_back(position, move.data.width, move.data.height);

View file

@ -122,7 +122,8 @@ public:
const std::string& process_gcode(const std::string& gcode);
// Calculates all data needed for gcode visualization
void calc_gcode_preview_data(GCodePreviewData& preview_data);
// throws CanceledException through print->throw_if_canceled() (sent by the caller as callback).
void calc_gcode_preview_data(GCodePreviewData& preview_data, std::function<void()> cancel_callback = std::function<void()>());
// Return an estimate of the memory consumed by the time estimator.
size_t memory_used() const;
@ -237,10 +238,11 @@ private:
// Checks if the given int is a valid extrusion role (contained into enum ExtrusionRole)
bool _is_valid_extrusion_role(int value) const;
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data);
void _calc_gcode_preview_travel(GCodePreviewData& preview_data);
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data);
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data);
// All the following methods throw CanceledException through print->throw_if_canceled() (sent by the caller as callback).
void _calc_gcode_preview_extrusion_layers(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
void _calc_gcode_preview_travel(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
void _calc_gcode_preview_retractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
void _calc_gcode_preview_unretractions(GCodePreviewData& preview_data, std::function<void()> cancel_callback);
};
} // namespace Slic3r

View file

@ -2,6 +2,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/log/trivial.hpp>
#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#ifdef WIN32
@ -88,7 +89,7 @@ static DWORD execute_process_winapi(const std::wstring &command_line)
// Run the script. If it is a perl script, run it through the bundled perl interpreter.
// If it is a batch file, run it through the cmd.exe.
// Otherwise run it directly.
static int run_script_win32(const std::string &script, const std::string &gcode)
static int run_script(const std::string &script, const std::string &gcode, std::string &/*std_err*/)
{
// Unpack the argument list provided by the user.
int nArgs;
@ -132,9 +133,46 @@ static int run_script_win32(const std::string &script, const std::string &gcode)
}
#else
#include <sys/stat.h> //for getting filesystem UID/GID
#include <unistd.h> //for getting current UID/GID
#include <boost/process.hpp>
// POSIX
#include <cstdlib> // getenv()
#include <sstream>
#include <boost/process.hpp>
namespace process = boost::process;
static int run_script(const std::string &script, const std::string &gcode, std::string &std_err)
{
// Try to obtain user's default shell
const char *shell = ::getenv("SHELL");
if (shell == nullptr) { shell = "sh"; }
// Quote and escape the gcode path argument
std::string command { script };
command.append(" '");
for (char c : gcode) {
if (c == '\'') { command.append("'\\''"); }
else { command.push_back(c); }
}
command.push_back('\'');
BOOST_LOG_TRIVIAL(debug) << boost::format("Executing script, shell: %1%, command: %2%") % shell % command;
process::ipstream istd_err;
process::child child(shell, "-c", command, process::std_err > istd_err);
std_err.clear();
std::string line;
while (child.running() && std::getline(istd_err, line)) {
std_err.append(line);
std_err.push_back('\n');
}
child.wait();
return child.exit_code();
}
#endif
namespace Slic3r {
@ -158,27 +196,15 @@ void run_post_process_scripts(const std::string &path, const PrintConfig &config
if (script.empty())
continue;
BOOST_LOG_TRIVIAL(info) << "Executing script " << script << " on file " << path;
#ifdef WIN32
int result = run_script_win32(script, gcode_file.string());
#else
//FIXME testing existence of a script is risky, as the script line may contain the script and some additional command line parameters.
// We would have to process the script line into parameters before testing for the existence of the command, the command may be looked up
// in the PATH etc.
if (! boost::filesystem::exists(boost::filesystem::path(script)))
throw std::runtime_error(std::string("The configured post-processing script does not exist: ") + script);
struct stat info;
if (stat(script.c_str(), &info))
throw std::runtime_error(std::string("Cannot read information for post-processing script: ") + script);
boost::filesystem::perms script_perms = boost::filesystem::status(script).permissions();
//if UID matches, check UID perm. else if GID matches, check GID perm. Otherwise check other perm.
if (!(script_perms & ((info.st_uid == geteuid()) ? boost::filesystem::perms::owner_exe
: ((info.st_gid == getegid()) ? boost::filesystem::perms::group_exe
: boost::filesystem::perms::others_exe))))
throw std::runtime_error(std::string("The configured post-processing script is not executable: check permissions. ") + script);
int result = boost::process::system(script, gcode_file);
if (result < 0)
BOOST_LOG_TRIVIAL(error) << "Script " << script << " on file " << path << " failed. Negative error code returned.";
#endif
std::string std_err;
const int result = run_script(script, gcode_file.string(), std_err);
if (result != 0) {
const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str()
: (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str();
BOOST_LOG_TRIVIAL(error) << msg;
throw std::runtime_error(msg);
}
}
}
}