Skip to content

Commit

Permalink
Merge pull request #4389 from thinkyhead/rc_optimize_planner
Browse files Browse the repository at this point in the history
Optimize planner with precalculation, etc.
  • Loading branch information
thinkyhead authored Jul 25, 2016
2 parents 6900bb2 + d8f2876 commit b7b7c90
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 83 deletions.
43 changes: 22 additions & 21 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,20 @@ static void report_current_position();
print_xyz(PSTR(STRINGIFY(VAR) "="), PSTR(" : " SUFFIX "\n"), VAR); } while(0)
#endif

/**
* sync_plan_position
* Set planner / stepper positions to the cartesian current_position.
* The stepper code translates these coordinates into step units.
* Allows translation between steps and millimeters for cartesian & core robots
*/
inline void sync_plan_position() {
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", current_position);
#endif
planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); }

#if ENABLED(DELTA) || ENABLED(SCARA)
inline void sync_plan_position_delta() {
#if ENABLED(DEBUG_LEVELING_FEATURE)
Expand Down Expand Up @@ -897,16 +911,15 @@ void setup() {
// Send "ok" after commands by default
for (int8_t i = 0; i < BUFSIZE; i++) send_ok[i] = true;

// loads data from EEPROM if available else uses defaults (and resets step acceleration rate)
// Load data from EEPROM if available (or use defaults)
// This also updates variables in the planner, elsewhere
Config_RetrieveSettings();

// Initialize current position based on home_offset
memcpy(current_position, home_offset, sizeof(home_offset));

#if ENABLED(DELTA) || ENABLED(SCARA)
// Vital to init kinematic equivalent for X0 Y0 Z0
SYNC_PLAN_POSITION_KINEMATIC();
#endif
// Vital to init stepper/planner equivalent for current_position
SYNC_PLAN_POSITION_KINEMATIC();

thermalManager.init(); // Initialize temperature loop

Expand Down Expand Up @@ -1319,7 +1332,7 @@ inline bool code_value_bool() { return code_value_byte() > 0; }
case TEMPUNIT_C:
return code_value_float();
case TEMPUNIT_F:
return (code_value_float() - 32) / 1.8;
return (code_value_float() - 32) * 0.5555555556;
case TEMPUNIT_K:
return code_value_float() - 272.15;
default:
Expand All @@ -1333,7 +1346,7 @@ inline bool code_value_bool() { return code_value_byte() > 0; }
case TEMPUNIT_K:
return code_value_float();
case TEMPUNIT_F:
return code_value_float() / 1.8;
return code_value_float() * 0.5555555556;
default:
return code_value_float();
}
Expand Down Expand Up @@ -1627,19 +1640,6 @@ inline void line_to_destination(float fr_mm_m) {
}
inline void line_to_destination() { line_to_destination(feedrate_mm_m); }

/**
* sync_plan_position
* Set planner / stepper positions to the cartesian current_position.
* The stepper code translates these coordinates into step units.
* Allows translation between steps and millimeters for cartesian & core robots
*/
inline void sync_plan_position() {
#if ENABLED(DEBUG_LEVELING_FEATURE)
if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", current_position);
#endif
planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
}
inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); }
inline void set_current_to_destination() { memcpy(current_position, destination, sizeof(current_position)); }
inline void set_destination_to_current() { memcpy(destination, current_position, sizeof(destination)); }

Expand Down Expand Up @@ -5147,6 +5147,7 @@ inline void gcode_M92() {
}
}
}
planner.refresh_positioning();
}

