From 35e8ef2482bf71450f970fee4239b853a00d63bb Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Wed, 9 Oct 2024 13:16:11 +0200 Subject: [PATCH] - ProcessFeature divisa in GetProcessings(collect e raccolta strategie) e ProcessMachinings (scelta strategia migliore e applicazione lavorazioni) - in ProcessMachinings predisposto ciclo per ricalcolare in caso di errore su Apply - Nuova lista globale PROCESSINGS - Calcolo tempi commentato, da riposizionare in base alle misure che si vogliono effettuare - Predisposizione funzione per calcolo della matrice delle combinazioni (completamente da fare) --- LuaLibs/BeamExec.lua | 316 +++++++++++++++++++++++-------------------- Process.lua | 6 +- 2 files changed, 175 insertions(+), 147 deletions(-) diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 7c1e95d..15d3b86 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -27,9 +27,9 @@ EgtMdbSave() ------------------------------------------------------------------------------------------------------------- -- *** variabili globali *** ------------------------------------------------------------------------------------------------------------- -TOOLS = nil -STRATEGIES = nil -MACHININGS = nil +TOOLS = {} -- tabella contenente tutti gli utensili +STRATEGIES = nil -- tabella contenente le strategie disponibili per ogni feature +MACHININGS = {} -- tabella contenente le lavorazioni da applicare ------------------------------------------------------------------------------------------------------------- -- *** COSTANTI *** TODO -> DA SPOSTARE IN BEAMDATA??? @@ -85,8 +85,6 @@ end ------------------------------------------------------------------------------------------------------------- function BeamExec.GetToolsFromDB() - -- creo lista globale utensili disponibili - TOOLS = {} -- lista appoggio utensile local Tool = {} @@ -714,8 +712,33 @@ local function GetIndexBestStrategyFromComparison( AvailableStrategies, nIndex1, end ------------------------------------------------------------------------------------------------------------- --- funzione che processa tutte le feature sul pezzo e trova la miglior strategia di lavorazione tra quelle disponibili -local function GetBestStrategy( vProcSingleRot, Part) +-- funzione che trova la strategia migliore tra quelle disponibili +local function GetBestStrategy( vProcSingleRot) + for i = 1, #vProcSingleRot do + -- processo tutte le feature attive + local Proc = vProcSingleRot[i] + if Proc.nFlg ~= 0 then + local nIndexBestStrategy = 0 + -- controllo se ci sono strategie disponibili + if Proc.AvailableStrategies and #Proc.AvailableStrategies > 0 then + -- ciclo tutte le strategie della feature + for nIndexCurrentStrategy = 1, #Proc.AvailableStrategies do + -- scelgo la migliore strategia tra le due + nIndexBestStrategy = GetIndexBestStrategyFromComparison( Proc.AvailableStrategies, nIndexCurrentStrategy, nIndexBestStrategy) + -- salvo sulla proc la migliore strategia + end + if nIndexBestStrategy ~= 0 then + Proc.ChosenStrategy = Proc.AvailableStrategies[nIndexBestStrategy] + end + end + end + end + return vProcSingleRot +end + +------------------------------------------------------------------------------------------------------------- +-- funzione che processa tutte le feature del pezzo +local function CalculateStrategies( vProcSingleRot, Part) -- per ogni feature for i = 1, #vProcSingleRot do -- processo tutte le feature attive @@ -723,7 +746,6 @@ local function GetBestStrategy( vProcSingleRot, Part) if Proc.nFlg ~= 0 then -- controllo se ci sono strategie disponibili if Proc.AvailableStrategies and #Proc.AvailableStrategies > 0 then - local nIndexBestStrategy = 0 -- ciclo tutte le strategie della feature for nIndexCurrentStrategy = 1, #Proc.AvailableStrategies do -- eseguo file config con i parametri di default @@ -731,30 +753,22 @@ local function GetBestStrategy( vProcSingleRot, Part) CurrentStrategy = RunStrategyLibraries( Proc.AvailableStrategies[nIndexCurrentStrategy].sStrategyId) -- controllo che le librerie siano state effettivamente caricate if CurrentStrategy.Config and CurrentStrategy.Script then - local bStrategyOk -- eseguo la strategia solo come calcolo fattibilità e voto. Non si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati _, Proc.AvailableStrategies[nIndexCurrentStrategy].Result = CurrentStrategy.Script.Make( false, Proc, Part, Proc.AvailableStrategies[nIndexCurrentStrategy].Parameters) - -- scelgo la migliore strategia tra le due - nIndexBestStrategy = GetIndexBestStrategyFromComparison( Proc.AvailableStrategies, nIndexCurrentStrategy, nIndexBestStrategy) - -- se scelta strategia standard, esco subito alla prima che trovo completa + -- se scelta strategia in modalità base o standard, esco subito alla prima che trovo completa -- TODO serve paraemtro da Beam&Wall ( oppure da confirgurazione) !!!!!!!! - if BEAM.GetFirstCompletedStrategy and nIndexBestStrategy > 0 then - if Proc.AvailableStrategies[nIndexBestStrategy].Result.sStatus == 'Complete' then - break - end + if BEAM.GetFirstCompletedStrategy and Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sStatus == 'Complete' then + break end -- se non trovo i file della strategia, scrivo che non è più disponibile else Proc.AvailableStrategies[nIndexCurrentStrategy].Result = {} Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sInfo = 'Strategy not found' + Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sStatus = 'Not-Applicable' end end - -- salvo sulla proc la migliore strategia - if nIndexBestStrategy ~= 0 then - Proc.ChosenStrategy = Proc.AvailableStrategies[nIndexBestStrategy] - end end end end @@ -838,7 +852,6 @@ end -- esegue le strategie migliori che ha precedentemente scelto local function CalculateMachinings( vProc, Part) local bAreAllApplyOk = true - MACHININGS = {} -- applico le strategie scelte for i = 1, #vProc do -- processo tutte le feature attive applicando le lavorazioni @@ -856,48 +869,25 @@ end ------------------------------------------------------------------------------------------------------------- local function PrintFeatures( vProc, Part) - EgtOutLog( ' RawBox=' .. tostring( Part.RawBox)) - for i = 1, #vProc do - local Proc = vProc[i] - local sOut = string.format( ' Id=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Down=%s Side=%s Head=%s Tail=%s Fcse=%1d,%1d Diam=%.2f Fct=%2d Box=%s TopoName=%s', - Proc.id, Proc.nGrp, Proc.nPrc, Proc.idTask, Proc.idCut, - Proc.nFlg, EgtIf( Proc.bDown, 'T', 'F'), EgtIf( Proc.bSide, 'T', 'F'), - EgtIf( Proc.bHead, 'T', 'F'), EgtIf( Proc.bTail, 'T', EgtIf( Proc.bAdvTail, 'A', 'F')), - Proc.nFcs, Proc.nFce, Proc.dDiam, Proc.nFct, tostring( Proc.b3Box), Proc.Topology.sName or '') - -- info speciali per Block Haus Half Lap - if Proc.nPrc == 37 then - local sSpec = string.format( ' N=%s Hd=%s', tostring( Proc.vtN or V_NULL()), EgtIf( Proc.bHeadDir, 'T', 'F')) - sOut = sOut .. sSpec + if vProc then + EgtOutLog( ' RawBox=' .. tostring( Part.b3Box)) + for i = 1, #vProc do + local Proc = vProc[i] + local sOut = string.format( ' Id=%3d Grp=%1d Prc=%3d Flg=%2d Fct=%2d TopoName=%s', + Proc.id, Proc.nGrp, Proc.nPrc, Proc.nFlg, Proc.nFct, Proc.Topology.sName or '') + EgtOutLog( sOut) end - EgtOutLog( sOut) end end ------------------------------------------------------------------------------------------------------------- -function BeamExec.ProcessFeatures( PARTS) - -- ciclo sui pezzi - local nTotErr = 0 - local Stats = {} - local nOrd = 1 - local Part = {} - +function BeamExec.GetProcessings( PROCESSINGS, PARTS) + -- recupero tutti i processing di tutti i pezzi in tutte le rotazioni for nPart = 1, #PARTS do if not PARTS[nPart].id and PARTS[nPart].b3Raw:getDimX() < BeamData.dMinRaw then break end - - -- per ogni rotazione, calcolo come lavorare le feature per decidere posizionamento iniziale e in che rotazione verranno lavorate le singole feature local vProcRot = {} - -- lista contenente le feature da eseguire - local vProc = {} - --- TODO da rimuovere o lasciare solo per debug -if EgtGetDebugLevel() >= 3 then - EgtStartCounter() -end - - -- TODO Il numero di rotazioni da calcolare deve dipendere dalle impostazionei del cliente. Per adesso si calcolano tutte e 4, ma può essere ottimizzato for dRotIndex = 1, 4 do - -- recupero le feature di lavorazione della trave table.insert( vProcRot, CollectFeatures( PARTS[nPart])) @@ -905,8 +895,8 @@ end -- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no vProcRot[dRotIndex] = GetFeatureInfoAndDependency( vProcRot[dRotIndex], PARTS[nPart]) - -- sceglie la strategia migliore tra quelle disponibili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies) - vProcRot[dRotIndex] = GetBestStrategy( vProcRot[dRotIndex], PARTS[nPart]) + -- calcola le strategie applicabili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies) + vProcRot[dRotIndex] = CalculateStrategies( vProcRot[dRotIndex], PARTS[nPart]) -- ruoto il grezzo per calcolare la fattibilità delle lavorazioni nella prossima rotazione -- vettore movimento grezzi per rotazione di 90deg ogni step @@ -925,107 +915,143 @@ end PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw) PARTS[nPart].b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[nPart].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) end - - --- TODO da rimuovere o lasciare solo per debug -if EgtGetDebugLevel() >= 3 then - local timeCollect = EgtStopCounter() - timeCollect = timeCollect + 0 - EgtOutBox( timeCollect, 'Collect calculation time') - EgtStartCounter() + local Part = {} + Part.Rotation = vProcRot + -- recupero le feature di lavorazione della trave + table.insert( PROCESSINGS, Part) + end + return PROCESSINGS end - - -- TODO decidere come lavorare ogni feature in base alla matrice delle rotazioni - -- la matrice delle rotazioni deve già salvare sulla proc la strategia da utilizzare - -- Conviene salvarsi tutti i dati fino alla lavorazione e il ciclo di applicazione va ad applicare senza calcolare? - - -- aggiungo la fase, se non è la prima - if nOrd == 1 then - EgtSetCurrPhase( 1) - else - BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, 0) - end - local nPhase = EgtGetCurrPhase() - local nDispId = EgtGetPhaseDisposition( nPhase) - EgtSetInfo( nDispId, 'TYPE', 'START') - EgtSetInfo( nDispId, 'ORD', nOrd) - EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( PARTS[nPart].idRaw) .. ' Part=' .. tostring( PARTS[nPart].id) .. ' ***', 1) - - -- debug - if EgtGetDebugLevel() >= 1 then - PrintFeatures( vProc, PARTS[nPart]) - end - EgtOutLog( ' *** AddMachinings ***', 1) - - -- TODO PROVVISORIO in attesa di scelta lavorazione in fase opportuna - vProc = vProcRot[1] - - -- ordino le features - vProc = OrderFeatures( vProc) - - -- TODO da fare - MACHININGS = {} - -- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale - CalculateMachinings( vProc, PARTS[nPart]) - - -- TODO riordinare lavorazioni ottimizzando cambio utensile/spezzone ecc..., mantenendo dipendenze definite prima - -- ordino le lavorazioni - -- OrderMachining( vProc, PARTS[nPart]) - - -- aggiunge effettivamente le lavorazioni - MachiningLib.AddOperations( vProc, PARTS[nPart]) - +------------------------------------------------------------------------------------------------------------- +local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart) + -- TODO funziona da sviluppare completamente + local BestCombination = {} + BestCombination = ProcessingsOnPart.Rotation[1] + return BestCombination +end +------------------------------------------------------------------------------------------------------------- +function BeamExec.ProcessMachinings( PROCESSINGS, PARTS) + -- ciclo sui pezzi + local nTotErr = 0 + local Stats = {} + local nOrd = 1 + local ProcessCompleted = false + local nMaxLoops = 5 -- TODO da rimuovere o lasciare solo per debug -if EgtGetDebugLevel() >= 3 then - local timeMachining = EgtStopCounter() - timeMachining = timeMachining + 0 - EgtOutBox( timeMachining, 'Machining calculation time') -end +--if EgtGetDebugLevel() >= 3 then +-- EgtStartCounter() +--end +-- TODO da rimuovere o lasciare solo per debug +--if EgtGetDebugLevel() >= 3 then +-- local timeCollect = EgtStopCounter() +-- timeCollect = timeCollect + 0 +-- EgtOutBox( timeCollect, 'Collect calculation time') +-- EgtStartCounter() +--end +-- TODO da rimuovere o lasciare solo per debug +--if EgtGetDebugLevel() >= 3 then +-- local timeMachining = EgtStopCounter() +-- timeMachining = timeMachining + 0 +-- EgtOutBox( timeMachining, 'Machining calculation time') +--end + local nCurrLoop = 0 + -- ciclo fino a che tutte le applicazioni delle lavorazioni sono corrette + while not ProcessCompleted do + -- aumento numero loop nel quale siamo + nCurrLoop = nCurrLoop + 1 + -- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni + for nPart = 1, #PARTS do + -- calcolo della migliore strategia per ogni rotazione del pezzo + for dRotIndex = 1, 4 do + PROCESSINGS[nPart].Rotation[dRotIndex] = GetBestStrategy( PROCESSINGS[nPart].Rotation[dRotIndex]) + end + -- si calcola la combinazione di lavorazione migliore + local vProc = GetBestResultFromCombinationsMatrix( PROCESSINGS[nPart]) - EgtOutLog( ' *** End AddMachinings ***', 1) - -- indice pezzo successivo - nOrd = nOrd + 1 - end + -- aggiungo la fase, se non è la prima + if nOrd == 1 then + EgtSetCurrPhase( 1) + else + BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, 0) + end + local nPhase = EgtGetCurrPhase() + local nDispId = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( nDispId, 'TYPE', 'START') + EgtSetInfo( nDispId, 'ORD', nOrd) + EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( PARTS[nPart].idRaw) .. ' Part=' .. tostring( PARTS[nPart].id) .. ' ***', 1) --- ===== finiti i pezzi, si scarica il restante ===== - local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw) - if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then - BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0) - local nPhase = EgtGetCurrPhase() - local nDispId = EgtGetPhaseDisposition( nPhase) - EgtSetInfo( nDispId, 'TYPE', 'REST') - EgtSetInfo( nDispId, 'ORD', nOrd) - end + -- debug + if EgtGetDebugLevel() >= 1 then + PrintFeatures( vProc, PARTS[nPart]) + end + EgtOutLog( ' *** AddMachinings ***', 1) - -- Aggiornamento finale di tutto - EgtSetCurrPhase( 1) - local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings() - -- eventuale ricalcolo per macchine tipo PF (ma tengo warning del primo calcolo) - if EgtExistsInfo( EgtGetCurrMachGroup(), 'RECALC') then - EgtOutLog( ' **** RECALC ****') - bApplOk, sApplErrors, _ = EgtApplyAllMachinings() - EgtRemoveInfo( EgtGetCurrMachGroup(), 'RECALC') - end - if not bApplOk then - nTotErr = nTotErr + 1 - table.insert( Stats, {nErr = 1, sMsg=sApplErrors, nRot=0, idCut=0, idTask=0}) - elseif sApplWarns and #sApplWarns > 0 then - local vLine = EgtSplitString( sApplWarns, '\r\n') - for i = 1, #vLine do - local nPos = vLine[i]:find( '(WRN', 1, true) - if nPos then - local sData = vLine[i]:sub( nPos + 1, -2) - local vVal = EgtSplitString( sData, ',') - local nWarn = EgtGetVal( vVal[1] or '', 'WRN', 'i') - local nCutId = EgtGetVal( vVal[2] or '', 'CUTID', 'i') - if nWarn and nCutId then - table.insert( Stats, { nErr=-nWarn, sMsg=vLine[i], nRot=0, idCut=nCutId, idTask=0}) + -- ordino le features + vProc = OrderFeatures( vProc) + + -- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale + CalculateMachinings( vProc, PARTS[nPart]) + + -- TODO riordinare lavorazioni ottimizzando cambio utensile/spezzone ecc..., mantenendo dipendenze definite prima + -- ordino le lavorazioni + -- OrderMachining( vProc, PARTS[nPart]) + + -- aggiunge effettivamente le lavorazioni + MachiningLib.AddOperations( vProc, PARTS[nPart]) + + EgtOutLog( ' *** End AddMachinings ***', 1) + -- indice pezzo successivo + nOrd = nOrd + 1 + end + + -- ===== finiti i pezzi, si scarica il restante ===== + local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw) + if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then + BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0) + local nPhase = EgtGetCurrPhase() + local nDispId = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( nDispId, 'TYPE', 'REST') + EgtSetInfo( nDispId, 'ORD', nOrd) + end + + -- Aggiornamento finale di tutto + EgtSetCurrPhase( 1) + local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings() + -- eventuale ricalcolo per macchine tipo PF (ma tengo warning del primo calcolo) + if EgtExistsInfo( EgtGetCurrMachGroup(), 'RECALC') then + EgtOutLog( ' **** RECALC ****') + bApplOk, sApplErrors, _ = EgtApplyAllMachinings() + EgtRemoveInfo( EgtGetCurrMachGroup(), 'RECALC') + end + if not bApplOk then + nTotErr = nTotErr + 1 + table.insert( Stats, {nErr = 1, sMsg=sApplErrors, nRot=0, idCut=0, idTask=0}) + elseif sApplWarns and #sApplWarns > 0 then + local vLine = EgtSplitString( sApplWarns, '\r\n') + for i = 1, #vLine do + local nPos = vLine[i]:find( '(WRN', 1, true) + if nPos then + local sData = vLine[i]:sub( nPos + 1, -2) + local vVal = EgtSplitString( sData, ',') + local nWarn = EgtGetVal( vVal[1] or '', 'WRN', 'i') + local nCutId = EgtGetVal( vVal[2] or '', 'CUTID', 'i') + if nWarn and nCutId then + table.insert( Stats, { nErr=-nWarn, sMsg=vLine[i], nRot=0, idCut=nCutId, idTask=0}) + end end end end + + -- TODO per il momento non si cicla mai una seconda volta. Controllare anche parametro modalità scelta strategia + -- Gestione da fare completamente. La strategia che ha generato una lavorazione con errore deve essere annullata + -- si fa un reset del MACH e poi si ritorna a inizio ciclo e si rifà tutto + -- se i cicli superano il massimo si esce (nell'ultimo ciclo possibile si potrebbe escludere la feature e basta, anche se avesse altre strategie da provare) + if true or nCurrLoop > nMaxLoops then + ProcessCompleted = true + end end return ( nTotErr == 0), Stats diff --git a/Process.lua b/Process.lua index 862bc71..1d345f8 100644 --- a/Process.lua +++ b/Process.lua @@ -75,7 +75,8 @@ end local BeamExec = require( 'BeamExec') -- Variabili globali -PARTS = {} +PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo +PROCESSINGS = {} -- tabella contenente tutte le informazioni di ogni feature, processate per ogni rotazione -- Carico i dati globali local BeamData = require( 'BeamData') @@ -304,7 +305,8 @@ end -- *** Inserimento delle lavorazioni nelle travi *** ------------------------------------------------------------------------------------------------------------- local function MyProcessFeatures() - local bOk, Stats = BeamExec.ProcessFeatures( PARTS) + local PROCESSINGS = BeamExec.GetProcessings( PROCESSINGS, PARTS) + local bOk, Stats = BeamExec.ProcessMachinings( PROCESSINGS, PARTS) local nErrCnt = 0 local nWarnCnt = 0 local sOutput = ''