Bläddra i källkod

⚡️ Optimize Planner calculations (#24484)

tombrazier 2 år sedan
förälder
incheckning
fc0615fbd1
2 ändrade filer med 80 tillägg och 110 borttagningar
  1. 78
    86
      Marlin/src/module/planner.cpp
  2. 2
    24
      Marlin/src/module/planner.h

+ 78
- 86
Marlin/src/module/planner.cpp Visa fil

28
  * Derived from Grbl
28
  * Derived from Grbl
29
  * Copyright (c) 2009-2011 Simen Svale Skogsrud
29
  * Copyright (c) 2009-2011 Simen Svale Skogsrud
30
  *
30
  *
31
- * The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis.
31
+ * Ring buffer gleaned from wiring_serial library by David A. Mellis.
32
  *
32
  *
33
+ * Fast inverse function needed for Bézier interpolation for AVR
34
+ * was designed, written and tested by Eduardo José Tagle, April 2018.
33
  *
35
  *
34
- * Reasoning behind the mathematics in this module (in the key of 'Mathematica'):
36
+ * Planner mathematics (Mathematica-style):
35
  *
37
  *
36
- * s == speed, a == acceleration, t == time, d == distance
38
+ * Where: s == speed, a == acceleration, t == time, d == distance
37
  *
39
  *
38
  * Basic definitions:
40
  * Basic definitions:
39
  *   Speed[s_, a_, t_] := s + (a*t)
41
  *   Speed[s_, a_, t_] := s + (a*t)
41
  *
43
  *
42
  * Distance to reach a specific speed with a constant acceleration:
44
  * Distance to reach a specific speed with a constant acceleration:
43
  *   Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t]
45
  *   Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t]
44
- *   d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance()
46
+ *   d -> (m^2 - s^2) / (2 a)
45
  *
47
  *
46
  * Speed after a given distance of travel with constant acceleration:
48
  * Speed after a given distance of travel with constant acceleration:
47
  *   Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t]
49
  *   Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t]
49
  *
51
  *
50
  * DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2]
52
  * DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2]
51
  *
53
  *
52
- * When to start braking (di) to reach a specified destination speed (s2) after accelerating
53
- * from initial speed s1 without ever stopping at a plateau:
54
+ * When to start braking (di) to reach a specified destination speed (s2) after
55
+ * acceleration from initial speed s1 without ever reaching a plateau:
54
  *   Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di]
56
  *   Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di]
55
- *   di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance()
57
+ *   di -> (2 a d - s1^2 + s2^2)/(4 a)
56
  *
58
  *
57
- * IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a)
59
+ * We note, as an optimization, that if we have already calculated an
60
+ * acceleration distance d1 from s1 to m and a deceration distance d2
61
+ * from m to s2 then
58
  *
62
  *
59
- * --
60
- *
61
- * The fast inverse function needed for Bézier interpolation for AVR
62
- * was designed, written and tested by Eduardo José Tagle on April/2018
63
+ *   d1 -> (m^2 - s1^2) / (2 a)
64
+ *   d2 -> (m^2 - s2^2) / (2 a)
65
+ *   di -> (d + d1 - d2) / 2
63
  */
66
  */
64
 
67
 
65
 #include "planner.h"
68
 #include "planner.h"
211
 uint32_t Planner::acceleration_long_cutoff;
214
 uint32_t Planner::acceleration_long_cutoff;
212
 
215
 
213
 xyze_float_t Planner::previous_speed;
216
 xyze_float_t Planner::previous_speed;
214
-float Planner::previous_nominal_speed_sqr;
217
+float Planner::previous_nominal_speed;
215
 
218
 
216
 #if ENABLED(DISABLE_INACTIVE_EXTRUDER)
219
 #if ENABLED(DISABLE_INACTIVE_EXTRUDER)
217
   last_move_t Planner::g_uc_extruder_last_move[E_STEPPERS] = { 0 };
220
   last_move_t Planner::g_uc_extruder_last_move[E_STEPPERS] = { 0 };
220
 #ifdef XY_FREQUENCY_LIMIT
223
 #ifdef XY_FREQUENCY_LIMIT
221
   int8_t Planner::xy_freq_limit_hz = XY_FREQUENCY_LIMIT;