/**
Expand Down Expand Up @@ -6140,7 +6141,7 @@ inline void gcode_M428() {
bool err = false;
LOOP_XYZ(i) {
if (axis_homed[i]) {
float base = (current_position[i] > (sw_endstop_min[i] + sw_endstop_max[i]) / 2) ? base_home_pos(i) : 0,
float base = (current_position[i] > (sw_endstop_min[i] + sw_endstop_max[i]) * 0.5) ? base_home_pos(i) : 0,
diff = current_position[i] - LOGICAL_POSITION(base, i);
if (diff > -20 && diff < 20) {
set_home_offset((AxisEnum)i, home_offset[i] - diff);
Expand Down
6 changes: 6 additions & 0 deletions Marlin/configuration_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,16 @@ void Config_Postprocess() {
// steps per s2 needs to be updated to agree with units per s2
planner.reset_acceleration_rates();

// Make sure delta kinematics are updated before refreshing the
// planner position so the stepper counts will be set correctly.
#if ENABLED(DELTA)
recalc_delta_settings(delta_radius, delta_diagonal_rod);
#endif

// Refresh steps_to_mm with the reciprocal of axis_steps_per_mm
// and init stepper.count[], planner.position[] with current_position
planner.refresh_positioning();

#if ENABLED(PIDTEMP)
thermalManager.updatePID();
#endif
Expand Down
111 changes: 67 additions & 44 deletions Marlin/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,39 +80,40 @@ block_t Planner::block_buffer[BLOCK_BUFFER_SIZE];
volatile uint8_t Planner::block_buffer_head = 0; // Index of the next block to be pushed
volatile uint8_t Planner::block_buffer_tail = 0;

float Planner::max_feedrate_mm_s[NUM_AXIS]; // Max speeds in mm per second
float Planner::axis_steps_per_mm[NUM_AXIS];
unsigned long Planner::max_acceleration_steps_per_s2[NUM_AXIS];
unsigned long Planner::max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software
float Planner::max_feedrate_mm_s[NUM_AXIS], // Max speeds in mm per second
Planner::axis_steps_per_mm[NUM_AXIS],
Planner::steps_to_mm[NUM_AXIS];

unsigned long Planner::max_acceleration_steps_per_s2[NUM_AXIS],
Planner::max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software

millis_t Planner::min_segment_time;
float Planner::min_feedrate_mm_s;
float Planner::acceleration; // Normal acceleration mm/s^2 DEFAULT ACCELERATION for all printing moves. M204 SXXXX
float Planner::retract_acceleration; // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX
float Planner::travel_acceleration; // Travel acceleration mm/s^2 DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
float Planner::max_xy_jerk; // The largest speed change requiring no acceleration
float Planner::max_z_jerk;
float Planner::max_e_jerk;
float Planner::min_travel_feedrate_mm_s;
float Planner::min_feedrate_mm_s,
Planner::acceleration, // Normal acceleration mm/s^2 DEFAULT ACCELERATION for all printing moves. M204 SXXXX
Planner::retract_acceleration, // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX
Planner::travel_acceleration, // Travel acceleration mm/s^2 DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
Planner::max_xy_jerk, // The largest speed change requiring no acceleration
Planner::max_z_jerk,
Planner::max_e_jerk,
Planner::min_travel_feedrate_mm_s;

#if ENABLED(AUTO_BED_LEVELING_FEATURE)
matrix_3x3 Planner::bed_level_matrix; // Transform to compensate for bed level
#endif

#if ENABLED(AUTOTEMP)
float Planner::autotemp_max = 250;
float Planner::autotemp_min = 210;
float Planner::autotemp_factor = 0.1;
float Planner::autotemp_max = 250,
Planner::autotemp_min = 210,
Planner::autotemp_factor = 0.1;
bool Planner::autotemp_enabled = false;
#endif

// private:

long Planner::position[NUM_AXIS] = { 0 };

float Planner::previous_speed[NUM_AXIS];

float Planner::previous_nominal_speed;
float Planner::previous_speed[NUM_AXIS],
Planner::previous_nominal_speed;

#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
uint8_t Planner::g_uc_extruder_last_move[EXTRUDERS] = { 0 };
Expand Down Expand Up @@ -783,31 +784,37 @@ void Planner::check_axes_activity() {
#if ENABLED(COREXY) || ENABLED(COREXZ) || ENABLED(COREYZ)
float delta_mm[6];
#if ENABLED(COREXY)
delta_mm[X_HEAD] = dx / axis_steps_per_mm[A_AXIS];
delta_mm[Y_HEAD] = dy / axis_steps_per_mm[B_AXIS];
delta_mm[Z_AXIS] = dz / axis_steps_per_mm[Z_AXIS];
delta_mm[A_AXIS] = (dx + dy) / axis_steps_per_mm[A_AXIS];
delta_mm[B_AXIS] = (dx - dy) / axis_steps_per_mm[B_AXIS];
delta_mm[X_HEAD] = dx * steps_to_mm[A_AXIS];
delta_mm[Y_HEAD] = dy * steps_to_mm[B_AXIS];
delta_mm[Z_AXIS] = dz * steps_to_mm[Z_AXIS];
delta_mm[A_AXIS] = (dx + dy) * steps_to_mm[A_AXIS];
delta_mm[B_AXIS] = (dx - dy) * steps_to_mm[B_AXIS];
#elif ENABLED(COREXZ)
delta_mm[X_HEAD] = dx / axis_steps_per_mm[A_AXIS];
delta_mm[Y_AXIS] = dy / axis_steps_per_mm[Y_AXIS];
delta_mm[Z_HEAD] = dz / axis_steps_per_mm[C_AXIS];
delta_mm[A_AXIS] = (dx + dz) / axis_steps_per_mm[A_AXIS];
delta_mm[C_AXIS] = (dx - dz) / axis_steps_per_mm[C_AXIS];
delta_mm[X_HEAD] = dx * steps_to_mm[A_AXIS];
delta_mm[Y_AXIS] = dy * steps_to_mm[Y_AXIS];
delta_mm[Z_HEAD] = dz * steps_to_mm[C_AXIS];
delta_mm[A_AXIS] = (dx + dz) * steps_to_mm[A_AXIS];
delta_mm[C_AXIS] = (dx - dz) * steps_to_mm[C_AXIS];
#elif ENABLED(COREYZ)
delta_mm[X_AXIS] = dx / axis_steps_per_mm[A_AXIS];
delta_mm[Y_HEAD] = dy / axis_steps_per_mm[Y_AXIS];
delta_mm[Z_HEAD] = dz / axis_steps_per_mm[C_AXIS];
delta_mm[B_AXIS] = (dy + dz) / axis_steps_per_mm[B_AXIS];
delta_mm[C_AXIS] = (dy - dz) / axis_steps_per_mm[C_AXIS];
delta_mm[X_AXIS] = dx * steps_to_mm[X_AXIS];
delta_mm[Y_HEAD] = dy * steps_to_mm[B_AXIS];
delta_mm[Z_HEAD] = dz * steps_to_mm[C_AXIS];
delta_mm[B_AXIS] = (dy + dz) * steps_to_mm[B_AXIS];
delta_mm[C_AXIS] = (dy - dz) * steps_to_mm[C_AXIS];
#endif
#else
float delta_mm[4];
delta_mm[X_AXIS] = dx / axis_steps_per_mm[X_AXIS];
delta_mm[Y_AXIS] = dy / axis_steps_per_mm[Y_AXIS];
delta_mm[Z_AXIS] = dz / axis_steps_per_mm[Z_AXIS];
#if ENABLED(DELTA)
// On delta all axes (should!) have the same steps-per-mm
// so calculate distance in steps first, then do one division
// at the end to get millimeters
#else
delta_mm[X_AXIS] = dx * steps_to_mm[X_AXIS];
delta_mm[Y_AXIS] = dy * steps_to_mm[Y_AXIS];
delta_mm[Z_AXIS] = dz * steps_to_mm[Z_AXIS];
#endif
#endif
delta_mm[E_AXIS] = (de / axis_steps_per_mm[E_AXIS]) * volumetric_multiplier[extruder] * extruder_multiplier[extruder] / 100.0;
delta_mm[E_AXIS] = 0.01 * (de * steps_to_mm[E_AXIS]) * volumetric_multiplier[extruder] * extruder_multiplier[extruder];

if (block->steps[X_AXIS] <= dropsegments && block->steps[Y_AXIS] <= dropsegments && block->steps[Z_AXIS] <= dropsegments) {
block->millimeters = fabs(delta_mm[E_AXIS]);
Expand All @@ -820,10 +827,16 @@ void Planner::check_axes_activity() {
sq(delta_mm[X_HEAD]) + sq(delta_mm[Y_AXIS]) + sq(delta_mm[Z_HEAD])
#elif ENABLED(COREYZ)
sq(delta_mm[X_AXIS]) + sq(delta_mm[Y_HEAD]) + sq(delta_mm[Z_HEAD])
#elif ENABLED(DELTA)
sq(dx) + sq(dy) + sq(dz)
#else
sq(delta_mm[X_AXIS]) + sq(delta_mm[Y_AXIS]) + sq(delta_mm[Z_AXIS])
#endif
);
)
#if ENABLED(DELTA)
* steps_to_mm[X_AXIS]
#endif
;
}
float inverse_millimeters = 1.0 / block->millimeters; // Inverse millimeters to remove multiple divides

Expand Down Expand Up @@ -875,7 +888,7 @@ void Planner::check_axes_activity() {
while (filwidth_delay_dist >= MMD_MM) filwidth_delay_dist -= MMD_MM;

// Convert into an index into the measurement array
filwidth_delay_index1 = (int)(filwidth_delay_dist / 10.0 + 0.0001);
filwidth_delay_index1 = (int)(filwidth_delay_dist * 0.1 + 0.0001);

// If the index has changed (must have gone forward)...
if (filwidth_delay_index1 != filwidth_delay_index2) {
Expand Down Expand Up @@ -962,7 +975,7 @@ void Planner::check_axes_activity() {
block->acceleration_steps_per_s2 = (max_acceleration_steps_per_s2[E_AXIS] * block->step_event_count) / block->steps[E_AXIS];
}
block->acceleration = block->acceleration_steps_per_s2 / steps_per_mm;
block->acceleration_rate = (long)(block->acceleration_steps_per_s2 * 16777216.0 / ((F_CPU) / 8.0));
block->acceleration_rate = (long)(block->acceleration_steps_per_s2 * 16777216.0 / ((F_CPU) * 0.125));

#if 0 // Use old jerk for now

Expand Down Expand Up @@ -1008,10 +1021,12 @@ void Planner::check_axes_activity() {
#endif

// Start with a safe speed
float vmax_junction = max_xy_jerk / 2;
float vmax_junction_factor = 1.0;
float mz2 = max_z_jerk / 2, me2 = max_e_jerk / 2;
float csz = current_speed[Z_AXIS], cse = current_speed[E_AXIS];
float vmax_junction = max_xy_jerk * 0.5,
vmax_junction_factor = 1.0,
mz2 = max_z_jerk * 0.5,
me2 = max_e_jerk * 0.5,
csz = current_speed[Z_AXIS],
cse = current_speed[E_AXIS];
if (fabs(csz) > mz2) vmax_junction = min(vmax_junction, mz2);
if (fabs(cse) > me2) vmax_junction = min(vmax_junction, me2);
vmax_junction = min(vmax_junction, block->nominal_speed);
Expand Down Expand Up @@ -1164,6 +1179,7 @@ void Planner::check_axes_activity() {
void Planner::set_e_position_mm(const float& e) {
position[E_AXIS] = lround(e * axis_steps_per_mm[E_AXIS]);
stepper.set_e_position(position[E_AXIS]);
previous_speed[E_AXIS] = 0.0;
}

// Recalculate the steps/s^2 acceleration rates, based on the mm/s^2
Expand All @@ -1172,6 +1188,13 @@ void Planner::reset_acceleration_rates() {
max_acceleration_steps_per_s2[i] = max_acceleration_mm_per_s2[i] * axis_steps_per_mm[i];
}

// Recalculate position, steps_to_mm if axis_steps_per_mm changes!
void Planner::refresh_positioning() {
LOOP_XYZE(i) planner.steps_to_mm[i] = 1.0 / planner.axis_steps_per_mm[i];
set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
reset_acceleration_rates();
}

#if ENABLED(AUTOTEMP)

void Planner::autotemp_M109() {
Expand Down
4 changes: 3 additions & 1 deletion Marlin/planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class Planner {

static float max_feedrate_mm_s[NUM_AXIS]; // Max speeds in mm per second
static float axis_steps_per_mm[NUM_AXIS];
static float steps_to_mm[NUM_AXIS];
static unsigned long max_acceleration_steps_per_s2[NUM_AXIS];
static unsigned long max_acceleration_mm_per_s2[NUM_AXIS]; // Use M201 to override by software

Expand All @@ -142,7 +143,7 @@ class Planner {

/**
* The current position of the tool in absolute steps
* Reclculated if any axis_steps_per_mm are changed by gcode
* Recalculated if any axis_steps_per_mm are changed by gcode
*/
static long position[NUM_AXIS];

