mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 07:11:06 -04:00
feat(posts): trigger the Cincinnati safety head raise by rapid length
The safety raise (M47 P<SafetyHeadraiseDistance>) used to fire only when the next part had a different drawing name, which has nothing to do with crash risk: a long rapid between copies of the same part got a plain M47, while a short hop between neighbouring different drawings got the full raise. Sheets are rarely flat (5/8" plate can be ~1.5" out of flat within supplier tolerance), and longer rapids cross more of that bow. Add SafetyHeadraiseRapidDistance (program units, default 12"): any rapid to the next pierce longer than it takes the safety raise, regardless of drawing. Unknown travel never does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
efa4844049
commit
abfc1a714a
11 files changed
+77
-51
No files matched your search
@@ -18,12 +18,6 @@ public sealed class FeatureContext
|
||||
public bool IsFirstFeatureOfPart { get; set; }
|
||||
public bool IsLastFeatureOnSheet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True when the rapid after this feature goes to a different part, so its head
|
||||
/// raise is the safety head raise.
|
||||
/// </summary>
|
||||
public bool IsSafetyHeadraise { get; set; }
|
||||
|
||||
/// <summary>True when this feature cuts the part's exterior (selects ExteriorM47).</summary>
|
||||
public bool IsExteriorFeature { get; set; }
|
||||
public bool IsEtch { get; set; }
|
||||
@@ -32,8 +26,8 @@ public sealed class FeatureContext
|
||||
public double SheetDiagonal { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Rapid travel from this feature's end to the next pierce, used by
|
||||
/// <see cref="M47Mode.Auto"/>. Null when unknown.
|
||||
/// Rapid travel from this feature's end to the next pierce, used by the safety
|
||||
/// head raise and <see cref="M47Mode.Auto"/>. Null when unknown.
|
||||
/// </summary>
|
||||
public double? RapidDistance { get; set; }
|
||||
|
||||
@@ -332,12 +326,7 @@ public sealed class CincinnatiFeatureWriter
|
||||
|
||||
private void WriteM47(TextWriter writer, FeatureContext ctx)
|
||||
{
|
||||
var line = CincinnatiHeadRaise.Line(
|
||||
_config,
|
||||
ctx.IsSafetyHeadraise,
|
||||
ctx.IsExteriorFeature,
|
||||
ctx.RapidDistance
|
||||
);
|
||||
var line = CincinnatiHeadRaise.Line(_config, ctx.IsExteriorFeature, ctx.RapidDistance);
|
||||
if (line != null)
|
||||
writer.WriteLine(line);
|
||||
}
|
||||
|
||||
@@ -5,19 +5,13 @@ namespace OpenNest.Posts.Cincinnati;
|
||||
/// </summary>
|
||||
internal static class CincinnatiHeadRaise
|
||||
{
|
||||
/// <param name="isSafetyHeadraise">True when the rapid goes to a different part.</param>
|
||||
/// <param name="isExterior">True when the feature just cut is a part exterior.</param>
|
||||
/// <param name="rapidDistance">Travel to the next pierce; null when unknown.</param>
|
||||
/// <returns>The block to write, or null for no head raise.</returns>
|
||||
internal static string Line(
|
||||
CincinnatiPostConfig config,
|
||||
bool isSafetyHeadraise,
|
||||
bool isExterior,
|
||||
double? rapidDistance
|
||||
)
|
||||
internal static string Line(CincinnatiPostConfig config, bool isExterior, double? rapidDistance)
|
||||
{
|
||||
if (isSafetyHeadraise && config.SafetyHeadraiseDistance.HasValue)
|
||||
return $"M47 P{config.SafetyHeadraiseDistance.Value} (Safety Headraise)";
|
||||
if (IsSafetyRapid(config, rapidDistance))
|
||||
return SafetyLine(config);
|
||||
|
||||
var mode = isExterior ? config.ExteriorM47 : config.InteriorM47;
|
||||
return mode switch
|
||||
@@ -29,6 +23,19 @@ internal static class CincinnatiHeadRaise
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// True when the rapid is long enough to cross warped plate, so it takes the
|
||||
/// safety head raise. Unknown travel never does.
|
||||
/// </summary>
|
||||
internal static bool IsSafetyRapid(CincinnatiPostConfig config, double? rapidDistance) =>
|
||||
config.SafetyHeadraiseDistance.HasValue
|
||||
&& config.SafetyHeadraiseRapidDistance is { } threshold
|
||||
&& rapidDistance is { } distance
|
||||
&& distance > threshold;
|
||||
|
||||
internal static string SafetyLine(CincinnatiPostConfig config) =>
|
||||
$"M47 P{config.SafetyHeadraiseDistance.Value} (Safety Headraise)";
|
||||
|
||||
// Unknown travel, or no threshold configured, always gets the full raise.
|
||||
private static bool IsLongRapid(CincinnatiPostConfig config, double? rapidDistance) =>
|
||||
config.M47OverrideDistanceThreshold is not { } threshold
|
||||
|
||||
@@ -17,9 +17,9 @@ internal static class CincinnatiHoleCallWriter
|
||||
/// Unmapped calls fall back to the call's own id.
|
||||
/// </param>
|
||||
/// <param name="partName">Part-name comment to emit when the call opens a part, else null.</param>
|
||||
/// <param name="isSafetyHeadraise">
|
||||
/// True when the call is a part's first feature after another part, matching the
|
||||
/// feature writer's safety head raise.
|
||||
/// <param name="rapidDistance">
|
||||
/// Travel from the call to the next pierce, which selects the safety head raise;
|
||||
/// null when unknown.
|
||||
/// </param>
|
||||
internal static void Write(
|
||||
TextWriter w,
|
||||
@@ -31,7 +31,7 @@ internal static class CincinnatiHoleCallWriter
|
||||
CoordinateFormatter fmt,
|
||||
IReadOnlyDictionary<Program, int> holeSubprograms,
|
||||
string partName = null,
|
||||
bool isSafetyHeadraise = false
|
||||
double? rapidDistance = null
|
||||
)
|
||||
{
|
||||
var postSubNum =
|
||||
@@ -66,8 +66,8 @@ internal static class CincinnatiHoleCallWriter
|
||||
if (isLastFeature)
|
||||
return;
|
||||
|
||||
if (isSafetyHeadraise && config.SafetyHeadraiseDistance.HasValue)
|
||||
w.WriteLine($"M47 P{config.SafetyHeadraiseDistance.Value} (Safety Headraise)");
|
||||
if (CincinnatiHeadRaise.IsSafetyRapid(config, rapidDistance))
|
||||
w.WriteLine(CincinnatiHeadRaise.SafetyLine(config));
|
||||
else
|
||||
w.WriteLine("M47");
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ public sealed class CincinnatiPartSubprogramWriter
|
||||
PartName = drawingName,
|
||||
IsFirstFeatureOfPart = false,
|
||||
IsLastFeatureOnSheet = isLastFeature,
|
||||
IsSafetyHeadraise = false,
|
||||
IsExteriorFeature = exterior[i],
|
||||
IsEtch = isEtch,
|
||||
LibraryFile = isEtch ? etchLibrary : cutLibrary,
|
||||
|
||||
@@ -180,10 +180,17 @@ namespace OpenNest.Posts.Cincinnati
|
||||
[Category("7. Safety")]
|
||||
[DisplayName("Safety Headraise Distance")]
|
||||
[Description(
|
||||
"Safety head raise distance in machine units, posted as M47 P<distance> before the rapid to a different part. Null = disabled."
|
||||
"Safety head raise distance in machine units, posted as M47 P<distance> before rapids longer than the safety headraise rapid distance. Null = disabled."
|
||||
)]
|
||||
public int? SafetyHeadraiseDistance { get; set; } = 2000;
|
||||
|
||||
[Category("7. Safety")]
|
||||
[DisplayName("Safety Headraise Rapid Distance")]
|
||||
[Description(
|
||||
"Rapids to the next pierce longer than this get the safety head raise instead of the M47 mode's raise, so the head clears warped plate. Program units. Null = disabled."
|
||||
)]
|
||||
public double? SafetyHeadraiseRapidDistance { get; set; } = 12.0;
|
||||
|
||||
[Category("8. Pallet")]
|
||||
[DisplayName("Pallet Exchange")]
|
||||
[Description("When pallet exchange occurs (None, EndOfSheet, or StartAndEnd).")]
|
||||
|
||||
@@ -210,9 +210,8 @@ public sealed class CincinnatiSheetWriter
|
||||
var next = i + 1 < items.Count ? items[i + 1] : null;
|
||||
var isLastFeature = next == null;
|
||||
|
||||
// A head raise belongs before the rapid that leaves this item, so the safety
|
||||
// raise goes on a part's last item when a different part follows.
|
||||
var isSafetyHeadraise = next != null && next.Part.BaseDrawing.Name != partName;
|
||||
// A head raise belongs before the rapid that leaves this item; its travel
|
||||
// decides whether that raise is the safety raise.
|
||||
double? rapidDistance =
|
||||
next == null
|
||||
? null
|
||||
@@ -228,7 +227,6 @@ public sealed class CincinnatiSheetWriter
|
||||
item,
|
||||
i,
|
||||
partName,
|
||||
isSafetyHeadraise,
|
||||
rapidDistance,
|
||||
isLastFeature
|
||||
);
|
||||
@@ -250,7 +248,7 @@ public sealed class CincinnatiSheetWriter
|
||||
_fmt,
|
||||
_holeSubprograms,
|
||||
isFirstFeatureOfPart ? partName : null,
|
||||
isSafetyHeadraise
|
||||
rapidDistance
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -262,7 +260,6 @@ public sealed class CincinnatiSheetWriter
|
||||
PartName = partName,
|
||||
IsFirstFeatureOfPart = isFirstFeatureOfPart,
|
||||
IsLastFeatureOnSheet = isLastFeature,
|
||||
IsSafetyHeadraise = isSafetyHeadraise,
|
||||
IsExteriorFeature = item.IsExterior,
|
||||
IsEtch = item.IsEtch,
|
||||
LibraryFile = item.IsEtch ? etchLibrary : cutLibrary,
|
||||
@@ -296,7 +293,6 @@ public sealed class CincinnatiSheetWriter
|
||||
SheetItem item,
|
||||
int index,
|
||||
string partName,
|
||||
bool isSafetyHeadraise,
|
||||
double? rapidDistance,
|
||||
bool isLastPart
|
||||
)
|
||||
@@ -325,7 +321,7 @@ public sealed class CincinnatiSheetWriter
|
||||
|
||||
// One head raise covers the rapid back and the rapid on. The part is complete,
|
||||
// so the raise follows the exterior M47 mode.
|
||||
var raise = CincinnatiHeadRaise.Line(_config, isSafetyHeadraise, true, rapidDistance);
|
||||
var raise = CincinnatiHeadRaise.Line(_config, true, rapidDistance);
|
||||
if (raise != null)
|
||||
w.WriteLine(raise);
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"ExteriorM47": "Always",
|
||||
"M47OverrideDistanceThreshold": null,
|
||||
"SafetyHeadraiseDistance": 2000,
|
||||
"SafetyHeadraiseRapidDistance": 12.0,
|
||||
"PalletExchange": "EndOfSheet",
|
||||
"LeadInFeedratePercent": 0.5,
|
||||
"LeadInArcLine2FeedratePercent": 0.5,
|
||||
|
||||
Reference in new issue
Block a user