224
   int8_t Planner::xy_freq_limit_hz = XY_FREQUENCY_LIMIT;
222
   float Planner::xy_freq_min_speed_factor = (XY_FREQUENCY_MIN_PERCENT) * 0.01f;
225
   float Planner::xy_freq_min_speed_factor = (XY_FREQUENCY_MIN_PERCENT) * 0.01f;
223
-  int32_t Planner::xy_freq_min_interval_us = LROUND(1000000.0 / (XY_FREQUENCY_LIMIT));
226
+  int32_t Planner::xy_freq_min_interval_us = LROUND(1000000.0f / (XY_FREQUENCY_LIMIT));
224
 #endif
227
 #endif
225
 
228
 
226
 #if ENABLED(LIN_ADVANCE)
229
 #if ENABLED(LIN_ADVANCE)
250
   TERN_(HAS_POSITION_FLOAT, position_float.reset());
253
   TERN_(HAS_POSITION_FLOAT, position_float.reset());
251
   TERN_(IS_KINEMATIC, position_cart.reset());
254
   TERN_(IS_KINEMATIC, position_cart.reset());
252
   previous_speed.reset();
255
   previous_speed.reset();
253
-  previous_nominal_speed_sqr = 0;
256
+  previous_nominal_speed = 0;
254
   TERN_(ABL_PLANAR, bed_level_matrix.set_to_identity());
257
   TERN_(ABL_PLANAR, bed_level_matrix.set_to_identity());
255
   clear_block_buffer();
258
   clear_block_buffer();
256
   delay_before_delivering = 0;
259
   delay_before_delivering = 0;
786
   NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE));
789
   NOLESS(final_rate, uint32_t(MINIMAL_STEP_RATE));
787
 
790
 
788
   #if ENABLED(S_CURVE_ACCELERATION)
791
   #if ENABLED(S_CURVE_ACCELERATION)
789
-    uint32_t cruise_rate = initial_rate;
792
+    // If we have some plateau time, the cruise rate will be the nominal rate
793
+    uint32_t cruise_rate = block->nominal_rate;
790
   #endif
794
   #endif
791
 
795
 
792
   const int32_t accel = block->acceleration_steps_per_s2;
796
   const int32_t accel = block->acceleration_steps_per_s2;
793
 
797
 
794
-          // Steps required for acceleration, deceleration to/from nominal rate
795
-  uint32_t accelerate_steps = CEIL(estimate_acceleration_distance(initial_rate, block->nominal_rate, accel)),
796
-           decelerate_steps = FLOOR(estimate_acceleration_distance(block->nominal_rate, final_rate, -accel));
797
-          // Steps between acceleration and deceleration, if any
798
-  int32_t plateau_steps = block->step_event_count - accelerate_steps - decelerate_steps;
799
-
800
-  // Does accelerate_steps + decelerate_steps exceed step_event_count?
801
-  // Then we can't possibly reach the nominal rate, there will be no cruising.
802
-  // Use intersection_distance() to calculate accel / braking time in order to
803
-  // reach the final_rate exactly at the end of this block.
804
-  if (plateau_steps < 0) {
805
-    const float accelerate_steps_float = CEIL(intersection_distance(initial_rate, final_rate, accel, block->step_event_count));
806
-    accelerate_steps = _MIN(uint32_t(_MAX(accelerate_steps_float, 0)), block->step_event_count);
807
-    decelerate_steps = block->step_event_count - accelerate_steps;
808
-    plateau_steps = 0;
809
-
810
-    #if ENABLED(S_CURVE_ACCELERATION)
811
-      // We won't reach the cruising rate. Let's calculate the speed we will reach
812
-      cruise_rate = final_speed(initial_rate, accel, accelerate_steps);
813
-    #endif
798
+  // Steps for acceleration, plateau and deceleration
799
+  int32_t plateau_steps = block->step_event_count;
800
+  uint32_t accelerate_steps = 0,
801
+           decelerate_steps = 0;
802
+
803
+  if (accel != 0) {
804
+    // Steps required for acceleration, deceleration to/from nominal rate
805
+    const float nominal_rate_sq = sq(float(block->nominal_rate));
806
+    float accelerate_steps_float = (nominal_rate_sq - sq(float(initial_rate))) * (0.5f / accel);
807
+    accelerate_steps = CEIL(accelerate_steps_float);
808
+    const float decelerate_steps_float = (nominal_rate_sq - sq(float(final_rate))) * (0.5f / accel);
809
+    decelerate_steps = decelerate_steps_float;
810
+
811
+    // Steps between acceleration and deceleration, if any
812
+    plateau_steps -= accelerate_steps + decelerate_steps;
813
+
814
+    // Does accelerate_steps + decelerate_steps exceed step_event_count?
815
+    // Then we can't possibly reach the nominal rate, there will be no cruising.
816
+    // Calculate accel / braking time in order to reach the final_rate exactly
817
+    // at the end of this block.
818
+    if (plateau_steps < 0) {
819
+      accelerate_steps_float = CEIL((block->step_event_count + accelerate_steps_float - decelerate_steps_float) * 0.5f);
820
+      accelerate_steps = _MIN(uint32_t(_MAX(accelerate_steps_float, 0)), block->step_event_count);
821
+      decelerate_steps = block->step_event_count - accelerate_steps;
822
+
823
+      #if ENABLED(S_CURVE_ACCELERATION)
824
+        // We won't reach the cruising rate. Let's calculate the speed we will reach
825
+        cruise_rate = final_speed(initial_rate, accel, accelerate_steps);
826
+      #endif
827
+    }
814
   }
828
   }
