Archived
deploy webservice static-file routing for docsite folder URLs, per-instance step-cache db, and constant-height panel title bars.
This commit is contained in:
@@ -104,6 +104,10 @@
|
||||
Simulate --> Map --> Train --> Evaluate --> Apply
|
||||
</code></pre>
|
||||
<h2 id="1-prerequisites">1. Prerequisites</h2>
|
||||
<div class="TIP">
|
||||
<h5>Tip</h5>
|
||||
<p>For the complete data-collection checklist behind a project, see <a href="../manual/setup/project-data-checklist.html">Project Data Checklist</a>.</p>
|
||||
</div>
|
||||
<p>Before training you need:</p>
|
||||
<table>
|
||||
<thead>
|
||||
@@ -131,6 +135,10 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="IMPORTANT">
|
||||
<h5>Important</h5>
|
||||
<p>Before training, the workpiece + fixture must be correctly placed relative to the work offset, otherwise the simulated engagement (and therefore the trained coefficients) is wrong. See <a href="../manual/setup/program-zero-alignment.html">Program Zero Alignment</a> — particularly the high-fidelity caution that the G54 used must reflect the <strong>real</strong> machine offset, and the rough-resolution check for catching a wrong setup at the opening plunge.</p>
|
||||
</div>
|
||||
<h3 id="sensor-data-file-format">Sensor Data File Format</h3>
|
||||
<p>The CSV must contain a header row with <code>ActualTime</code> and at least one force/torque channel:</p>
|
||||
<table>
|
||||
@@ -180,12 +188,52 @@ MachiningMotionResolution = FeedPerTooth;
|
||||
<pre><code class="lang-csharp">EnablePhysics = true;
|
||||
</code></pre>
|
||||
<h3 id="milling-force-cycle-division">Milling Force Cycle Division</h3>
|
||||
<p>Set the number of angular divisions per revolution before training. Higher values yield more accurate phase alignment:</p>
|
||||
<pre><code class="lang-csharp">MillingForceCycleDivisionNum = 360;
|
||||
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_MillingCycleDivisionNum">MillingCycleDivisionNum</a> is the number of angular divisions per spindle revolution used by the force evaluation. <strong>The default is 36, which is intended for normal simulation</strong> — force playback does not benefit from a finer division, and raising it only slows the physics down. <strong>Training is the exception</strong>: phase alignment and coefficient quality improve with a finer division, so set it in the training script:</p>
|
||||
<pre><code class="lang-csharp">MillingCycleDivisionNum = 180; // training only; default 36 is for normal simulation
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>This must be set <strong>before</strong> executing <code>TrainMillingPara</code>. A larger value produces a more accurate <code>AngleOffset</code> result and better milling coefficients.</p>
|
||||
<p>This must be set <strong>before</strong> the simulation run that <code>TrainMillingPara</code> consumes.</p>
|
||||
</div>
|
||||
<p><strong>How much is enough — measured (2-flute D8, Al6061-T6, <code>MachiningResolution_mm</code> 0.03125, sensor series sampled at 0.1 ms):</strong></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><code>MillingCycleDivisionNum</code></th>
|
||||
<th>R</th>
|
||||
<th>Fc error @ t=0.2</th>
|
||||
<th>Fn error @ t=0.2</th>
|
||||
<th>ploughing coefficients</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>36 (default)</td>
|
||||
<td>91.5 %</td>
|
||||
<td>−6.7 %</td>
|
||||
<td>−8.8 %</td>
|
||||
<td>badly off (Kpc +40 %)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>180</strong></td>
|
||||
<td><strong>95.2 %</strong></td>
|
||||
<td><strong>−6.6 %</strong></td>
|
||||
<td><strong>−6.1 %</strong></td>
|
||||
<td>Kpc +10 %</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>720</td>
|
||||
<td>95.2 %</td>
|
||||
<td>−6.9 %</td>
|
||||
<td>−6.3 %</td>
|
||||
<td>Kpc +11 %</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>180 is the sweet spot: the default 36 is genuinely too coarse for training (the ploughing coefficients degrade badly), and 720 buys nothing while costing 4× the physics.</strong> Do not assume “larger is always better”.</p>
|
||||
<div class="WARNING">
|
||||
<h5>Warning</h5>
|
||||
<p>The value is <strong>process-wide, not per-project</strong>: it is not saved into the <code>.hincproj</code>, and it survives <code>ResetRuntime()</code> and project switches. Two consequences: (a) a training script must always set it explicitly — a fresh service instance starts at 36; (b) after training, the same instance keeps the large value, so subsequent normal simulations run slower until you set it back (or restart the instance).</p>
|
||||
</div>
|
||||
<hr>
|
||||
<h2 id="3-configure-data-mapping">3. Configure Data Mapping</h2>
|
||||
@@ -207,12 +255,94 @@ Offset options: <code>null</code>, <code>ShiftTime_s(<seconds>)</code>, <c
|
||||
<p>When you have both controller data and sensor data:</p>
|
||||
<pre><code class="lang-csharp">PlayNcFile("NC/machining.nc");
|
||||
MapSingleByCsvFile("Data/controller.csv"); // maps FileNo/LineNo → ActualTime
|
||||
MapSeriesByCsvFile("Data/sensor.csv"); // maps ActualTime → sensor series
|
||||
MapSeriesByCsvFile("Data/sensor.csv"); // ActualTime → sensor series
|
||||
</code></pre>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p><strong>Why two-layer mapping?</strong> Running the NC through the system interpreter produces more accurate simulation paths than direct CSV playback. The controller data bridges simulation steps to real time via <code>FileNo</code>/<code>LineNo</code>, and the sensor data bridges real time to force/torque readings.</p>
|
||||
</div>
|
||||
<h3 id="-train-on-the-steady-part-of-the-cut--it-is-the-largest-single-lever">⚠ Train on the steady part of the cut — it is the largest single lever</h3>
|
||||
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_MapSeriesByCsvFile_">MapSeriesByCsvFile</a> pairs each step with a window of sensor
|
||||
samples. The window is anchored at the step's <strong>end</strong> time and runs forward for one cycle period, so
|
||||
the samples a step is fitted against are the ones its <strong>neighbours</strong> produced, never its own.</p>
|
||||
<p><strong>While the cut is steady, that costs nothing.</strong> A neighbouring step cutting the same arc at the
|
||||
same chip load produces, at a given rotation angle, the same force this step would have produced, so
|
||||
the borrowed samples are extra data rather than extra error. The pairing turns into a systematic
|
||||
bias only where the <strong>cutter–workpiece engagement changes across the window</strong> — cutter entry, pass
|
||||
exit, corners, depth changes.</p>
|
||||
<p>Measured on the D8 2-flute Al6061-T6 case (one source file at a 1 ms sampling period; only the
|
||||
training set and the <code>CycleSamplingMode</code> window vary):</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>training set</th>
|
||||
<th>window</th>
|
||||
<th>Fc error @ t=0.2</th>
|
||||
<th>Fn error @ t=0.2</th>
|
||||
<th>R</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>whole path (1076 cutting steps)</td>
|
||||
<td><code>SpindleCycle</code> (default)</td>
|
||||
<td>−9.3 %</td>
|
||||
<td>−9.9 %</td>
|
||||
<td>94.3 %</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>whole path</td>
|
||||
<td><code>FluteCycle</code></td>
|
||||
<td>−7.1 %</td>
|
||||
<td>−8.1 %</td>
|
||||
<td>95.7 %</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>steady part only (~800 steps)</strong></td>
|
||||
<td><code>SpindleCycle</code> (default)</td>
|
||||
<td><strong>−3.3 %</strong></td>
|
||||
<td><strong>−2.3 %</strong></td>
|
||||
<td><strong>98.5 %</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>steady part only (~800 steps)</strong></td>
|
||||
<td><code>FluteCycle</code></td>
|
||||
<td><strong>−3.2 %</strong></td>
|
||||
<td><strong>−2.4 %</strong></td>
|
||||
<td><strong>98.6 %</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Two things to read off it. First, <strong>restricting training to the steady part is worth more than any
|
||||
other setting</strong> — here it more than halved the error, and did so at the coarsest sampling period.
|
||||
Second, <strong>once the transient is gone the window choice stops mattering</strong> (0.06 percentage points
|
||||
between the two modes, versus 2.2 on the whole path): <code>FluteCycle</code>'s advantage on the whole path was
|
||||
only ever a shorter exposure to the entry and exit ramps. Keep the <code>SpindleCycle</code> default and its
|
||||
larger sample count.</p>
|
||||
<p>In this case the transient was 272 of the 1076 cutting steps: the entry ramp, where the radial
|
||||
engagement builds from 0.09 mm to the nominal 2 mm, and the pass exit, where it climbs to 5 mm as
|
||||
the cutter runs off the far corner. Select the training section by requiring the engagement to be
|
||||
constant — <code>CuttingWidth_mm</code> and <code>CuttingDepth_mm</code> steady across neighbouring steps — rather than by
|
||||
eyeballing the toolpath.</p>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p><strong>Gaps in the sensor data are handled.</strong> A step whose pairing window contains no measured row —
|
||||
an acquisition dropout, or rows removed to keep the steady section only — is excluded from the
|
||||
mapping, and a single <code>Map-ShotGap--StepsSkipped</code> warning reports how many steps were skipped.
|
||||
A window-edge row is only interpolated when the rows bracketing the edge span at most two
|
||||
spindle revolutions; rows farther apart sit across a gap, and no value is fabricated from them.
|
||||
Watch for that warning after mapping measured data: a large count means the acquisition and the
|
||||
play do not overlap the way you think they do.</p>
|
||||
</div>
|
||||
<div class="WARNING">
|
||||
<h5>Warning</h5>
|
||||
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_MachiningResolution_mm">MachiningResolution_mm</a> must not be too coarse for
|
||||
training: at 1/16 of the cutter diameter and coarser (D8 case: 0.0625 and 0.125), usable
|
||||
samples dropped by half and the phase pairing degraded badly — at 0.0625 it failed to
|
||||
recognise one of the six cutting passes outright, and coefficients came out wildly wrong
|
||||
(Fc −12 % to −33 %). Around 1/256 of the diameter (0.03125 here) the result saturates;
|
||||
refining further showed no benefit.</p>
|
||||
</div>
|
||||
<hr>
|
||||
<h2 id="4-run-simulation">4. Run Simulation</h2>
|
||||
<pre><code class="lang-csharp">PlayNcFile("NC/file1.nc");
|
||||
@@ -230,9 +360,46 @@ MapSeriesByCsvFile("Data/sensor.csv"); // maps ActualTime → se
|
||||
<h2 id="5-export-simulation-data">5. Export Simulation Data</h2>
|
||||
<p>Export step data and waveform data for analysis:</p>
|
||||
<pre><code class="lang-csharp">WriteStepFiles("Output/[NcName].step.csv");
|
||||
WriteShotFiles("Output/[NcName].shot.csv", 1);
|
||||
WriteShotFiles("Output/[NcName].shot.csv", 0.1); // 2nd arg = sampling period in ms
|
||||
</code></pre>
|
||||
<p>The shot file contains time-resolved force columns: <code>Tool.Fx/Fy/Fz</code>, <code>Workpiece.Fx/Fy/Fz</code>, <code>Spindle.Mx/My/Mz</code>.</p>
|
||||
<h3 id="-the-shot-sampling-period-is-the-dominant-accuracy-lever">⚠ The shot sampling period is the dominant accuracy lever</h3>
|
||||
<p>The second argument of <a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_WriteShotFiles_">WriteShotFiles</a> is the sampling period in <strong>milliseconds</strong>, and when a simulated shot file is fed back into training it — not the angular division count, not the machining resolution — sets the accuracy ceiling. Each row is interpolated from the per-division force waveform, so the information per revolution is <code>min(MillingCycleDivisionNum, samples per revolution)</code>, where</p>
|
||||
<pre><code>samples per revolution = 60000 / (rpm × samplingPeriod_ms)
|
||||
</code></pre>
|
||||
<p>Measured on the same case (2-flute D8, Al6061-T6, <code>MachiningResolution_mm</code> 0.03125, S1270 → one revolution = 47.2 ms):</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>sampling period</th>
|
||||
<th>samples / rev</th>
|
||||
<th>R</th>
|
||||
<th>Fc error @ t=0.2</th>
|
||||
<th>Fn error @ t=0.2</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1 ms</td>
|
||||
<td>47</td>
|
||||
<td>94.2 %</td>
|
||||
<td>−9.3 %</td>
|
||||
<td>−9.9 %</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>0.1 ms</strong></td>
|
||||
<td><strong>472</strong></td>
|
||||
<td><strong>95.2 %</strong></td>
|
||||
<td><strong>−6.6 %</strong></td>
|
||||
<td><strong>−6.1 %</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>At 1 ms the waveform is sampled only ~47×/rev, and raising <code>MillingCycleDivisionNum</code> from 180 to 720 changes nothing because the extra grid points are pure interpolation of the same data. <strong>Pick the sampling period first</strong>: for training on simulated data use a period at or below the division period (<code>60000 / (rpm × MillingCycleDivisionNum)</code> ms); when comparing against a real measurement, match the sampling period to the physical DAQ rate, otherwise the two sides carry different information densities and the comparison is biased.</p>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p>A fine period makes large files — the case above went from 13 MB at 1 ms to 128 MB at 0.1 ms for a 6-cut program. Budget disk accordingly, and do not commit such files to a repository.</p>
|
||||
</div>
|
||||
<p>For coordinate system explanations, see <a href="../manual/analysis/milling-physics-coordinates.html">Milling Physics Coordinates</a>.</p>
|
||||
<hr>
|
||||
<h2 id="6-train-milling-parameters">6. Train Milling Parameters</h2>
|
||||
@@ -335,7 +502,7 @@ WriteShotFiles("Output/[NcName].shot.csv", 1);
|
||||
<h2 id="complete-script-example">Complete Script Example</h2>
|
||||
<pre><code class="lang-csharp">MachiningResolution_mm = 0.0625;
|
||||
EnablePhysics = true;
|
||||
MillingForceCycleDivisionNum = 360;
|
||||
MillingCycleDivisionNum = 180; // training only; default 36 suits normal simulation, 720 buys nothing
|
||||
|
||||
ClearTimeMappingData();
|
||||
AddTimeDataByFile("lineA", "Mapping/sensor1.csv", "18:25:51.7100", "18:26:12.9910");
|
||||
@@ -347,7 +514,7 @@ TrainMillingPara(Fx|Fy|Fz, "MillingPara/trained.mp");
|
||||
LoadCuttingParaByFile("MillingPara/trained.mp");
|
||||
|
||||
WriteStepFiles("Output/[NcName].step.csv");
|
||||
WriteShotFiles("Output/[NcName].shot.csv", 1);
|
||||
WriteShotFiles("Output/[NcName].shot.csv", 0.1);
|
||||
</code></pre>
|
||||
<h2 id="see-also">See Also</h2>
|
||||
<ul>
|
||||
|
||||
Reference in New Issue
Block a user