@@ -99,6 +99,7 @@ void HangprinterKinematics::Init() noexcept
99
99
constexpr float DefaultTorqueConstants[HANGPRINTER_AXES] = { 0 .0F };
100
100
101
101
ARRAY_INIT (anchors, DefaultAnchors);
102
+ anchorMode = HangprinterAnchorMode::LastOnTop;
102
103
printRadius = DefaultPrintRadius;
103
104
spoolBuildupFactor = DefaultSpoolBuildupFactor;
104
105
ARRAY_INIT (spoolRadii, DefaultSpoolRadii);
@@ -229,6 +230,12 @@ bool HangprinterKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
229
230
}
230
231
else if (mCode == 666 )
231
232
{
233
+ // 0=None, 1=last-top, 2=all-top, 3-half-top, etc
234
+ uint32_t unsignedAnchorMode = (uint32_t )anchorMode;
235
+ gb.TryGetUIValue (' T' , unsignedAnchorMode, seen);
236
+ if (unsignedAnchorMode <= (uint32_t )HangprinterAnchorMode::AllOnTop) {
237
+ anchorMode = (HangprinterAnchorMode)unsignedAnchorMode;
238
+ }
232
239
gb.TryGetFValue (' Q' , spoolBuildupFactor, seen);
233
240
gb.TryGetFloatArray (' R' , HANGPRINTER_AXES, spoolRadii, seen);
234
241
gb.TryGetUIArray (' U' , HANGPRINTER_AXES, mechanicalAdvantage, seen);
@@ -248,7 +255,7 @@ bool HangprinterKinematics::Configure(unsigned int mCode, GCodeBuffer& gb, const
248
255
}
249
256
else
250
257
{
251
- reply.printf (" M666 Q%.4f\n " , (double )spoolBuildupFactor);
258
+ reply.printf (" M666 T%u Q%.4f\n " , ( unsigned )anchorMode , (double )spoolBuildupFactor);
252
259
reply.lcat (" R:Spool r " );
253
260
for (size_t i = 0 ; i < HANGPRINTER_AXES; ++i)
254
261
{
@@ -470,25 +477,51 @@ static bool isSameSide(float const v0[3], float const v1[3], float const v2[3],
470
477
return dot0*dot1 > 0 .0F ;
471
478
}
472
479
473
- // For each triangle side in a pseudo-pyramid, check if the point is inside the pyramid (Except for the base)
474
- // Also check that any point below the line between two exterior anchors (all anchors are exterior except for the last one)
475
- // is in the "inside part" all the way down to min_Z, however low it may be.
476
- // To further limit the movements in the X and Y axes one can simply set a smaller print radius.
477
- bool HangprinterKinematics::IsReachable (float axesCoords[MaxAxes], AxesBitmap axes) const noexcept /* override*/
480
+ bool HangprinterKinematics::IsInsidePyramidSides (float const coords[3 ]) const noexcept
478
481
{
479
- float const coords[3 ] = {axesCoords[X_AXIS], axesCoords[Y_AXIS], axesCoords[Z_AXIS]};
480
482
bool reachable = true ;
481
483
482
484
// Check all the planes defined by triangle sides in the pyramid
483
485
for (size_t i = 0 ; reachable && i < HANGPRINTER_AXES - 1 ; ++i) {
484
486
reachable = reachable && isSameSide (anchors[i], anchors[(i+1 ) % (HANGPRINTER_AXES - 1 )], anchors[HANGPRINTER_AXES - 1 ], anchors[(i+2 ) % (HANGPRINTER_AXES - 1 )], coords);
485
487
}
488
+ return reachable;
489
+ }
490
+
491
+ bool HangprinterKinematics::IsInsidePrismSides (float const coords[3 ], unsigned const discount_last) const noexcept
492
+ {
493
+ bool reachable = true ;
486
494
487
495
// For each side of the base, check the plane formed by side and another point bellow them in z.
488
- for (size_t i = 0 ; reachable && i < HANGPRINTER_AXES - 1 ; ++i) {
496
+ for (size_t i = 0 ; reachable && i < HANGPRINTER_AXES - discount_last ; ++i) {
489
497
float const lower_point[3 ] = {anchors[i][0 ], anchors[i][1 ], anchors[i][2 ] - 1 };
490
498
reachable = reachable && isSameSide (anchors[i], anchors[(i+1 ) % (HANGPRINTER_AXES - 1 )], lower_point, anchors[(i+2 ) % (HANGPRINTER_AXES - 1 )], coords);
491
499
}
500
+ return reachable;
501
+ }
502
+
503
+ // For each triangle side in a pseudo-pyramid, check if the point is inside the pyramid (Except for the base)
504
+ // Also check that any point below the line between two exterior anchors (all anchors are exterior except for the last one)
505
+ // is in the "inside part" all the way down to min_Z, however low it may be.
506
+ // To further limit the movements in the X and Y axes one can simply set a smaller print radius.
507
+ bool HangprinterKinematics::IsReachable (float axesCoords[MaxAxes], AxesBitmap axes) const noexcept /* override*/
508
+ {
509
+ float const coords[3 ] = {axesCoords[X_AXIS], axesCoords[Y_AXIS], axesCoords[Z_AXIS]};
510
+ bool reachable = true ;
511
+
512
+ switch (anchorMode) {
513
+ case HangprinterAnchorMode::None:
514
+ return true ;
515
+
516
+ // This reaches a pyramid on top of the lower prism if the bed is below the lower anchors
517
+ case HangprinterAnchorMode::LastOnTop:
518
+ default :
519
+ reachable = reachable && IsInsidePyramidSides (coords);
520
+ reachable = reachable && IsInsidePrismSides (coords, 1 );
521
+
522
+ case HangprinterAnchorMode::AllOnTop:
523
+ reachable = reachable && IsInsidePrismSides (coords, 0 );
524
+ };
492
525
493
526
return reachable;
494
527
}
@@ -612,7 +645,7 @@ bool HangprinterKinematics::WriteCalibrationParameters(FileStore *f) const noexc
612
645
ok = f->Write (scratchString.c_str ());
613
646
if (!ok) return false ;
614
647
615
- scratchString.printf (" M666 Q%.6f " , (double )spoolBuildupFactor);
648
+ scratchString.printf (" M666 T%u Q%.6f " , ( unsigned )anchorMode , (double )spoolBuildupFactor);
616
649
ok = f->Write (scratchString.c_str ());
617
650
if (!ok) return false ;
618
651
0 commit comments