815
-  #if ENABLED(S_CURVE_ACCELERATION)
816
-    else // We have some plateau time, so the cruise rate will be the nominal rate
817
-      cruise_rate = block->nominal_rate;
818
-  #endif
819
 
829
 
820
   #if ENABLED(S_CURVE_ACCELERATION)
830
   #if ENABLED(S_CURVE_ACCELERATION)
821
     // Jerk controlled speed requires to express speed versus time, NOT steps
831
     // Jerk controlled speed requires to express speed versus time, NOT steps
822
-    uint32_t acceleration_time = ((float)(cruise_rate - initial_rate) / accel) * (STEPPER_TIMER_RATE),
823
-             deceleration_time = ((float)(cruise_rate - final_rate) / accel) * (STEPPER_TIMER_RATE),
832
+    uint32_t acceleration_time = (float(cruise_rate - initial_rate) / accel) * (STEPPER_TIMER_RATE),
833
+             deceleration_time = (float(cruise_rate - final_rate) / accel) * (STEPPER_TIMER_RATE),
824
     // And to offload calculations from the ISR, we also calculate the inverse of those times here
834
     // And to offload calculations from the ISR, we also calculate the inverse of those times here
825
              acceleration_time_inverse = get_period_inverse(acceleration_time),
835
              acceleration_time_inverse = get_period_inverse(acceleration_time),
826
              deceleration_time_inverse = get_period_inverse(deceleration_time);
836
              deceleration_time_inverse = get_period_inverse(deceleration_time);
1175
 
1185
 
1176
   // Go from the tail (currently executed block) to the first block, without including it)
1186
   // Go from the tail (currently executed block) to the first block, without including it)
1177
   block_t *block = nullptr, *next = nullptr;
1187
   block_t *block = nullptr, *next = nullptr;
