SPE-1872: Implemented G2/G3 lines discretization for gcfMarlinFirmware firmware flavour

This commit is contained in:
enricoturri1966 2024-02-15 13:44:42 +01:00 committed by Lukas Matena
parent ebc7444a20
commit 5c4c18661e
2 changed files with 144 additions and 69 deletions

View File

@ -3341,6 +3341,77 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
process_G1(g1_axes, g1_feedrate, G1DiscretizationOrigin::G2G3, remaining_internal_g1_lines); process_G1(g1_axes, g1_feedrate, G1DiscretizationOrigin::G2G3, remaining_internal_g1_lines);
}; };
#if ENABLE_ET_SPE1872_FIRMWARE_BUDDY_G2G3
if (m_flavor == gcfMarlinFirmware) {
// calculate arc segments
// reference:
// Prusa-Firmware-Buddy\lib\Marlin\Marlin\src\gcode\motion\G2_G3.cpp - plan_arc()
// https://github.com/prusa3d/Prusa-Firmware-Buddy-Private/blob/private/lib/Marlin/Marlin/src/gcode/motion/G2_G3.cpp
static const float MAX_ARC_DEVIATION = 0.02f;
static const float MIN_ARC_SEGMENTS_PER_SEC = 50;
static const float MIN_ARC_SEGMENT_MM = 0.1f;
static const float MAX_ARC_SEGMENT_MM = 2.0f;
const float feedrate_mm_s = feedrate.has_value() ? *feedrate : m_feedrate;
const float radius_mm = rel_center.norm();
const float segment_mm = std::clamp(std::min(std::sqrt(8.0f * radius_mm * MAX_ARC_DEVIATION), feedrate_mm_s * (1.0f / MIN_ARC_SEGMENTS_PER_SEC)), MIN_ARC_SEGMENT_MM, MAX_ARC_SEGMENT_MM);
const float flat_mm = radius_mm * std::abs(arc.angle);
const size_t segments = std::max<size_t>(flat_mm / segment_mm + 0.8f, 1);
AxisCoords prev_target = m_start_position;
if (segments > 1) {
const float inv_segments = 1.0f / static_cast<float>(segments);
const float theta_per_segment = static_cast<float>(arc.angle) * inv_segments;
const float cos_T = cos(theta_per_segment);
const float sin_T = sin(theta_per_segment);
const float z_per_segment = arc.delta_z() * inv_segments;
const float extruder_per_segment = (extrusion.has_value()) ? *extrusion * inv_segments : 0.0f;
static const size_t N_ARC_CORRECTION = 25;
size_t arc_recalc_count = N_ARC_CORRECTION;
Vec2f rvec(-rel_center.x(), -rel_center.y());
AxisCoords arc_target = { 0.0f, 0.0f, m_start_position[Z], m_start_position[E] };
for (size_t i = 1; i < segments; ++i) {
if (--arc_recalc_count) {
// Apply vector rotation matrix to previous rvec.a / 1
const float r_new_Y = rvec.x() * sin_T + rvec.y() * cos_T;
rvec.x() = rvec.x() * cos_T - rvec.y() * sin_T;
rvec.y() = r_new_Y;
}
else {
arc_recalc_count = N_ARC_CORRECTION;
// Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments.
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
// To reduce stuttering, the sin and cos could be computed at different times.
// For now, compute both at the same time.
const float Ti = i * theta_per_segment;
const float cos_Ti = cos(Ti);
const float sin_Ti = sin(Ti);
rvec.x() = -rel_center.x() * cos_Ti + rel_center.y() * sin_Ti;
rvec.y() = -rel_center.x() * sin_Ti - rel_center.y() * cos_Ti;
}
// Update arc_target location
arc_target[X] = arc.center.x() + rvec.x();
arc_target[Y] = arc.center.y() + rvec.y();
arc_target[Z] += z_per_segment;
arc_target[E] += extruder_per_segment;
m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
internal_only_g1_line(adjust_target(arc_target, prev_target), z_per_segment != 0.0, (i == 1) ? feedrate : std::nullopt,
extrusion, segments - i);
prev_target = arc_target;
}
}
// Ensure last segment arrives at target location.
m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, (segments == 1) ? feedrate : std::nullopt, extrusion);
}
else {
#endif // ENABLE_ET_SPE1872_FIRMWARE_BUDDY_G2G3
// calculate arc segments // calculate arc segments
// reference: // reference:
// Prusa-Firmware\Firmware\motion_control.cpp - mc_arc() // Prusa-Firmware\Firmware\motion_control.cpp - mc_arc()
@ -3434,6 +3505,9 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line, bool cloc
// Ensure last segment arrives at target location. // Ensure last segment arrives at target location.
m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line() m_start_position = m_end_position; // this is required because we are skipping the call to process_gcode_line()
internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, (segments == 1) ? feedrate : std::nullopt, extrusion); internal_only_g1_line(adjust_target(end_position, prev_target), arc.delta_z() != 0.0, (segments == 1) ? feedrate : std::nullopt, extrusion);
#if ENABLE_ET_SPE1872_FIRMWARE_BUDDY_G2G3
}
#endif // ENABLE_ET_SPE1872_FIRMWARE_BUDDY_G2G3
} }
void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line) void GCodeProcessor::process_G10(const GCodeReader::GCodeLine& line)

View File

@ -65,6 +65,7 @@
// requires VGCODE_ENABLE_ET_SPE1872 set to 1 in libvgcode (Types.hpp) // requires VGCODE_ENABLE_ET_SPE1872 set to 1 in libvgcode (Types.hpp)
#define ENABLE_ET_SPE1872 (1 && ENABLE_NEW_GCODE_VIEWER) #define ENABLE_ET_SPE1872 (1 && ENABLE_NEW_GCODE_VIEWER)
#define ENABLE_ET_SPE1872_FIRMWARE_BUDDY (1 && ENABLE_ET_SPE1872) #define ENABLE_ET_SPE1872_FIRMWARE_BUDDY (1 && ENABLE_ET_SPE1872)
#define ENABLE_ET_SPE1872_FIRMWARE_BUDDY_G2G3 (1 && ENABLE_ET_SPE1872_FIRMWARE_BUDDY)
#define ENABLE_ET_SPE1872_FIRMWARE_G2G3 (1 && ENABLE_ET_SPE1872) #define ENABLE_ET_SPE1872_FIRMWARE_G2G3 (1 && ENABLE_ET_SPE1872)
#define ENABLE_ET_SPE1872_DEBUG (1 && ENABLE_ET_SPE1872) #define ENABLE_ET_SPE1872_DEBUG (1 && ENABLE_ET_SPE1872)