CURA-12352 different minimum layer time for layers that contain overhangs #1020
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: GcodeAnalyzer | |
on: | |
push: | |
paths: | |
- 'include/**' | |
- 'src/**' | |
- '.github/workflows/gcodeanalyzer.yml' | |
branches: | |
- main | |
pull_request: | |
types: [ opened, reopened, synchronize ] | |
paths: | |
- 'include/**' | |
- 'src/**' | |
- '.github/workflows/gcodeanalyzer.yml' | |
branches: | |
- main | |
- 'CURA-*' | |
- 'PP-*' | |
- 'NP-*' | |
- '[0-9]+.[0-9]+' | |
permissions: | |
contents: write | |
deployments: write | |
# TODO: Make cura-workflows/benchmark.yml generic enough to fit the gcodeanalyzer benchmark | |
jobs: | |
check_actor: | |
uses: ultimaker/cura-workflows/.github/workflows/check-actor.yml@main | |
secrets: inherit | |
conan-recipe-version: | |
needs: [ check_actor ] | |
if: ${{ needs.check_actor.outputs.proceed == 'true' }} | |
uses: ultimaker/cura-workflows/.github/workflows/conan-recipe-version.yml@main | |
gcodeanalyzer: | |
needs: [ conan-recipe-version ] | |
name: Run GCodeAnalyzer on the engine | |
runs-on: ubuntu-latest | |
steps: | |
- name: Setup the build environment | |
uses: ultimaker/cura-workflows/.github/actions/setup-build-environment@main | |
with: | |
install_system_dependencies: true | |
- name: Checkout GCodeAnalyzer | |
uses: actions/checkout@v4 | |
with: | |
repository: 'Ultimaker/GCodeAnalyzer' | |
ref: 'main' | |
path: 'GCodeAnalyzer' | |
fetch-depth: 1 | |
token: ${{ secrets.CURA_BENCHMARK_PAT }} | |
- name: Checkout Test Models | |
uses: actions/checkout@v4 | |
with: | |
repository: 'Ultimaker/NightlyTestModels' | |
ref: 'main' | |
path: 'NightlyTestModels' | |
fetch-depth: 1 | |
token: ${{ secrets.GITHUB_TOKEN }} | |
- name: Install dependencies | |
run: conan install . ${{ needs.conan-recipe-version.outputs.version_full }} -s "*:build_type=Release" --build=missing --update -g VirtualRunEnv -c tools.build:skip_test=True -o with_cura_resources=True | |
- name: Build CuraEngine and tests | |
run: | | |
source build/Release/generators/conanbuild.sh | |
cmake --preset release | |
cmake --build --preset release | |
- name: Collect STL-files, run CuraEngine, output GCode-files | |
run: | | |
for file in `ls NightlyTestModels/*.stl`; | |
do | |
( time ./build/Release/CuraEngine slice --force-read-parent --force-read-nondefault -v -p -j $CURA_RESOURCES/definitions/ultimaker_s3.def.json -l $file -o `basename $file .stl`.gcode ) 2> `basename $file .stl`.time | |
done | |
# TODO: Move this to GCodeAnalyzer | |
- name: Run GCodeAnalyzer on generated GCode files | |
id: gcode_out | |
run: | | |
import sys | |
import os | |
import json | |
import re | |
from Charon.filetypes.GCodeFile import GCodeFile | |
sys.path.append(".") | |
import GCodeAnalyzer | |
GCodeFile.SkipHeaderValidation = True | |
folder_path = ".." | |
jzon = [] | |
for filename in os.listdir(folder_path): | |
basename = os.path.basename(filename) | |
_base, ext = os.path.splitext(basename) | |
if ext.lower() != ".gcode": | |
continue | |
infilename = os.path.join(folder_path, filename) | |
with open(infilename.rsplit(".", 1)[0] + ".time", "r") as f: | |
content = f.read() | |
match = re.search(r"^real\s+(\d+)m(\d+\.\d+)s", content, re.MULTILINE) | |
if match: | |
timer = float(match.group(1)) * 60 + float(match.group(2)) | |
else: | |
timer = 0 | |
frame = GCodeAnalyzer.DataFrame(infilename) | |
line_lengths = frame.gc.extrusions['length'].describe() | |
all_lengths = frame.gc.travels['length'].describe() | |
extrusion_values = frame.gc.extrusions['E'].describe() | |
temperatures = frame['T_0_nozzle'].describe() | |
print_time = frame.time.max() | |
no_retractions = len(frame.gc.retractions) | |
total_travel_length = frame.gc.travels.length.sum() | |
# microsegments violations | |
queue = 16 | |
seg_sec = 80 | |
violation_threshold = queue / seg_sec | |
microsegments_wall_skin = frame.gc.extrusions.duration[(frame.type == 'WALL-OUTER') | (frame.type == 'WALL-INNER') | (frame.type == 'SKIN')].rolling(queue).sum() | |
no_violations_wall_skin = microsegments_wall_skin[microsegments_wall_skin < violation_threshold].count() | |
microsegments_infill = frame.gc.extrusions.duration[frame.type == 'FILL'].rolling(queue).sum() | |
no_violations_infill = microsegments_infill[microsegments_infill < violation_threshold].count() | |
jzon += [ | |
{ | |
"name": f"Print time {basename}", | |
"unit": "s", | |
"value": print_time, | |
}, | |
{ | |
"name": f"Microsegment violations in wall-skin {basename}", | |
"unit": "-", | |
"value": int(no_violations_wall_skin), | |
}, | |
{ | |
"name": f"Microsegment violations in infill {basename}", | |
"unit": "-", | |
"value": int(no_violations_infill), | |
}, | |
{ | |
"name": f"Number of retractions {basename}", | |
"unit": "-", | |
"value": no_retractions, | |
}, | |
{ | |
"name": f"Total travel length {basename}", | |
"unit": "mm", | |
"value": total_travel_length, | |
}, | |
{ | |
"name": f"Minimum Line Length {basename}", | |
"unit": "mm", | |
"value": line_lengths["min"], | |
}, | |
{ | |
"name": f"Line Lengths 25 Percentile {basename}", | |
"unit": "mm", | |
"value": line_lengths["25%"], | |
}, | |
{ | |
"name": f"Minimum All Distances {basename}", | |
"unit": "mm", | |
"value": all_lengths["min"], | |
}, | |
{ | |
"name": f"All Distances 25 Percentile {basename}", | |
"unit": "mm", | |
"value": all_lengths["25%"], | |
}, | |
{ | |
"name": f"Extrusion-Axis {basename}", | |
"unit": "mm", | |
"value": extrusion_values["min"], | |
}, | |
{ | |
"name": f"Extrusion Lengths 25 Percentile {basename}", | |
"unit": "mm", | |
"value": extrusion_values["25%"], | |
}, | |
{ | |
"name": f"Number Of Temperature Commands {basename}", | |
"unit": "#", | |
"value": temperatures["count"], | |
}, | |
{ | |
"name": f"Mean Temperature {basename}", | |
"unit": "Celcius", | |
"value": temperatures["50%"], | |
}, | |
{ | |
"name": f"Slicing time {basename}", | |
"unit": "s", | |
"value": timer, | |
}, | |
] | |
with open("../output.json", "w") as outfile: | |
outfile.write(json.dumps(jzon)) | |
shell: python | |
working-directory: GCodeAnalyzer | |
- name: Store benchmark result | |
uses: benchmark-action/github-action-benchmark@v1 | |
with: | |
name: CGcodeAnalyzer | |
output-file-path: output.json | |
gh-repository: github.com/Ultimaker/CuraEngineBenchmarks | |
gh-pages-branch: main | |
benchmark-data-dir-path: dev/gcodeanalyzer | |
tool: customBiggerIsBetter | |
github-token: ${{ secrets.CURA_BENCHMARK_PAT }} | |
auto-push: true | |
max-items-in-chart: 250 |