1178
-  float current_entry_speed = 0.0, next_entry_speed = 0.0;
1188
+  float current_entry_speed = 0.0f, next_entry_speed = 0.0f;
1179
   while (block_index != head_block_index) {
1189
   while (block_index != head_block_index) {
1180
 
1190
 
1181
     next = &block_buffer[block_index];
1191
     next = &block_buffer[block_index];
1199
             // Block is not BUSY, we won the race against the Stepper ISR:
1209
             // Block is not BUSY, we won the race against the Stepper ISR:
1200
 
1210
 
1201
             // NOTE: Entry and exit factors always > 0 by all previous logic operations.
1211
             // NOTE: Entry and exit factors always > 0 by all previous logic operations.
1202
-            const float current_nominal_speed = SQRT(block->nominal_speed_sqr),
1203
-                        nomr = 1.0f / current_nominal_speed;
1212
+            const float nomr = 1.0f / block->nominal_speed;
1204
             calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
1213
             calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
1205
             #if ENABLED(LIN_ADVANCE)
1214
             #if ENABLED(LIN_ADVANCE)
1206
               if (block->use_advance_lead) {
1215
               if (block->use_advance_lead) {
1207
                 const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm[E_AXIS];
1216
                 const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm[E_AXIS];
1208
-                block->max_adv_steps = current_nominal_speed * comp;
1217
+                block->max_adv_steps = block->nominal_speed * comp;
1209
                 block->final_adv_steps = next_entry_speed * comp;
1218
                 block->final_adv_steps = next_entry_speed * comp;
1210
               }
1219
               }
1211
             #endif
1220
             #endif
1240
     if (!stepper.is_block_busy(block)) {
1249
     if (!stepper.is_block_busy(block)) {
1241
       // Block is not BUSY, we won the race against the Stepper ISR:
1250
       // Block is not BUSY, we won the race against the Stepper ISR:
1242
 
1251
 
1243
-      const float current_nominal_speed = SQRT(block->nominal_speed_sqr),
1244
-                  nomr = 1.0f / current_nominal_speed;
1252
+      const float nomr = 1.0f / block->nominal_speed;
1245
       calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
1253
       calculate_trapezoid_for_block(block, current_entry_speed * nomr, next_entry_speed * nomr);
1246
       #if ENABLED(LIN_ADVANCE)
1254
       #if ENABLED(LIN_ADVANCE)
1247
         if (block->use_advance_lead) {
1255
         if (block->use_advance_lead) {
1248
           const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm[E_AXIS];
1256
           const float comp = block->e_D_ratio * extruder_advance_K[active_extruder] * settings.axis_steps_per_mm[E_AXIS];
1249
-          block->max_adv_steps = current_nominal_speed * comp;
1257
+          block->max_adv_steps = block->nominal_speed * comp;
1250
           block->final_adv_steps = next_entry_speed * comp;
1258
           block->final_adv_steps = next_entry_speed * comp;
1251
         }
1259
         }
1252
       #endif
1260
       #endif
1290
     #define FAN_SET(F) do{ kickstart_fan(fan_speed, ms, F); _FAN_SET(F); }while(0)
1298
     #define FAN_SET(F) do{ kickstart_fan(fan_speed, ms, F); _FAN_SET(F); }while(0)
1291
 
1299
 
1292
     const millis_t ms = millis();
1300
     const millis_t ms = millis();
1293
-    TERN_(HAS_FAN0, FAN_SET(0));
1294
-    TERN_(HAS_FAN1, FAN_SET(1));
1295
-    TERN_(HAS_FAN2, FAN_SET(2));
1296
-    TERN_(HAS_FAN3, FAN_SET(3));
1297
-    TERN_(HAS_FAN4, FAN_SET(4));
1298
-    TERN_(HAS_FAN5, FAN_SET(5));
1299
-    TERN_(HAS_FAN6, FAN_SET(6));
1300
-    TERN_(HAS_FAN7, FAN_SET(7));
1301
+    TERN_(HAS_FAN0, FAN_SET(0)); TERN_(HAS_FAN1, FAN_SET(1));
1302
+    TERN_(HAS_FAN2, FAN_SET(2)); TERN_(HAS_FAN3, FAN_SET(3));
1303
+    TERN_(HAS_FAN4, FAN_SET(4)); TERN_(HAS_FAN5, FAN_SET(5));
1304
+    TERN_(HAS_FAN6, FAN_SET(6)); TERN_(HAS_FAN7, FAN_SET(7));
1301
   }
1305
   }
1302
 
1306
 
1303
   #if FAN_KICKSTART_TIME
1307
   #if FAN_KICKSTART_TIME
1485
     for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
1489
     for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
1486
       const block_t * const block = &block_buffer[b];
1490
       const block_t * const block = &block_buffer[b];
1487
       if (NUM_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k, || block->steps.u, || block->steps.v, || block->steps.w)) {
1491
       if (NUM_AXIS_GANG(block->steps.x, || block->steps.y, || block->steps.z, || block->steps.i, || block->steps.j, || block->steps.k, || block->steps.u, || block->steps.v, || block->steps.w)) {
1488
-        const float se = (float)block->steps.e / block->step_event_count * SQRT(block->nominal_speed_sqr); // mm/sec;
1492
+        const float se = float(block->steps.e) / block->step_event_count * block->nominal_speed; // mm/sec
1489
         NOLESS(high, se);
1493
         NOLESS(high, se);
1490
       }
1494
       }
1491
     }