Expand Down Expand Up @@ -187,6 +188,7 @@ class Planner {
*/

static void reset_acceleration_rates();
static void refresh_positioning();

// Manage fans, paste pressure, etc.
static void check_axes_activity();
Expand Down
8 changes: 4 additions & 4 deletions Marlin/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,14 +944,14 @@ float Stepper::get_axis_position_mm(AxisEnum axis) {
CRITICAL_SECTION_END;
// ((a1+a2)+(a1-a2))/2 -> (a1+a2+a1-a2)/2 -> (a1+a1)/2 -> a1
// ((a1+a2)-(a1-a2))/2 -> (a1+a2-a1+a2)/2 -> (a2+a2)/2 -> a2
axis_steps = (pos1 + ((axis == CORE_AXIS_1) ? pos2 : -pos2)) / 2.0f;
axis_steps = (pos1 + ((axis == CORE_AXIS_1) ? pos2 : -pos2)) * 0.5f;
}
else
axis_steps = position(axis);
#else
axis_steps = position(axis);
#endif
return axis_steps / planner.axis_steps_per_mm[axis];
return axis_steps * planner.steps_to_mm[axis];
}

void Stepper::finish_and_disable() {
Expand All @@ -973,9 +973,9 @@ void Stepper::endstop_triggered(AxisEnum axis) {

float axis_pos = count_position[axis];
if (axis == CORE_AXIS_1)
axis_pos = (axis_pos + count_position[CORE_AXIS_2]) / 2;
axis_pos = (axis_pos + count_position[CORE_AXIS_2]) * 0.5;
else if (axis == CORE_AXIS_2)
axis_pos = (count_position[CORE_AXIS_1] - axis_pos) / 2;
axis_pos = (count_position[CORE_AXIS_1] - axis_pos) * 0.5;
endstops_trigsteps[axis] = axis_pos;

#else // !COREXY && !COREXZ && !COREYZ
Expand Down
2 changes: 1 addition & 1 deletion Marlin/stepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ class Stepper {
// Triggered position of an axis in mm (not core-savvy)
//
static FORCE_INLINE float triggered_position_mm(AxisEnum axis) {
return endstops_trigsteps[axis] / planner.axis_steps_per_mm[axis];
return endstops_trigsteps[axis] * planner.steps_to_mm[axis];
}

#if ENABLED(LIN_ADVANCE)
Expand Down
Loading

0 comments on commit b7b7c90

Please sign in to comment.