Class StepFeedSolver
Runner-agnostic per-step feed solver core of the NC optimization process: computes per-step feed adjustments from milling physics (force / yielding / spindle torque / spindle power / thermal yield / custom criteria and relief-face collision), constrains them over extended segments, propagates acceleration limits backward, and builds tool deflection compensation.
public class StepFeedSolver
- Inheritance
-
StepFeedSolver
- Inherited Members
- Extension Methods
Remarks
Ported from HiNc NcOptProc (frozen HardNc baseline):
extension-window walkers, force/feed-per-tooth solver family,
feed boundaries, BuildStepAdjustment(ICuttingPara, Dictionary<int, StepOptContext>, List<MachiningStep>, IProgress<IMessage>, CancellationToken, KeyValuePair<int, StepOptContext>, StepLuggage, StepBrief, StepAdjustmentLogger, SourceFloorOverTargetTally, SpindleWarningsSaid),
ParallelBuildStepAdjustments(ICuttingPara, Dictionary<int, StepOptContext>, List<MachiningStep>, Func<string, string>, IProgress<IMessage>, CancellationToken),
ConstrainIndividualFeedrate(ICuttingPara, MachiningToolHouse, bool, List<INcOptPiecePack>, List<MachiningStep>, Dictionary<int, StepOptContext>, IProgress<IMessage>),
BuildCompensation(ICuttingPara, List<INcOptPiecePack>, List<MachiningStep>, SortedList<int, NcOptOption>, IProgress<IMessage>)
and the acceleration family.
The two HardNc seams are parameterized: the stored step luggage is read
through a ReadBulkDelegate<TData> one segment of
StepLuggageSegmentSize step indices at a time, on the solver's
own thread before each parallel pass over the segment (was a
SequentialBulkReader<MillingStepLuggage>.GetStep per step from the
parallel workers, every call queued behind one lock), and the
per-source-file log path derivation is injected via a
Func<T, TResult> (was the HardNcUtil
[NcFile]/[NcName] template constants).
Constructors
StepFeedSolver(ReadBulkDelegate<StepLuggage>, ReadBulkDelegate<StepBrief>)
Ctor.
public StepFeedSolver(ReadBulkDelegate<StepLuggage> readStepLuggages, ReadBulkDelegate<StepBrief> readStepBriefs)
Parameters
readStepLuggagesReadBulkDelegate<StepLuggage>Reads the stored StepLuggage rows of a step index range,
[begin, end). Called on the solver's thread, never from a parallel worker, once per segment of StepLuggageSegmentSize indices the solver touches. A faulted read the delegate reports and answers null for leaves the segment's steps without luggage: a touched one keeps its simulated feedrate, as a step without a stored row does (one that cuts nothing is set no limit, as ever).readStepBriefsReadBulkDelegate<StepBrief>Reads the stored briefs' rows (StepBrief) of a step index range,
[begin, end), on the same terms, beside the luggage rows: a step's four physics constraints (yielding stress, spindle torque and power, thermal yield) read its stored force brief and sequential physics state, and the compensation pass's fast path reads its stored force brief – the brief-into-DB chain's C4a; the resident copies on the steps are not read. A step whose row the segment does not hold is asked itself (its creation cache, then the host); one without briefs anywhere has no physics constraint applied and no deflection to compensate, as a step without luggage keeps its simulated feed. A faulted read the delegate reports and answers null for is taken as a faulted luggage read is: the segment's touched steps keep their simulated feed in the feed solve (one that cuts nothing is set no limit, as ever), and in the compensation build a step of the segment whose destination feed is still its commanded one when the build runs is compensated with nothing – asked of nobody for their own copy either way, one report for the segment, not one per step.
Fields
StepLuggageSegmentSize
Step indices per read of the step cache: the solver groups the steps it works on into segments of this many indices (AlignedSegments(IEnumerable<int>, int)), reads each segment once into a dictionary and runs its parallel pass over that segment before it reads the next, so at most one segment's rows are held.
public const int StepLuggageSegmentSize = 2048
Field Value
Properties
CoreNum
Parallel computation thread num.
0 is special number to use all cores.
Wired from the HiNC:OptCoreNum configuration by
HiNcRclUtil alongside the legacy HardNc
NcOptProc.CoreNum.
public static int CoreNum { get; set; }
Property Value
EnableStepAdjustmentLog
Enable create log file for building individual StepAdjustment process.
Wired by the SessionShell.EnableIndividualStepAdjustmentLog
proxy setter alongside the legacy HardNc
NcOptProc.EnableIndividualStepAdjustmentLog.
public static bool EnableStepAdjustmentLog { get; set; }
Property Value
Methods
AccelerationConstrainAllFeedrate(List<INcOptPiecePack>, List<MachiningStep>, SortedList<int, NcOptOption>, Dictionary<int, INcOptPiecePack>, IProgress<IMessage>)
Constrain the feedrate of all steps by the maximum acceleration: walks every step forward and recursively propagates the acceleration limit backward when a step's feedrate cannot be reached.
public static void AccelerationConstrainAllFeedrate(List<INcOptPiecePack> piecePackList, List<MachiningStep> machiningSteps, SortedList<int, NcOptOption> stepIndexToSeedOptionSortedList, Dictionary<int, INcOptPiecePack> stepIndexToPackDictionary, IProgress<IMessage> mixedProgress)
Parameters
piecePackListList<INcOptPiecePack>The list of piece packs to process.
machiningStepsList<MachiningStep>The list of machining steps.
stepIndexToSeedOptionSortedListSortedList<int, NcOptOption>Sorted list mapping step index to seed optimization option.
stepIndexToPackDictionaryDictionary<int, INcOptPiecePack>Dictionary mapping step index to its owning pack. The packs here carry at least 1 step each.
mixedProgressIProgress<IMessage>The message host for logging.
BuildCompensation(ICuttingPara, List<INcOptPiecePack>, List<MachiningStep>, SortedList<int, NcOptOption>, IProgress<IMessage>)
Builds tool deflection compensation for every non-arc piece pack, writing each step's compensation vector into the PACK's own adjustment (StepAdjustmentList / StepAdjustment) — the object the writeback plan builder reads.
public void BuildCompensation(ICuttingPara millingPara, List<INcOptPiecePack> piecePackList, List<MachiningStep> machiningSteps, SortedList<int, NcOptOption> stepIndexToSeedOptionSortedList, IProgress<IMessage> mixedProgress)
Parameters
millingParaICuttingParaThe cutting parameters.
piecePackListList<INcOptPiecePack>The list of piece packs to process.
machiningStepsList<MachiningStep>The list of machining steps.
stepIndexToSeedOptionSortedListSortedList<int, NcOptOption>Sorted list mapping step index to seed optimization option.
mixedProgressIProgress<IMessage>The message host for logging.
Remarks
Fixed-handoff port of HiNc NcOptProc.BuildCompensation (frozen
HardNc baseline).
History note — the baseline carries a data-flow defect that is
deliberately NOT reproduced: it writes the compensation into the
StepAdjustment of the context dictionary
while its output generation reads the pack's own adjustment, whose
compensation stays null from construction — so HardNc never emitted a
compensated coordinate. This port redirects the assignment to the pack
adjustments, closing the handoff (the context/pack object separation
itself is intentional and stays, StepOptContext).
A second divergence follows from the redirect: the per-step fast path
compares MachineMotionStep.CommandedClFeedrate_mmds against the PACK
adjustment's post-flatten/acceleration DstFeedrate_mmds — the
value the writeback chain continues from — whereas the baseline
compared the context-side value those passes never touch. The pack
value is the saner recompute trigger: the simulated deflection is
reused exactly when the destination feedrate still equals the
simulated one.
Ported gates: arc packs are skipped whole (IsArc — arc lines never build compensation), PreservedPiecePack builds nothing, and a step only builds when its seed option's CompensationMask is non-zero. A mono pack's single shared adjustment is written per step (the last step wins), mirroring the baseline's build side; the writeback deliberately consumes compensation on splition fragments only (see StepAdjustment).
ConstrainIndividualFeedrate(ICuttingPara, MachiningToolHouse, bool, List<INcOptPiecePack>, List<MachiningStep>, Dictionary<int, StepOptContext>, IProgress<IMessage>)
Constrains individual feedrate for each step.
public static void ConstrainIndividualFeedrate(ICuttingPara millingPara, MachiningToolHouse millingToolHouse, bool isFlatConstraining, List<INcOptPiecePack> piecePackList, List<MachiningStep> machiningSteps, Dictionary<int, StepOptContext> stepIndexToStepOptContextDictionary, IProgress<IMessage> mixedProgress)
Parameters
millingParaICuttingParaThe cutting parameters.
millingToolHouseMachiningToolHouseThe machining tool house.
isFlatConstrainingboolFlat constraining process is the pre-process that constrains neighbor steps to the same feedrate; non-flat constraining process is the post-process.
piecePackListList<INcOptPiecePack>The list of piece packs to process.
machiningStepsList<MachiningStep>The list of machining steps.
stepIndexToStepOptContextDictionaryDictionary<int, StepOptContext>Dictionary mapping step index to optimization context.
mixedProgressIProgress<IMessage>The message host for logging.
GetIndexByPostDistance(List<MachiningStep>, int, double)
Get index by post distance.
The index position is larger than the distance or is at end or is stepIndex.
Or the index is endIndex(size of the machiningSteps) or is stepIndex.
public static int GetIndexByPostDistance(List<MachiningStep> machiningSteps, int stepIndex, double extendedPostDistance)
Parameters
machiningStepsList<MachiningStep>All machining steps.
stepIndexintThe target step index the window extends from.
extendedPostDistancedoubleThe forward extension distance in mm.
Returns
- int
The walked index.
GetIndexByPreDistance(List<MachiningStep>, int, double)
Get index by pre-distance.
The position of index is before the distance. i.e. the distance is larger from extendedPreDistance.
Or the index is 0 or is stepIndex.
public static int GetIndexByPreDistance(List<MachiningStep> machiningSteps, int stepIndex, double extendedPreDistance)
Parameters
machiningStepsList<MachiningStep>All machining steps.
stepIndexintThe target step index the window extends from.
extendedPreDistancedoubleThe backward extension distance in mm.
Returns
- int
The walked index.
GetSourceFeedrateFloor_mmds(MachiningStep, NcOptOption)
The source-feedrate floor of a step in mm/s (EnableSourceFeedrateFloor): the option's ratio of the feedrate the source program commanded on the step. 0 — no floor — when the option is off, when feedrate optimization is off (the written feed is then the source's, so a floor could hold nothing and must not be logged or reported as holding anything), or when the step carries no usable commanded feedrate.
public static double GetSourceFeedrateFloor_mmds(MachiningStep machiningStep, NcOptOption ncOptOption)
Parameters
machiningStepMachiningStepThe machining step.
ncOptOptionNcOptOptionThe optimization option effective on the step.
Returns
- double
The floor in mm/s, or 0 for none.
GetTouchedFeedPerToothBoundary_mm(MachiningStep, NcOptOption)
Get the feed-per-tooth boundary in mm of a touched step by composing the option limits and the cutter optimization limits. If the composed limits conflict, the smallest wins (conservation principle).
public static Range<double> GetTouchedFeedPerToothBoundary_mm(MachiningStep machiningStep, NcOptOption ncOptOption)
Parameters
machiningStepMachiningStepThe machining step.
ncOptOptionNcOptOptionThe optimization option effective on the step.
Returns
Remarks
rapid is not concern
GetTouchedFeedrateBoundary_mmds(MachiningStep, NcOptOption)
Get the feedrate boundary in mm/s of a touched step. When the tool flute num is known the boundary derives from GetTouchedFeedPerToothBoundary_mm(MachiningStep, NcOptOption); otherwise from the option's plain feedrate limits.
public static Range<double> GetTouchedFeedrateBoundary_mmds(MachiningStep machiningStep, NcOptOption ncOptOption)
Parameters
machiningStepMachiningStepThe machining step.
ncOptOptionNcOptOptionThe optimization option effective on the step.
Returns
Remarks
rapid is not concern
ParallelBuildStepAdjustments(ICuttingPara, Dictionary<int, StepOptContext>, List<MachiningStep>, Func<string, string>, IProgress<IMessage>, CancellationToken)
Build the per-step StepAdjustment of every entry of
stepIndexToStepOptContextDictionary in parallel.
When EnableStepAdjustmentLog is on, one
.IndependentStepAdjustment.log file is created per source NC file; one that
cannot be opened throws out of the pass before its first step, the logs opened
before it shut.
public void ParallelBuildStepAdjustments(ICuttingPara millingPara, Dictionary<int, StepOptContext> stepIndexToStepOptContextDictionary, List<MachiningStep> machiningSteps, Func<string, string> getLogBaseFilePath, IProgress<IMessage> messageProgress, CancellationToken cancellationToken)
Parameters
millingParaICuttingParaThe cutting parameters.
stepIndexToStepOptContextDictionaryDictionary<int, StepOptContext>Dictionary mapping step index to optimization context.
machiningStepsList<MachiningStep>The raw strip-pose step projection, UNFILTERED, in strip order (position ==
MachiningStep.StepIndex; entries may be null).getLogBaseFilePathFunc<string, string>Maps a source NC file path to the absolute base output path of its adjustment log; the solver appends the
.IndependentStepAdjustment.logsuffix. This is the runner-agnostic replacement for the HardNc[NcFile]/[NcName]template constants —Hi.Common.PathUtils.PathUtil.GetPathByTemplatemay be used by the caller with its own keyword strings.messageProgressIProgress<IMessage>The message host for logging.
cancellationTokenCancellationTokenEnds the pass at the next segment or step without throwing: the steps it did not reach are left unsolved, the adjustment logs are shut without the lines they still buffer, and the pass closes with
NcOpt-Feed–Canceledwhere a completed one closes withNcOpt-Feed–Built.
Remarks
Step-index key space: every step-keyed collection here — the context
dictionary keys, the logger seed sets (built from
StepIndex) and the
Enqueue(int, string) keys (the dictionary entry
keys) — lives in ONE space: the step's position in
machiningSteps, which equals the intrinsic
MachiningStep.StepIndex (the strip pos index) because the list
is the raw unfiltered strip-pose projection (mirrors the oracle,
NcOptProc). Null-step tolerance likewise mirrors the
oracle: steps are read directly with no extra null guards, exactly as
the oracle reads them.