1495
     }
1936
           #if ENABLED(MIXING_EXTRUDER)
1940
           #if ENABLED(MIXING_EXTRUDER)
1937
             bool ignore_e = false;
1941
             bool ignore_e = false;
1938
             float collector[MIXING_STEPPERS];
1942
             float collector[MIXING_STEPPERS];
1939
-            mixer.refresh_collector(1.0, mixer.get_current_vtool(), collector);
1943
+            mixer.refresh_collector(1.0f, mixer.get_current_vtool(), collector);
1940
             MIXER_STEPPER_LOOP(e)
1944
             MIXER_STEPPER_LOOP(e)
1941
               if (e_steps * collector[e] > max_e_steps) { ignore_e = true; break; }
1945
               if (e_steps * collector[e] > max_e_steps) { ignore_e = true; break; }
1942
           #else
1946
           #else
2193
       #if SECONDARY_LINEAR_AXES >= 1 && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM)
2197
       #if SECONDARY_LINEAR_AXES >= 1 && NONE(FOAMCUTTER_XYUV, ARTICULATED_ROBOT_ARM)
2194
         if (NEAR_ZERO(distance_sqr)) {
2198
         if (NEAR_ZERO(distance_sqr)) {
2195
           // Move does not involve any primary linear axes (xyz) but might involve secondary linear axes
2199
           // Move does not involve any primary linear axes (xyz) but might involve secondary linear axes
2196
-          distance_sqr = (0.0
2200
+          distance_sqr = (0.0f
2197
             SECONDARY_AXIS_GANG(
2201
             SECONDARY_AXIS_GANG(
2198
               IF_DISABLED(AXIS4_ROTATES, + sq(steps_dist_mm.i)),
2202
               IF_DISABLED(AXIS4_ROTATES, + sq(steps_dist_mm.i)),
2199
               IF_DISABLED(AXIS5_ROTATES, + sq(steps_dist_mm.j)),
2203
               IF_DISABLED(AXIS5_ROTATES, + sq(steps_dist_mm.j)),
2396
     if (was_enabled) stepper.wake_up();
2400
     if (was_enabled) stepper.wake_up();
2397
   #endif
2401
   #endif
2398
 
2402
 
2399
-  block->nominal_speed_sqr = sq(block->millimeters * inverse_secs);   // (mm/sec)^2 Always > 0
2403
+  block->nominal_speed = block->millimeters * inverse_secs;           // (mm/sec) Always > 0
2400
   block->nominal_rate = CEIL(block->step_event_count * inverse_secs); // (step/sec) Always > 0
2404
   block->nominal_rate = CEIL(block->step_event_count * inverse_secs); // (step/sec) Always > 0
2401
 
2405
 
2402
   #if ENABLED(FILAMENT_WIDTH_SENSOR)
2406
   #if ENABLED(FILAMENT_WIDTH_SENSOR)
2492
   if (speed_factor < 1.0f) {
2496
   if (speed_factor < 1.0f) {
2493
     current_speed *= speed_factor;
2497
     current_speed *= speed_factor;
2494
     block->nominal_rate *= speed_factor;
2498
     block->nominal_rate *= speed_factor;
2495
-    block->nominal_speed_sqr = block->nominal_speed_sqr * sq(speed_factor);
2499
+    block->nominal_speed *= speed_factor;
2496
   }
2500
   }
2497
 
2501
 
2498
   // Compute and limit the acceleration rate for the trapezoid generator.
2502
   // Compute and limit the acceleration rate for the trapezoid generator.
2592
     if (block->use_advance_lead) {
2596
     if (block->use_advance_lead) {
2593
       block->advance_speed = (STEPPER_TIMER_RATE) / (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * settings.axis_steps_per_mm[E_AXIS_N(extruder)]);
2597
       block->advance_speed = (STEPPER_TIMER_RATE) / (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * settings.axis_steps_per_mm[E_AXIS_N(extruder)]);
2594
       #if ENABLED(LA_DEBUG)
2598
       #if ENABLED(LA_DEBUG)
2595
-        if (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * 2 < SQRT(block->nominal_speed_sqr) * block->e_D_ratio)
2599
+        if (extruder_advance_K[active_extruder] * block->e_D_ratio * block->acceleration * 2 < block->nominal_speed * block->e_D_ratio)
2596
           SERIAL_ECHOLNPGM("More than 2 steps per eISR loop executed.");
2600
           SERIAL_ECHOLNPGM("More than 2 steps per eISR loop executed.");
2597
         if (block->advance_speed < 200)
2601
         if (block->advance_speed < 200)
2598
           SERIAL_ECHOLNPGM("eISR running at > 10kHz.");
2602
           SERIAL_ECHOLNPGM("eISR running at > 10kHz.");
2663
       unit_vec *= inverse_millimeters;      // Use pre-calculated (1 / SQRT(x^2 + y^2 + z^2))
2667
       unit_vec *= inverse_millimeters;      // Use pre-calculated (1 / SQRT(x^2 + y^2 + z^2))
2664
 
2668
 
2665
     // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
2669
     // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
2666
-    if (moves_queued && !UNEAR_ZERO(previous_nominal_speed_sqr)) {
2670
+    if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
2667
       // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
2671
       // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
2668
       // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
2672
       // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
2669
       float junction_cos_theta = LOGICAL_AXIS_GANG(
2673
       float junction_cos_theta = LOGICAL_AXIS_GANG(
2792
       }
2796
       }
2793
 
2797
 
2794
       // Get the lowest speed
2798
       // Get the lowest speed
2795
-      vmax_junction_sqr = _MIN(vmax_junction_sqr, block->nominal_speed_sqr, previous_nominal_speed_sqr);
2799
+      vmax_junction_sqr = _MIN(vmax_junction_sqr, sq(block->nominal_speed), sq(previous_nominal_speed));
2796
     }
2800
     }
2797
     else // Init entry speed to zero. Assume it starts from rest. Planner will correct this later.
2801
     else // Init entry speed to zero. Assume it starts from rest. Planner will correct this later.
2798
       vmax_junction_sqr = 0;
2802
       vmax_junction_sqr = 0;
2801
 
2805
 
2802
   #endif
2806
   #endif
2803
 
2807
 
2804
-  #ifdef USE_CACHED_SQRT
2805
-    #define CACHED_SQRT(N, V) \
2806
-      static float saved_V, N; \
2807
-      if (V != saved_V) { N = SQRT(V); saved_V = V; }
2808
-  #else
2809
-    #define CACHED_SQRT(N, V) const float N = SQRT(V)
2810
-  #endif
2811
-
2812
   #if HAS_CLASSIC_JERK
2808
   #if HAS_CLASSIC_JERK
2813
 
2809
 
2814
     /**
2810
     /**
2815
      * Adapted from Průša MKS firmware
2811
      * Adapted from Průša MKS firmware
2816
      * https://github.com/prusa3d/Prusa-Firmware
2812
      * https://github.com/prusa3d/Prusa-Firmware
2817
      */
2813
      */
2818
-    CACHED_SQRT(nominal_speed, block->nominal_speed_sqr);
2819
-
2820
     // Exit speed limited by a jerk to full halt of a previous last segment
2814
     // Exit speed limited by a jerk to full halt of a previous last segment
2821
     static float previous_safe_speed;
2815
     static float previous_safe_speed;
2822
 
2816
 
2823
     // Start with a safe speed (from which the machine may halt to stop immediately).
2817
     // Start with a safe speed (from which the machine may halt to stop immediately).
2824
-    float safe_speed = nominal_speed;
2818
+    float safe_speed = block->nominal_speed;
2825
 
2819
 
2826
     #ifndef TRAVEL_EXTRA_XYJERK
2820
     #ifndef TRAVEL_EXTRA_XYJERK
2827
       #define TRAVEL_EXTRA_XYJERK 0
2821
       #define TRAVEL_EXTRA_XYJERK 0
2834
                   maxj = (max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f)); // mj : The max jerk setting for this axis
2828
                   maxj = (max_jerk[i] + (i == X_AXIS || i == Y_AXIS ? extra_xyjerk : 0.0f)); // mj : The max jerk setting for this axis
2835
       if (jerk > maxj) {                          // cs > mj : New current speed too fast?
2829
       if (jerk > maxj) {                          // cs > mj : New current speed too fast?
2836
         if (limited) {                            // limited already?
2830
         if (limited) {                            // limited already?
2837
-          const float mjerk = nominal_speed * maxj; // ns*mj
2831
+          const float mjerk = block->nominal_speed * maxj; // ns*mj
2838
           if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk; // ns*mj/cs
2832
           if (jerk * safe_speed > mjerk) safe_speed = mjerk / jerk; // ns*mj/cs
2839
         }
2833
         }
2840
         else {
2834
         else {
2845
     }
2839
     }
2846
 
2840
 
2847
     float vmax_junction;
2841
     float vmax_junction;
2848
-    if (moves_queued && !UNEAR_ZERO(previous_nominal_speed_sqr)) {
2842
+    if (moves_queued && !UNEAR_ZERO(previous_nominal_speed)) {
2849
       // Estimate a maximum velocity allowed at a joint of two successive segments.
2843
       // Estimate a maximum velocity allowed at a joint of two successive segments.
2850
       // If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
2844
       // If this maximum velocity allowed is lower than the minimum of the entry / exit safe velocities,
2851
       // then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
2845
       // then the machine is not coasting anymore and the safe entry / exit velocities shall be used.
2856
 
2850
 
2857
       // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
2851
       // The junction velocity will be shared between successive segments. Limit the junction velocity to their minimum.
2858
       // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
2852
       // Pick the smaller of the nominal speeds. Higher speed shall not be achieved at the junction during coasting.
2859
-      CACHED_SQRT(previous_nominal_speed, previous_nominal_speed_sqr);
2860
-
2861
       float smaller_speed_factor = 1.0f;
2853
       float smaller_speed_factor = 1.0f;
2862
-      if (nominal_speed < previous_nominal_speed) {
2863
-        vmax_junction = nominal_speed;
2854
+      if (block->nominal_speed < previous_nominal_speed) {
2855
+        vmax_junction = block->nominal_speed;
2864
         smaller_speed_factor = vmax_junction / previous_nominal_speed;
2856
         smaller_speed_factor = vmax_junction / previous_nominal_speed;
2865
       }
2857
       }
2866
       else
2858
       else
2927
   // block nominal speed limits both the current and next maximum junction speeds. Hence, in both
2919
   // block nominal speed limits both the current and next maximum junction speeds. Hence, in both
2928
   // the reverse and forward planners, the corresponding block junction speed will always be at the
2920
   // the reverse and forward planners, the corresponding block junction speed will always be at the
2929
   // the maximum junction speed and may always be ignored for any speed reduction checks.
2921
   // the maximum junction speed and may always be ignored for any speed reduction checks.
2930
-  block->flag.set_nominal(block->nominal_speed_sqr <= v_allowable_sqr);
2922
+  block->flag.set_nominal(sq(block->nominal_speed) <= v_allowable_sqr);
2931
 
2923
 
2932
   // Update previous path unit_vector and nominal speed
2924
   // Update previous path unit_vector and nominal speed
2933
   previous_speed = current_speed;
2925
   previous_speed = current_speed;
2934
-  previous_nominal_speed_sqr = block->nominal_speed_sqr;
2926
+  previous_nominal_speed = block->nominal_speed;
2935
 
2927
 
2936
   position = target;  // Update the position
2928
   position = target;  // Update the position
2937
 
2929
 
3268
   );
3260
   );
3269
 
3261
 
3270
   if (has_blocks_queued()) {
3262
   if (has_blocks_queued()) {
3271
-    //previous_nominal_speed_sqr = 0.0; // Reset planner junction speeds. Assume start from rest.
3263
+    //previous_nominal_speed = 0.0f; // Reset planner junction speeds. Assume start from rest.
3272
     //previous_speed.reset();
3264
     //previous_speed.reset();
3273
     buffer_sync_block(BLOCK_BIT_SYNC_POSITION);
3265
     buffer_sync_block(BLOCK_BIT_SYNC_POSITION);
3274
   }
3266
   }
3344
 inline void limit_and_warn(float &val, const AxisEnum axis, PGM_P const setting_name, const xyze_float_t &max_limit) {
3336
 inline void limit_and_warn(float &val, const AxisEnum axis, PGM_P const setting_name, const xyze_float_t &max_limit) {
3345
   const uint8_t lim_axis = TERN_(HAS_EXTRUDERS, axis > E_AXIS ? E_AXIS :) axis;
3337
   const uint8_t lim_axis = TERN_(HAS_EXTRUDERS, axis > E_AXIS ? E_AXIS :) axis;
3346
   const float before = val;
3338
   const float before = val;
3347
-  LIMIT(val, 0.1, max_limit[lim_axis]);
3339
+  LIMIT(val, 0.1f, max_limit[lim_axis]);
3348
   if (before != val) {
3340
   if (before != val) {
3349
     SERIAL_CHAR(AXIS_CHAR(lim_axis));
3341
     SERIAL_CHAR(AXIS_CHAR(lim_axis));
3350
     SERIAL_ECHOPGM(" Max ");
3342
     SERIAL_ECHOPGM(" Max ");

+ 2
- 24
Marlin/src/module/planner.h Visa fil

199
   volatile bool is_move() { return !(is_sync() || is_page()); }
199
   volatile bool is_move() { return !(is_sync() || is_page()); }
200
 
200
 
201
   // Fields used by the motion planner to manage acceleration
201
   // Fields used by the motion planner to manage acceleration
202
-  float nominal_speed_sqr,                  // The nominal speed for this block in (mm/sec)^2
202
+  float nominal_speed,                      // The nominal speed for this block in (mm/sec)
203
         entry_speed_sqr,                    // Entry speed at previous-current junction in (mm/sec)^2
203
         entry_speed_sqr,                    // Entry speed at previous-current junction in (mm/sec)^2
204
         max_entry_speed_sqr,                // Maximum allowable junction entry speed in (mm/sec)^2
204
         max_entry_speed_sqr,                // Maximum allowable junction entry speed in (mm/sec)^2
205
         millimeters,                        // The total travel of this block in mm
205
         millimeters,                        // The total travel of this block in mm
510
     /**
510
     /**
511
      * Nominal speed of previous path line segment (mm/s)^2
511
      * Nominal speed of previous path line segment (mm/s)^2
512
      */
512
      */
513
-    static float previous_nominal_speed_sqr;
513
+    static float previous_nominal_speed;
514
 
514
 
515
     /**
515
     /**
516
      * Limit where 64bit math is necessary for acceleration calculation
516
      * Limit where 64bit math is necessary for acceleration calculation
1010
     static constexpr uint8_t prev_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index - 1); }
1010
     static constexpr uint8_t prev_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index - 1); }
1011
 
1011
 
1012
     /**
1012
     /**
1013
-     * Calculate the distance (not time) it takes to accelerate
1014
-     * from initial_rate to target_rate using the given acceleration:
1015
-     */
1016
-    static float estimate_acceleration_distance(const_float_t initial_rate, const_float_t target_rate, const_float_t accel) {
1017
-      if (accel == 0) return 0; // accel was 0, set acceleration distance to 0
1018
-      return (sq(target_rate) - sq(initial_rate)) / (accel * 2);
1019
-    }
1020
-
1021
-    /**
1022
-     * Return the point at which you must start braking (at the rate of -'accel') if
1023
-     * you start at 'initial_rate', accelerate (until reaching the point), and want to end at
1024
-     * 'final_rate' after traveling 'distance'.
1025
-     *
1026
-     * This is used to compute the intersection point between acceleration and deceleration
1027
-     * in cases where the "trapezoid" has no plateau (i.e., never reaches maximum speed)
1028
-     */
1029
-    static float intersection_distance(const_float_t initial_rate, const_float_t final_rate, const_float_t accel, const_float_t distance) {
1030
-      if (accel == 0) return 0; // accel was 0, set intersection distance to 0
1031
-      return (accel * 2 * distance - sq(initial_rate) + sq(final_rate)) / (accel * 4);
1032
-    }
1033
-
1034
-    /**
1035
      * Calculate the maximum allowable speed squared at this point, in order
1013
      * Calculate the maximum allowable speed squared at this point, in order
1036
      * to reach 'target_velocity_sqr' using 'acceleration' within a given
1014
      * to reach 'target_velocity_sqr' using 'acceleration' within a given
1037
      * 'distance'.
1015
      * 'distance'.

Laddar…
Avbryt
Spara