Skip to content

Commit 1ead60e

Browse files
dbuezasthinkyheadnarno2202
authored
⚡️ FT Motion trajectories, smoothing, optimization (#28115)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com> Co-authored-by: narno2202 <130909513+narno2202@users.noreply.github.com>
1 parent 5a0923e commit 1ead60e

17 files changed

Lines changed: 860 additions & 680 deletions

Marlin/Configuration_adv.h

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,7 @@
11911191

11921192
#define FTM_TRAJECTORY_TYPE TRAPEZOIDAL // Block acceleration profile (TRAPEZOIDAL, POLY5, POLY6)
11931193
// TRAPEZOIDAL: Continuous Velocity. Max acceleration is respected.
1194-
// POLY5: Like POLY6 with 1.5x but cpu cheaper.
1194+
// POLY5: Like POLY6 with 1.5x but uses less CPU.
11951195
// POLY6: Continuous Acceleration (aka S_CURVE).
11961196
// POLY trajectories not only reduce resonances without rounding corners, but also
11971197
// reduce extruder strain due to linear advance.
@@ -1201,30 +1201,12 @@
12011201
/**
12021202
* Advanced configuration
12031203
*/
1204-
#define FTM_UNIFIED_BWS // DON'T DISABLE unless you use Ulendo FBS (not implemented)
1205-
#if ENABLED(FTM_UNIFIED_BWS)
1206-
#define FTM_BW_SIZE 100 // Unified Window and Batch size with a ratio of 2
1207-
#else
1208-
#define FTM_WINDOW_SIZE 200 // Custom Window size for trajectory generation needed by Ulendo FBS
1209-
#define FTM_BATCH_SIZE 100 // Custom Batch size for trajectory generation needed by Ulendo FBS
1210-
#endif
1211-
1212-
#define FTM_FS 1000 // (Hz) Frequency for trajectory generation
1213-
1214-
#if DISABLED(COREXY)
1215-
#define FTM_STEPPER_FS 20000 // (Hz) Frequency for stepper I/O update
1216-
1217-
// Use this to adjust the time required to consume the command buffer.
1218-
// Try increasing this value if stepper motion is choppy.
1219-
#define FTM_STEPPERCMD_BUFF_SIZE 3000 // Size of the stepper command buffers
1220-
1221-
#else
1222-
// CoreXY motion needs a larger buffer size. These values are based on our testing.
1223-
#define FTM_STEPPER_FS 30000
1224-
#define FTM_STEPPERCMD_BUFF_SIZE 6000
1225-
#endif
1204+
#define FTM_BUFFER_SIZE 128 // Window size for trajectory generation, must be a power of 2 (e.g 64, 128, 256, ...)
1205+
// The total buffered time in seconds is (FTM_BUFFER_SIZE/FTM_FS)
1206+
#define FTM_FS 1000 // (Hz) Frequency for trajectory generation.
1207+
#define FTM_STEPPER_FS 2'000'000 // (Hz) Time resolution of stepper I/O update. Shouldn't affect CPU much (slower board testing needed)
1208+
#define FTM_MIN_SHAPE_FREQ 20 // (Hz) Minimum shaping frequency, lower consumes more RAM
12261209

1227-
#define FTM_MIN_SHAPE_FREQ 10 // (Hz) Minimum shaping frequency, lower consumes more RAM
12281210
#endif // FT_MOTION
12291211

12301212
/**

Marlin/src/core/types.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,24 @@ struct Flags<N, false> {
238238
FI bool operator[](const int n) const { return test(n); }
239239
FI int size() const { return sizeof(b); }
240240
FI operator bool() const { return b != 0; }
241+
242+
FI Flags<N>& operator|=(Flags<N> &p) const { b |= p.b; return *this; }
243+
FI Flags<N>& operator&=(Flags<N> &p) const { b &= p.b; return *this; }
244+
FI Flags<N>& operator^=(Flags<N> &p) const { b ^= p.b; return *this; }
245+
246+
FI Flags<N>& operator|=(const flagbits_t &p) { b |= flagbits_t(p); return *this; }
247+
FI Flags<N>& operator&=(const flagbits_t &p) { b &= flagbits_t(p); return *this; }
248+
FI Flags<N>& operator^=(const flagbits_t &p) { b ^= flagbits_t(p); return *this; }
249+
250+
FI Flags<N> operator|(Flags<N> &p) const { return Flags<N>(b | p.b); }
251+
FI Flags<N> operator&(Flags<N> &p) const { return Flags<N>(b & p.b); }
252+
FI Flags<N> operator^(Flags<N> &p) const { return Flags<N>(b ^ p.b); }
253+
FI Flags<N> operator~() const { return Flags<N>(~b); }
254+
255+
FI flagbits_t operator|(const flagbits_t &p) const { return b | flagbits_t(p); }
256+
FI flagbits_t operator&(const flagbits_t &p) const { return b & flagbits_t(p); }
257+
FI flagbits_t operator^(const flagbits_t &p) const { return b ^ flagbits_t(p); }
258+
241259
};
242260

243261
// Flag bits for more than 64 states
@@ -635,6 +653,21 @@ struct XYval {
635653
FI bool operator==(const T &p) const { return x == p && y == p; }
636654
FI bool operator!=(const T &p) const { return !operator==(p); }
637655

656+
FI bool operator< (const XYval<T> &rs) const { return x < rs.x && y < rs.y; }
657+
FI bool operator<=(const XYval<T> &rs) const { return x <= rs.x && y <= rs.y; }
658+
FI bool operator> (const XYval<T> &rs) const { return x > rs.x && y > rs.y; }
659+
FI bool operator>=(const XYval<T> &rs) const { return x >= rs.x && y >= rs.y; }
660+
661+
FI bool operator< (const XYZval<T> &rs) const { return true XY_GANG(&& x < rs.x, && y < rs.y); }
662+
FI bool operator<=(const XYZval<T> &rs) const { return true XY_GANG(&& x <= rs.x, && y <= rs.y); }
663+
FI bool operator> (const XYZval<T> &rs) const { return true XY_GANG(&& x > rs.x, && y > rs.y); }
664+
FI bool operator>=(const XYZval<T> &rs) const { return true XY_GANG(&& x >= rs.x, && y >= rs.y); }
665+
666+
FI bool operator< (const XYZEval<T> &rs) const { return true XY_GANG(&& x < rs.x, && y < rs.y); }
667+
FI bool operator<=(const XYZEval<T> &rs) const { return true XY_GANG(&& x <= rs.x, && y <= rs.y); }
668+
FI bool operator> (const XYZEval<T> &rs) const { return true XY_GANG(&& x > rs.x, && y > rs.y); }
669+
FI bool operator>=(const XYZEval<T> &rs) const { return true XY_GANG(&& x >= rs.x, && y >= rs.y); }
670+
638671
};
639672

640673
//
@@ -794,6 +827,16 @@ struct XYZval {
794827
FI bool operator==(const T &p) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == p, && y == p, && z == p, && i == p, && j == p, && k == p, && u == p, && v == p, && w == p); }
795828
FI bool operator!=(const T &p) const { return !operator==(p); }
796829

830+
FI bool operator< (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
831+
FI bool operator<=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
832+
FI bool operator> (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
833+
FI bool operator>=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
834+
835+
FI bool operator< (const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
836+
FI bool operator<=(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
837+
FI bool operator> (const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
838+
FI bool operator>=(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
839+
797840
};
798841

799842
//
@@ -957,6 +1000,16 @@ struct XYZEval {
9571000
FI bool operator==(const T &p) const { return ENABLED(HAS_X_AXIS) LOGICAL_AXIS_GANG(&& e == p, && x == p, && y == p, && z == p, && i == p, && j == p, && k == p, && u == p, && v == p, && w == p); }
9581001
FI bool operator!=(const T &p) const { return !operator==(p); }
9591002

1003+
FI bool operator< (const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e < rs.e, && x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
1004+
FI bool operator<=(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e <= rs.e, && x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
1005+
FI bool operator> (const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e > rs.e, && x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
1006+
FI bool operator>=(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e >= rs.e, && x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
1007+
1008+
FI bool operator< (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
1009+
FI bool operator<=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
1010+
FI bool operator> (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
1011+
FI bool operator>=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
1012+
9601013
};
9611014

9621015
#include <string.h> // for memset
@@ -1263,6 +1316,7 @@ class AxisBits {
12631316
FI AxisBits operator|(const AxisBits &p) const { return AxisBits(bits | p.bits); }
12641317
FI AxisBits operator&(const AxisBits &p) const { return AxisBits(bits & p.bits); }
12651318
FI AxisBits operator^(const AxisBits &p) const { return AxisBits(bits ^ p.bits); }
1319+
FI AxisBits operator~() const { return AxisBits(~bits); }
12661320

12671321
FI operator bool() const { return !!bits; }
12681322
FI operator uint16_t() const { return uint16_t(bits & 0xFFFF); }

Marlin/src/inc/Conditionals-4-adv.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,10 +1537,6 @@
15371537
#if !HAS_EXTRUDERS
15381538
#undef FTM_SHAPER_E
15391539
#endif
1540-
#if ENABLED(FTM_UNIFIED_BWS)
1541-
#define FTM_WINDOW_SIZE FTM_BW_SIZE
1542-
#define FTM_BATCH_SIZE FTM_BW_SIZE
1543-
#endif
15441540
#endif
15451541

15461542
// Multi-Stepping Limit

Marlin/src/inc/Conditionals-5-post.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3680,4 +3680,8 @@
36803680
// 2HEI : FTM_RATIO * 3 / 2
36813681
// 3HEI : FTM_RATIO * 2
36823682
#define FTM_SMOOTHING_ORDER 5 // 3 to 5 is closest to gaussian
3683+
#ifndef FTM_BUFFER_SIZE
3684+
#define FTM_BUFFER_SIZE 128
3685+
#endif
3686+
#define FTM_BUFFER_MASK (FTM_BUFFER_SIZE - 1u)
36833687
#endif

Marlin/src/inc/SanityCheck.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4491,10 +4491,9 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."
44914491
* Fixed-Time Motion limitations
44924492
*/
44934493
#if ENABLED(FT_MOTION)
4494+
static_assert(FTM_BUFFER_SIZE >= 4 && (FTM_BUFFER_SIZE & FTM_BUFFER_MASK) == 0, "FTM_BUFFER_SIZE must be a power of two (128, 256, 512, ...).");
44944495
#if ENABLED(MIXING_EXTRUDER)
44954496
#error "FT_MOTION does not currently support MIXING_EXTRUDER."
4496-
#elif DISABLED(FTM_UNIFIED_BWS)
4497-
#error "FT_MOTION requires FTM_UNIFIED_BWS to be enabled because FBS is not yet implemented."
44984497
#endif
44994498
#if !HAS_X_AXIS
45004499
static_assert(FTM_DEFAULT_SHAPER_X != ftMotionShaper_NONE, "Without any linear axes FTM_DEFAULT_SHAPER_X must be ftMotionShaper_NONE.");

0 commit comments

Comments
 (0)