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:
2026-08-27 14:51:37 +08:00
parent 1fc510af5e
commit 2a98ae7556
1468 changed files with 182837 additions and 18888 deletions
@@ -88,6 +88,7 @@
<h1 id="workflow-basic-machining-simulation">Workflow: Basic Machining Simulation</h1>
<p>This workflow walks through setting up and running a machining simulation from scratch, including project configuration, option tuning, NC execution, and result inspection.</p>
<p>For the <em>method</em> of assembling one — build order, how to shape the mission, and the replay-and-read-the-messages acceptance test that says the project is finished — see <a href="project-construction.html">Project Construction</a>.</p>
<pre><code class="lang-mermaid">flowchart TD
Equipment[&quot;Set machine tool &amp;&lt;br&gt;controller brand/type&quot;]
Job[&quot;Set workpiece, fixture,&lt;br&gt;tool house, NC files,&lt;br&gt;controller offsets&quot;]
@@ -97,6 +98,57 @@
Equipment --&gt; Job --&gt; Option --&gt; Run --&gt; View
</code></pre>
<h2 id="starting-from-client-deliverables">Starting from Client Deliverables</h2>
<p>A real project usually starts from a bundle a customer hands over: NC programs, part/blank CAD, a tool sheet, sometimes a machine model and a few words about how the part is clamped and zeroed. Before building anything, reconcile that bundle against the <a href="../manual/setup/project-data-checklist.html">Project Data Checklist</a>, then map each item to the steps below:</p>
<table>
<thead>
<tr>
<th>Client deliverable</th>
<th>Maps to</th>
<th>Setup page</th>
</tr>
</thead>
<tbody>
<tr>
<td>NC programs (<code>.nc</code>, <code>.anc</code>, …)</td>
<td>NC files + controller brand</td>
<td><a href="../manual/setup/controller-iso.html">General NC Code Support</a></td>
</tr>
<tr>
<td>Tool sheet (diameters, corner radius, flute count, stick-out)</td>
<td>Tool House</td>
<td><a href="../manual/setup/cutter.html">Cutter</a>, <a href="../manual/setup/apt.html">APT</a></td>
</tr>
<tr>
<td>Part CAD + blank/stock CAD</td>
<td>Workpiece <code>IdealGeom</code> + <code>InitGeom</code></td>
<td><a href="../manual/setup/anchor.html">Anchor</a></td>
</tr>
<tr>
<td>Machine model + axis layout (3-axis, 3+1, 5-axis)</td>
<td>Machine tool kinematic chain</td>
<td><a href="../manual/setup/machine-tool.html">Machine Tool</a></td>
</tr>
<tr>
<td>&ldquo;Where is program zero?&rdquo; notes, work-offset list</td>
<td>Program zero + work-offset table</td>
<td><a href="../manual/setup/program-zero-alignment.html">Program Zero Alignment</a></td>
</tr>
<tr>
<td>Material name</td>
<td>Workpiece material + cutting parameters</td>
<td><a href="../manual/setup/project-data-checklist.html">Project Data Checklist</a></td>
</tr>
</tbody>
</table>
<div class="NOTE">
<h5>Note</h5>
<p>CAD geometry commonly arrives as <strong>STEP</strong> (<code>.step</code> / <code>.stp</code>). The workpiece and machine bodies are consumed as <strong>STL</strong> (or parametric primitives), so convert STEP to STL before import. The tool sheet's diameter and corner radius are authoritative; flute length, tooth count, helix, and stick-out are often missing and may have to be estimated from the spec string and confirmed with the client.</p>
</div>
<div class="TIP">
<h5>Tip</h5>
<p>When deliverables are incomplete (no blank CAD, unknown work offsets, unverified machine model), you can still stand up a <strong>rough</strong> project: use the NC tool diameters, the named material, a placeholder stock box that encloses the tool path, and an identity work offset — then run a coarse pass (see <a href="#31-workpiece-entity-resolution">§3.1</a>) to catch gross overcut/collision while you wait for the missing data. Record every assumed value so it can be confirmed later.</p>
</div>
<h2 id="1-set-machine-tool-and-controller">1. Set Machine Tool and Controller</h2>
<p>The machine tool and controller are fixed equipment that define the physical simulation environment.</p>
<h3 id="machine-tool">Machine Tool</h3>
@@ -108,6 +160,10 @@
<hr>
<h2 id="2-set-job-components">2. Set Job Components</h2>
<p>With equipment fixed, configure the job-specific components that change between simulations.</p>
<div class="TIP">
<h5>Tip</h5>
<p>For the full list of data to collect before building a project (and a customer-facing checklist), see <a href="../manual/setup/project-data-checklist.html">Project Data Checklist</a>.</p>
</div>
<h3 id="job-components">Job Components</h3>
<table>
<thead>
@@ -162,6 +218,10 @@ var fixture = Fixture;
<h5>Warning</h5>
<p>Each halving of mesh width can increase computation time and RAM by up to <strong>8x</strong>. Start with a coarser resolution and refine only when needed.</p>
</div>
<div class="NOTE">
<h5>Note</h5>
<p>Going <em>finer</em> is what costs the <strong>8x</strong> — and at the fine resolutions real NC machining needs, geometry removal is usually the bottleneck. Going <em>coarser</em> only saves time while geometry removal is the bottleneck. Once the mesh is coarse enough that geometry removal is already cheap (1–2 mm is already very coarse for NC), the fixed per-step costs dominate and raising <code>MachiningResolution_mm</code> further barely changes total time (this is why 1.0 mm and 2.0 mm can run at nearly the same speed). To speed up in that regime, reduce the step count via <a href="#33-machining-motion-resolution">Machining Motion Resolution</a>. See <a href="../manual/analysis/cpu-usage.html">CPU Usage During Simulation</a>.</p>
</div>
<h3 id="32-display-cache">3.2 Display Cache</h3>
<pre><code class="lang-csharp">DispCache_Mb = 260;
</code></pre>
@@ -180,25 +240,29 @@ var fixture = Fixture;
<tr>
<td>Feed Per Cycle</td>
<td><code>MachiningMotionResolution = FeedPerCycle;</code></td>
<td>One step per spindle revolution</td>
<td>One step per spindle revolution (<strong>default</strong>)</td>
</tr>
<tr>
<td>Scaled Feed Per Cycle</td>
<td><code>MachiningMotionResolution = ScaledFeedPerCycle(0.5);</code></td>
<td>One step per revolution × scale factor</td>
<td><code>MachiningMotionResolution = ScaledFeedPerCycle(2);</code></td>
<td>One step per (revolution × scale): scale &gt; 1 → fewer steps (faster); scale &lt; 1 → more steps (finer)</td>
</tr>
<tr>
<td>Feed Per Tooth</td>
<td><code>MachiningMotionResolution = FeedPerTooth;</code></td>
<td>One step per tooth revolution (default)</td>
<td>One step per tooth pass (revolution ÷ flute count)</td>
</tr>
<tr>
<td>Fixed Pace</td>
<td><code>MachiningMotionResolution = FixedPace(1, 15);</code></td>
<td>Fixed linear (mm) and rotary (deg) resolution</td>
<td>Fixed linear (mm) and rotary (deg) resolution; cuts by sweeping between steps</td>
</tr>
</tbody>
</table>
<div class="IMPORTANT">
<h5>Important</h5>
<p><strong>Total simulation time is governed by whichever is slower: geometry removal or the per-step fixed costs.</strong> Geometry-removal cost is set by <a href="#31-workpiece-entity-resolution">mesh resolution</a>; the per-step fixed costs (physics, thermal/wear, per-step bookkeeping) are set by the <strong>number of steps</strong> — the motion-resolution mode plus the spindle revolutions along the toolpath, independent of mesh resolution and of workpiece size. At the fine resolutions real NC machining needs, <strong>geometry removal is usually the bottleneck</strong> (finer = much slower). Only once the mesh is coarse enough that geometry removal is already cheap do the fixed per-step costs dominate — then raising <code>MachiningResolution_mm</code> further will <strong>not</strong> speed things up (this is why 1.0 mm and 2.0 mm can run at nearly the same speed); reduce the step count instead — e.g. <code>ScaledFeedPerCycle(2)</code> takes one step per 2 revolutions, halving the steps, at the cost of sparser force-curve sampling. See <a href="../manual/analysis/cpu-usage.html">CPU Usage During Simulation</a>.</p>
</div>
<div class="WARNING">
<h5>Warning</h5>
<p><strong>Do not use scaled model dimensions as a substitute for adjusting mesh width.</strong> Scaling model dimensions causes internal algorithm thresholds (minimum cuttable amount, floating-point-to-fraction range) to become invalid, producing irregular geometry artifacts. Adjust resolution settings instead.</p>
@@ -209,7 +273,7 @@ var fixture = Fixture;
</code></pre>
<hr>
<h2 id="4-run-simulation">4. Run Simulation</h2>
<p>There are three ways to drive the simulation.</p>
<p>There are four ways to drive the simulation, plus player controls.</p>
<h3 id="41-playncfile--execute-from-a-file">4.1 PlayNcFile — Execute from a File</h3>
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayNcFile_">PlayNcFile</a><small>(API)</small> reads and executes an NC file.</p>
<pre><code class="lang-csharp">PlayNcFile(&quot;NC/file1.nc&quot;);
@@ -234,7 +298,15 @@ PlayNc($&quot;G01 X{x} Y20 F100&quot;, &quot;Generated Command&quot;);
<h5>Tip</h5>
<p>CSV files exported by <a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_WriteStepFiles_">WriteStepFiles</a><small>(API)</small> can be directly read back with <a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayCsvFile_">PlayCsvFile</a><small>(API)</small>.</p>
</div>
<h3 id="44-player-control">4.4 Player Control</h3>
<h3 id="44-playclfile--drive-from-a-cutter-location-file">4.4 PlayClFile — Drive from a Cutter-Location File</h3>
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_PlayClFile_">PlayClFile</a><small>(API)</small> replays an NX cutter-location file (CLSF / APT-source, <code>.cls</code>) directly as tool motion — the machine-independent CAM toolpath, <strong>before</strong> it is post-processed for a specific machine.</p>
<pre><code class="lang-csharp">PlayClFile(&quot;CL/part-op10.cls&quot;);
</code></pre>
<div class="NOTE">
<h5>Note</h5>
<p>Unlike the file players above, CL playback drives a <a class="xref" href="../api/HiMachining.Milling.ClMillingDevice.html">ClMillingDevice</a> chain — the cutter location is applied straight to the tool — <strong>not</strong> the machine-tool chain from <a href="#1-set-machine-tool-and-controller">§1</a>. Use it to verify the programmed path itself, independent of machine and post-processor. See <a href="../manual/runtime/cutter-location-playback.html">Cutter-Location (CL) Playback</a> for the supported record set, tool creation from <code>TLDATA</code>, and the chain requirement.</p>
</div>
<h3 id="45-player-control">4.5 Player Control</h3>
<table>
<thead>
<tr>
@@ -263,13 +335,13 @@ if (someCondition)
</code></pre>
<hr>
<h2 id="5-view-results">5. View Results</h2>
<h3 id="51-runtime-geometry">5.1 Runtime Geometry</h3>
<p>After simulation the workpiece geometry is a <strong>Runtime Geometry</strong> (cubic mesh). You can save and reload it to avoid re-computing the initial shape:</p>
<pre><code class="lang-csharp">WriteRuntimeGeom(&quot;Cache/file1.wct&quot;);
WriteRuntimeGeomToStl(&quot;Output/file1.stl&quot;);
<h3 id="51-meshed-geometry">5.1 Meshed Geometry</h3>
<p>After simulation the workpiece geometry is a <strong>Meshed Geometry</strong> (cubic mesh). You can save and reload it to avoid re-computing the initial shape:</p>
<pre><code class="lang-csharp">WriteMeshedGeom(&quot;Cache/file1.wct&quot;);
ExportMeshedGeomToStl(&quot;Output/file1.stl&quot;);
</code></pre>
<p>To reload a saved geometry for a subsequent run:</p>
<pre><code class="lang-csharp">ReadRuntimeGeom(&quot;Cache/init.wct&quot;);
<pre><code class="lang-csharp">ReadMeshedGeom(&quot;Cache/init.wct&quot;);
PlayNcFile(&quot;NC/file1.nc&quot;);
</code></pre>
<h3 id="52-step-data-inspection">5.2 Step Data Inspection</h3>
@@ -305,9 +377,14 @@ AppendMessagesToFile(&quot;Output/messages.txt&quot;);
</thead>
<tbody>
<tr>
<td>Very slow simulation</td>
<td>Resolution too fine</td>
<td>Increase <code>MachiningResolution_mm</code></td>
<td>Very slow simulation, large pink trail behind the tool</td>
<td>Geometry removal is the bottleneck (mesh too fine)</td>
<td>Increase <code>MachiningResolution_mm</code> (coarser mesh)</td>
</tr>
<tr>
<td>Very slow simulation, but a coarser mesh doesn't help</td>
<td>Limited by step count (per-step physics)</td>
<td>Reduce steps via <code>MachiningMotionResolution</code> (e.g. <code>ScaledFeedPerCycle(2)</code>)</td>
</tr>
<tr>
<td>Irregular bumps on geometry</td>
@@ -330,6 +407,7 @@ AppendMessagesToFile(&quot;Output/messages.txt&quot;);
<ul>
<li><a href="../manual/setup/controller-heidenhain.html">Heidenhain Support</a> — controller configuration</li>
<li><a href="../manual/setup/controller-iso.html">General NC Code Support</a> — ISO NC support</li>
<li><a href="../manual/runtime/cutter-location-playback.html">Cutter-Location (CL) Playback</a> — replay a CAM cutter-location file with <code>PlayClFile</code></li>
<li><a href="../manual/runtime/step.html">Step</a> — what a step is, accessing and outputting step data</li>
<li><a href="../manual/runtime/step-fields.html">Step Field Reference</a> — step field reference</li>
<li><a class="xref" href="../manual/runtime/script-command.html">Glossary: Script Commands</a> — script command basics</li>
@@ -104,6 +104,10 @@
Simulate --&gt; Map --&gt; Train --&gt; Evaluate --&gt; 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 &ldquo;larger is always better&rdquo;.</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(&lt;seconds&gt;)</code>, <c
<p>When you have both controller data and sensor data:</p>
<pre><code class="lang-csharp">PlayNcFile(&quot;NC/machining.nc&quot;);
MapSingleByCsvFile(&quot;Data/controller.csv&quot;); // maps FileNo/LineNo → ActualTime
MapSeriesByCsvFile(&quot;Data/sensor.csv&quot;); // maps ActualTime → sensor series
MapSeriesByCsvFile(&quot;Data/sensor.csv&quot;); // 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(&quot;NC/file1.nc&quot;);
@@ -230,9 +360,46 @@ MapSeriesByCsvFile(&quot;Data/sensor.csv&quot;); // 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(&quot;Output/[NcName].step.csv&quot;);
WriteShotFiles(&quot;Output/[NcName].shot.csv&quot;, 1);
WriteShotFiles(&quot;Output/[NcName].shot.csv&quot;, 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(&quot;Output/[NcName].shot.csv&quot;, 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(&quot;lineA&quot;, &quot;Mapping/sensor1.csv&quot;, &quot;18:25:51.7100&quot;, &quot;18:26:12.9910&quot;);
@@ -347,7 +514,7 @@ TrainMillingPara(Fx|Fy|Fz, &quot;MillingPara/trained.mp&quot;);
LoadCuttingParaByFile(&quot;MillingPara/trained.mp&quot;);
WriteStepFiles(&quot;Output/[NcName].step.csv&quot;);
WriteShotFiles(&quot;Output/[NcName].shot.csv&quot;, 1);
WriteShotFiles(&quot;Output/[NcName].shot.csv&quot;, 0.1);
</code></pre>
<h2 id="see-also">See Also</h2>
<ul>
@@ -192,9 +192,9 @@ PlayNcFile(&quot;NC/file1.nc&quot;); // pauses if a collision occurs
<hr>
<h2 id="3-geometry-defect-scanning">3. Geometry Defect Scanning</h2>
<p>Geometry defect scanning helps debug abnormal workpiece or tool geometry. This is typically used only when geometry construction problems are suspected.</p>
<h3 id="scanruntimegeominfdefect">ScanRuntimeGeomInfDefect</h3>
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_ScanRuntimeGeomInfDefect_">ScanRuntimeGeomInfDefect</a> scans for infinite edge cut defects in the runtime geometry. After scanning, defect areas are rendered with colored markers.</p>
<pre><code class="lang-csharp">ScanRuntimeGeomInfDefect();
<h3 id="scanmeshedgeominfdefect">ScanMeshedGeomInfDefect</h3>
<p><a class="xref" href="../api/Hi.MachiningProcs.SessionShell.html#Hi_MachiningProcs_SessionShell_ScanMeshedGeomInfDefect_">ScanMeshedGeomInfDefect</a> scans for infinite edge cut defects in the meshed geometry. After scanning, defect areas are rendered with colored markers.</p>
<pre><code class="lang-csharp">ScanMeshedGeomInfDefect();
</code></pre>
<p>Return values:</p>
<ul>
@@ -203,7 +203,7 @@ PlayNcFile(&quot;NC/file1.nc&quot;); // pauses if a collision occurs
<li><code>null</code> — unable to execute (e.g., workpiece does not exist)</li>
</ul>
<h3 id="workflow-scan-before-simulation">Workflow: Scan Before Simulation</h3>
<pre><code class="lang-csharp">ScanRuntimeGeomInfDefect();
<pre><code class="lang-csharp">ScanMeshedGeomInfDefect();
Pause(); // visually inspect defects
ClearDefectDisplayee(); // clear markers
PlayNcFile(&quot;NC/file1.nc&quot;);
@@ -214,7 +214,7 @@ PlayNcFile(&quot;NC/file1.nc&quot;);
</code></pre>
<div class="NOTE">
<h5>Note</h5>
<p>Defect markers are automatically cleared when the workpiece is reloaded or the runtime geometry is reset. During workpiece initialization, if construction defects are detected, markers are automatically displayed.</p>
<p>Defect markers are automatically cleared when the workpiece is reloaded or the meshed geometry is reset. During workpiece initialization, if construction defects are detected, markers are automatically displayed.</p>
</div>
<hr>
<h2 id="4-flying-piece-removal">4. Flying Piece Removal</h2>
@@ -224,7 +224,7 @@ PlayNcFile(&quot;NC/file1.nc&quot;);
</code></pre>
<div class="TIP">
<h5>Tip</h5>
<p>Run <code>RemoveFlyPiece</code> after simulation and before geometry export (<code>WriteRuntimeGeomToStl</code>) to produce a clean output.</p>
<p>Run <code>RemoveFlyPiece</code> after simulation and before geometry export (<code>ExportMeshedGeomToStl</code>) to produce a clean output.</p>
</div>
<hr>
<h2 id="combined-validation-script-example">Combined Validation Script Example</h2>
@@ -243,14 +243,14 @@ RemoveFlyPiece();
Diff(1);
// Scan for geometry defects
var hasDefects = ScanRuntimeGeomInfDefect();
var hasDefects = ScanMeshedGeomInfDefect();
if (hasDefects == true)
{
WarningMessage(&quot;Geometry defects detected&quot;);
}
// Export final geometry
WriteRuntimeGeomToStl(&quot;Output/final.stl&quot;);
ExportMeshedGeomToStl(&quot;Output/final.stl&quot;);
WriteStepFiles(&quot;Output/[NcName].step.csv&quot;);
</code></pre>
<h2 id="see-also">See Also</h2>
@@ -0,0 +1,314 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Workflow: Constructing a Project through the Web API | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Workflow: Constructing a Project through the Web API | HiAPI-C# 2025 ">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../img/HiAPI.logo.png" alt="">
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="Workflow-ProjectConstruction">
<h1 id="workflow-constructing-a-project-through-the-web-api">Workflow: Constructing a Project through the Web API</h1>
<p><a href="basic-simulation.html">Basic Simulation</a> describes <em>what</em> a project contains. This page describes
<em>how to build one so that it is actually finished</em> — the ordering that avoids rework, how to shape
the mission, and the acceptance test that tells you the project is complete rather than merely
populated.</p>
<p>It is written for whoever assembles a <code>.hincproj</code> from a customer's deliverables — a person driving
the browser UI, or an agent driving the same operations over the HTTP API.</p>
<pre><code class="lang-mermaid">flowchart TD
New[&quot;1 · New project&lt;br&gt;(self-contained root)&quot;]
Assets[&quot;2 · Place assets&lt;br&gt;NC, STL, resource files&quot;]
Equip[&quot;3 · Equipment&lt;br&gt;chain, spindle&quot;]
Job[&quot;4 · Job&lt;br&gt;stock, ideal geom, material&quot;]
Ctrl[&quot;5 · Controller&lt;br&gt;brand + its own tables&quot;]
Tools[&quot;6 · Tool house&quot;]
Mission[&quot;7 · Mission&lt;br&gt;grouped, per-group resolution&quot;]
Replay[&quot;8 · Replay and read&lt;br&gt;every message&quot;]
Cross[&quot;9 · Numeric cross-checks&quot;]
Assume[&quot;10 · Record every assumption&quot;]
New --&gt; Assets --&gt; Equip --&gt; Job --&gt; Ctrl --&gt; Tools --&gt; Mission --&gt; Replay --&gt; Cross --&gt; Assume
Replay --&gt;|any warning| Ctrl
</code></pre>
<h2 id="build-through-the-api-not-by-editing-the-xml">Build through the API, not by editing the XML</h2>
<p>Create and modify projects through the service's HTTP API. It is the same code path the UI uses, so
a project built that way is on the supported create/load/save route. Hand-authoring the <code>.hincproj</code>
XML is a fallback for fields the API cannot yet reach — and when you hit one, the better fix is to
add the endpoint.</p>
<h2 id="1-one-self-contained-root">1. One self-contained root</h2>
<p>The <code>.hincproj</code> and <strong>every</strong> asset it references live under one folder — the project's own
directory — and every reference is relative to it with <strong>no <code>../</code></strong>.</p>
<pre><code>&lt;project&gt;/
├── &lt;name&gt;.hincproj
├── NC/ the programs, copied in
├── Geom/ workpiece / fixture STL
├── MachineTool/ the kinematic chain
├── SpindleCapability/
├── WorkpieceMaterial/
├── CuttingParameter/
├── CutterMaterial/
└── README.md what was assumed, and why
</code></pre>
<p>Two things do not move themselves, so bring them in by hand before you wire anything:</p>
<ul>
<li><strong>NC files.</strong> A program-file command stores a plain relative path; nothing copies the file.</li>
<li><strong>Machine-tool side files.</strong> A chain that externalises its mechanism references the side file and
its STL bodies by bare name, relative to the <code>.mt</code>'s own folder — keep the whole folder together.</li>
</ul>
<p>Resource files (chain, spindle, cutting parameters, workpiece material, cutter material) are
<em>pre-prepared data loaded by reference</em>. Stage a copy inside the project and load it from there, so
the saved reference points inside the project rather than at a shared library.</p>
<h2 id="2-order-the-build-to-avoid-rework">2. Order the build to avoid rework</h2>
<p>Later steps read earlier ones, so this order costs the least:</p>
<ol>
<li><strong>New project</strong> at its final path.</li>
<li><strong>Machine tool</strong>, then <strong>spindle capability</strong>.</li>
<li><strong>Workpiece</strong>: stock geometry, ideal (target) geometry, resolution, the geometry-to-program-zero
and geometry-to-fixture transforms, then material and cutting parameters.</li>
<li><strong>Controller</strong>: brand first — switching brand later resets brand-specific tables — then the
controller's own tables (§4).</li>
<li><strong>Tool house</strong>: per tool, shaper profile → fluting → exposed height → holder → upper beam →
cutter material. Then refresh the offset tables from the tool house.</li>
<li><strong>Program zero</strong>: with the workpiece placed and the chain loaded, derive the work offset from the
model rather than typing a number. See <a href="../manual/setup/program-zero-alignment.html">Program Zero Alignment</a>.</li>
<li><strong>Mission</strong> (§3).</li>
<li><strong>Save</strong>, then <strong>load the saved file back</strong> and re-check. A project that cannot be reloaded
cleanly is not built.</li>
</ol>
<div class="IMPORTANT">
<h5>Important</h5>
<p>Verify the axis set after loading a machine tool. A kinematic chain binds each axis transformer by
<strong>branch name</strong> (<code>X</code>/<code>Y</code>/<code>Z</code>/<code>A</code>/<code>B</code>/<code>C</code>); a branch left at its authoring default name yields no
transformer, and that axis silently does not exist. The trap is that the controller preset already
seeds the linear axes, so a chain missing its Z branch still <em>reports</em> a Z — only a missing rotary
gives it away. Compare the reported axes against the mechanism you expect.</p>
</div>
<h2 id="3-shape-the-mission-around-the-process-not-the-file-list">3. Shape the mission around the process, not the file list</h2>
<p>A flat list of program files runs correctly but reads badly and gives you one knob for the whole
job. Group the programs into one <strong>List command per operation family</strong>, in the order the process
actually runs:</p>
<pre><code>Machining Motion Resolution
Collision Detection [Off]
Pause on Failure [Off]
Physics [On]
▸ 1 · Drilling Machining Resolution 0.5 mm
centre drill, drill
▸ 2 · Outside roughing Machining Resolution 0.5 mm
roughing 1 … 5
▸ 3 · Outside finishing Machining Resolution 0.2 mm
finishing 1 … 7
▸ 4 · Pocket roughing Machining Resolution 0.5 mm
▸ 5 · Pocket finishing Machining Resolution 0.2 mm
▸ 6 · Rest milling Machining Resolution 0.2 mm
▸ 7 · Rib machining Machining Resolution 0.2 mm
▸ 8 · Deburring Machining Resolution 0.2 mm
Post-Execution geometry diff on
</code></pre>
<p>Why this shape:</p>
<ul>
<li><strong>Grouping must not reorder.</strong> The stock evolves from one operation to the next, so the sequence
is load-bearing. Group <em>adjacent</em> operations; never sort the list into tidy families if that moves
an operation past another one.</li>
<li><strong>Each group carries its own machining resolution.</strong> Roughing is about force, not surface, so a
coarse resolution is enough and runs quickly. Finishing, rib and deburring passes leave the final
surface with small and ball cutters and deserve a finer one. Setting the resolution mid-mission
only changes the value the act runner cuts with — the workpiece is not rebuilt, and the geometry
container is adaptive — so alternating coarse and fine between groups is safe.</li>
<li><strong>A group is a switch.</strong> Disabling one List skips a whole phase, which is how you re-run
just the finishing passes without deleting anything.</li>
<li><strong>Budget the fine groups.</strong> Machining resolution drives the cost of subtracting material, not the
number of simulation steps — the step count follows the <em>motion</em> resolution and does not change.
On one 33-operation job, refining the finishing groups from 0.5 mm to 0.2 mm left the step count
identical and multiplied wall-clock time by about 2.8. Decide the finish resolution with that
trade-off in view, and say what it costs in the project's README so nobody is surprised.</li>
<li><strong>Setup commands are granular.</strong> Machining resolution, motion resolution, collision detection,
pause-on-failure and physics are separate commands, so each can sit exactly where it should take
effect — global ones at the top, per-phase ones inside a group.</li>
</ul>
<div class="TIP">
<h5>Tip</h5>
<p>A project that loads an ideal (target) geometry and never compares against it is unfinished. Turn
on the geometry diff in the Post-Execution command so a full replay ends by measuring the machined
stock against the finished part.</p>
</div>
<h2 id="4-fill-the-controllers-own-tables">4. Fill the controller's own tables</h2>
<p>The tool house describes the <em>physical</em> tool. The controller has its own record of the same tool,
and the NC program reads the controller's copy. Both must exist.</p>
<p>For a Siemens-style controller that is two tables:</p>
<table>
<thead>
<tr>
<th>Table</th>
<th>Holds</th>
<th>If empty</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tool name → tool number</td>
<td>the names a <code>T=&quot;…&quot;</code> call uses</td>
<td>the tool never mounts, and the program produces <strong>no machining steps at all</strong></td>
</tr>
<tr>
<td>Tool edge offsets</td>
<td>per <code>(tool, edge)</code>: length along the tool axis, radius</td>
<td>every edge call falls back to the generic offset table and logs a warning</td>
</tr>
</tbody>
</table>
<p>Take the values from the tool house and <strong>assert they match before writing</strong>. When the warning
disappears and the cut does not move at all, that is the proof the rows carry the right numbers —
if the geometry shifts, one of the two tables was wrong.</p>
<div class="NOTE">
<h5>Note</h5>
<p>Not every controller parameter has a consumer. Some, such as the maximum spindle speed, are
recorded machine data that nothing in the pipeline reads today. Filling them is good hygiene, but
do not report it as fixing a defect, and remember that copying a <em>guessed</em> value (an assumed
spindle, say) into a second place means both must move when the real datum arrives.</p>
</div>
<h2 id="5-the-finish-line-is-a-clean-replay-not-a-filled-form">5. The finish line is a clean replay, not a filled form</h2>
<p><strong>Replay the whole mission and inventory the messages by id.</strong> Every warning is an item on the
to-do list. Resist writing one up as an acceptable fallback: a fallback firing means the project
never supplied the data the fallback exists to cover.</p>
<p>Read messages at a low severity so nothing hides. The severities are
<code>Message</code>, <code>Success</code>, <code>Progress</code>, <code>Warning</code>, <code>Error</code> — note there is no <code>Info</code>, and an unrecognised
name is rejected in the response body rather than by an HTTP error, which reads exactly like
&ldquo;no messages&rdquo;.</p>
<p>Stop when only <em>declared informational</em> messages remain — the ones that state a known, deliberate
limitation. Typical survivors:</p>
<ul>
<li>one per NC file, reporting the line count;</li>
<li>machine M-codes that the runner recognises and consumes but does not model (OEM auxiliary
functions such as coolant valves), which are announced rather than silently ignored.</li>
</ul>
<p>Anything else is work.</p>
<h2 id="6-two-numeric-cross-checks--and-what-they-do-not-prove">6. Two numeric cross-checks — and what they do not prove</h2>
<p>Messages catch what the runner noticed. These two catch datum errors that produce no message at all.</p>
<p><strong>Depth of cut against the programmed layer depth.</strong> On a roughing pass whose step-down you can read
from the NC, the peak cutting depth must equal it. This pins the Z datum: if program zero is wrong,
the tool cuts a different amount and the peak does not land on the programmed number.</p>
<p><strong>Cycle time against the post-processor's own estimate.</strong> Many post-processors write a per-operation
machining time into the program as a comment. Sum them and compare with the simulated time.</p>
<div class="WARNING">
<h5>Warning</h5>
<p>Scope the cycle-time check honestly. It confirms that <strong>feed rates and path length</strong> are consumed
correctly. It is <strong>not</strong> a comparison against the real machine, because both sides ignore the same
things: there is no acceleration model (time is path length over feed rate, with no ramps — which
costs the most on finishing passes made of thousands of short segments), tool-change time defaults
to zero, and the tool-change and home positions come from the chain rather than from machine data.</p>
<p>For the same reason, a customer's &ldquo;total machining time&rdquo; running well above the sum of the
per-operation comments is usually <strong>not</strong> a contradiction — the comments are cutting time, the
total is wall clock including tool changes and inter-operation moves. Two different quantities.</p>
</div>
<h2 id="7-record-every-assumption">7. Record every assumption</h2>
<p>Real deliverables are incomplete. Build with sensible values, and write each one down in a
<code>README.md</code> beside the <code>.hincproj</code> — what was assumed, what it was inferred from, and what changes
when the real value arrives. Recurring items: work offsets, blank size and material, tool helix
angle, stick-out, holder dimensions, the spindle's power–torque curve, fixture geometry, and the
cycle-time inputs above.</p>
<p>Cross-reference: <a href="../manual/setup/project-data-checklist.html">Project Data Checklist</a> is the list to
hand the customer <em>before</em> building; this section is what you hand back <em>after</em>.</p>
</article>
<div class="contribution d-print-none">
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
</div>
</div>
</footer>
</body>
</html>
@@ -0,0 +1,189 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Workflow: Building a Simulation Report | HiAPI-C# 2025 </title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="title" content="Workflow: Building a Simulation Report | HiAPI-C# 2025 ">
<link rel="icon" href="../img/HiAPI.favicon.ico">
<link rel="stylesheet" href="../public/docfx.min.css">
<link rel="stylesheet" href="../public/main.css">
<meta name="docfx:navrel" content="../toc.html">
<meta name="docfx:tocrel" content="toc.html">
<meta name="docfx:rel" content="../">
<meta name="loc:inThisArticle" content="In this article">
<meta name="loc:searchResultsCount" content="{count} results for &quot;{query}&quot;">
<meta name="loc:searchNoResults" content="No results for &quot;{query}&quot;">
<meta name="loc:tocFilter" content="Filter by title">
<meta name="loc:nextArticle" content="Next">
<meta name="loc:prevArticle" content="Previous">
<meta name="loc:themeLight" content="Light">
<meta name="loc:themeDark" content="Dark">
<meta name="loc:themeAuto" content="Auto">
<meta name="loc:changeTheme" content="Change theme">
<meta name="loc:copy" content="Copy">
<meta name="loc:downloadPdf" content="Download PDF">
<script type="module" src="./../public/docfx.min.js"></script>
<script>
const theme = localStorage.getItem('theme') || 'auto'
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
</script>
</head>
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
<header class="bg-body border-bottom">
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
<div class="container-xxl flex-nowrap">
<a class="navbar-brand" href="../index.html">
<img id="logo" class="svg" src="../img/HiAPI.logo.png" alt="">
</a>
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
<i class="bi bi-three-dots"></i>
</button>
<div class="collapse navbar-collapse" id="navpanel">
<div id="navbar">
<form class="search" role="search" id="search">
<i class="bi bi-search"></i>
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
</form>
</div>
</div>
</div>
</nav>
</header>
<main class="container-xxl">
<div class="toc-offcanvas">
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
<div class="offcanvas-header">
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body">
<nav class="toc" id="toc"></nav>
</div>
</div>
</div>
<div class="content">
<div class="actionbar">
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
<i class="bi bi-list"></i>
</button>
<nav id="breadcrumb"></nav>
</div>
<article data-uid="Workflow-SimulationReport">
<h1 id="workflow-building-a-simulation-report">Workflow: Building a Simulation Report</h1>
<p>After a simulation has run, a report communicates the result: what the finished part looks like, how the machining loads evolved over the program, and whether the run was clean. This workflow covers how to turn a completed player session into a focused set of report captures — keeping the panels that carry result information and leaving out the navigation chrome.</p>
<pre><code class="lang-mermaid">flowchart TD
Build[&quot;Build project&lt;br&gt;(equipment, job, options)&quot;]
Run[&quot;Run simulation&quot;]
Capture[&quot;Capture focused views&lt;br&gt;(canvas · strip charts · messages)&quot;]
Assemble[&quot;Assemble report&quot;]
Build --&gt; Run --&gt; Capture --&gt; Assemble
</code></pre>
<h2 id="1-build-and-run">1. Build and Run</h2>
<p>Stand up and run the project first — see <a href="basic-simulation.html">Basic Machining Simulation</a> for equipment, job, options, and the <code>Play*</code> run commands. A report is built from a <strong>completed</strong> run: the workpiece geometry is final and the strip charts span the whole program.</p>
<h2 id="2-what-to-capture--and-what-to-leave-out">2. What to Capture — and What to Leave Out</h2>
<p>The player screen carries more panels than a report needs. A good report keeps the panels that hold result information and drops the navigation chrome:</p>
<table>
<thead>
<tr>
<th>Panel</th>
<th>In a report?</th>
<th>Why</th>
</tr>
</thead>
<tbody>
<tr>
<td>Main 3D canvas</td>
<td><strong>Keep</strong></td>
<td>The finished part — the headline image</td>
</tr>
<tr>
<td><a href="../app-anatomy/player/strip-charts.html">Strip Charts</a></td>
<td><strong>Keep</strong></td>
<td>Machining loads / availability over the whole program</td>
</tr>
<tr>
<td><a href="../app-anatomy/session-message-panel/index.html">Session Messages</a></td>
<td><strong>Keep (optional)</strong></td>
<td>The run log — proof the run was clean</td>
</tr>
<tr>
<td>Control Tree column</td>
<td>Drop</td>
<td>Navigation only; no result content</td>
</tr>
<tr>
<td><a href="../app-anatomy/player/selected-step-info-panel.html">Selected-Step Info column</a></td>
<td>Drop</td>
<td>Single-step detail; not a whole-run summary</td>
</tr>
</tbody>
</table>
<p>Use the three region quick-toggles in the top toolbar to collapse the columns you are not capturing, so each kept panel gets the full width/height.</p>
<h2 id="3-main-3d-canvas--several-views">3. Main 3D Canvas — Several Views</h2>
<p>Capture the finished part from several angles. Use the <strong>View</strong> menu on the <a href="../app-anatomy/renderingcanvas-tool-bar.html">Rendering Canvas Tool Bar</a> to switch between the orthographic and isometric presets (Isometric, Front, Back, Left, Right, Top, Bottom).</p>
<ul>
<li><strong>Isometric + Top</strong> are the most informative for most parts.</li>
<li>Add <strong>Front / Right</strong> for thin or shallow parts, where the side profile carries the wall thickness.</li>
</ul>
<div class="TIP">
<h5>Tip</h5>
<p><strong>The tool-path overlay carries information too — capture both.</strong> The machined tool-path overlay (the CL strip) shows the machining coverage and the retract/plunge motion, but it can be dense enough to obscure the part shape underneath. It is worth capturing each view <strong>both ways</strong>: with the tool path on (machining coverage) and off (clean part). Toggle it with the <strong>Tool Path</strong> button on the <a href="../app-anatomy/player/player-extended-renderingcanvas-tool-bar.html">Player Extended Rendering-Canvas Tool Bar</a> (and <strong>Path Points</strong> off with it). The workpiece geometry is a separate display flag, so it stays visible when the tool path is off.</p>
</div>
<h2 id="4-strip-charts--capture-wide">4. Strip Charts — Capture Wide</h2>
<p>The strip charts read best <strong>wide</strong>: at full width the whole-program time axis is legible and the per-series peaks are distinct. Before capturing, widen the right dock (drag its divider, or collapse the Selected-Step Info column so the charts fill the dock). See <a href="../app-anatomy/player/strip-charts.html">Strip Charts</a> for the chart types (Availability, Roughness, Color-Index) and their legends.</p>
<h2 id="5-session-messages--the-run-log">5. Session Messages — the Run Log</h2>
<p>The <a href="../app-anatomy/session-message-panel/index.html">Session Messages</a> panel's <strong>Shell / NC / Step</strong> tabs are the run log. <strong>Zero errors across all three tabs</strong> is the single strongest piece of report evidence that the run was clean. Use the panel's <strong>Export</strong> action to save the full log alongside the report.</p>
<h2 id="6-assemble">6. Assemble</h2>
<p>Combine the captures into the report: a multi-view montage of the finished part, the wide strip charts, and (optionally) the session log. Pair each with a one-line caption stating what it shows (part geometry, load history, clean run).</p>
<h2 id="see-also">See Also</h2>
<ul>
<li><a href="basic-simulation.html">Basic Machining Simulation</a> — build and run the project first</li>
<li><a href="../app-anatomy/player/strip-charts.html">Strip Charts</a> — chart types and legends</li>
<li><a href="../app-anatomy/player/player-extended-renderingcanvas-tool-bar.html">Player Extended Rendering-Canvas Tool Bar</a> — the Tool Path / Path Points toggles</li>
<li><a href="../app-anatomy/session-message-panel/index.html">Session Message Panel</a> — Shell / NC / Step tabs and Export</li>
<li><a class="xref" href="../manual/runtime/session-shell.html">Glossary: SessionShell Quick-Reference</a> — SessionShell quick-reference</li>
</ul>
</article>
<div class="contribution d-print-none">
</div>
<div class="next-article d-print-none border-top" id="nextArticle"></div>
</div>
<div class="affix">
<nav id="affix"></nav>
</div>
</main>
<div class="container-xxl search-results" id="search-results"></div>
<footer class="border-top text-secondary">
<div class="container-xxl">
<div class="flex-fill">
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
</div>
</div>
</footer>
</body>
</html>
@@ -15,6 +15,9 @@
<li>
<a href="basic-simulation.html" name="" title="Basic Simulation">Basic Simulation</a>
</li>
<li>
<a href="project-construction.html" name="" title="Project Construction">Project Construction</a>
</li>
<li>
<a href="force-training.html" name="" title="Milling Force Parameter Training">Milling Force Parameter Training</a>
</li>
@@ -27,6 +30,9 @@
<li>
<a href="geometry-validation.html" name="" title="Geometry Validation">Geometry Validation</a>
</li>
<li>
<a href="simulation-report.html" name="" title="Simulation Report">Simulation Report</a>
</li>
<li>
<a href="dynamometer-experiment-sop.html" name="" title="Dynamometer Experiment SOP">Dynamometer Experiment SOP</a>
</li>
+1 -1
View File
@@ -1,2 +1,2 @@
{"items":[{"name":"Basic Simulation","href":"basic-simulation.html","topicHref":"basic-simulation.html"},{"name":"Milling Force Parameter Training","href":"force-training.html","topicHref":"force-training.html"},{"name":"NC Optimization","href":"nc-optimization.html","topicHref":"nc-optimization.html"},{"name":"Sensor Data Mapping","href":"sensor-mapping.html","topicHref":"sensor-mapping.html"},{"name":"Geometry Validation","href":"geometry-validation.html","topicHref":"geometry-validation.html"},{"name":"Dynamometer Experiment SOP","href":"dynamometer-experiment-sop.html","topicHref":"dynamometer-experiment-sop.html"},{"name":"Examples","href":"examples/index.html","tocHref":"examples/toc.html","topicHref":"examples/index.html","homepage":"examples/index.html"}]}
{"items":[{"name":"Basic Simulation","href":"basic-simulation.html","topicHref":"basic-simulation.html"},{"name":"Project Construction","href":"project-construction.html","topicHref":"project-construction.html"},{"name":"Milling Force Parameter Training","href":"force-training.html","topicHref":"force-training.html"},{"name":"NC Optimization","href":"nc-optimization.html","topicHref":"nc-optimization.html"},{"name":"Sensor Data Mapping","href":"sensor-mapping.html","topicHref":"sensor-mapping.html"},{"name":"Geometry Validation","href":"geometry-validation.html","topicHref":"geometry-validation.html"},{"name":"Simulation Report","href":"simulation-report.html","topicHref":"simulation-report.html"},{"name":"Dynamometer Experiment SOP","href":"dynamometer-experiment-sop.html","topicHref":"dynamometer-experiment-sop.html"},{"name":"Examples","href":"examples/index.html","tocHref":"examples/toc.html","topicHref":"examples/index.html","homepage":"examples/index.html"}]}