- 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)
This commit is contained in:
andrea.villa
2024-10-09 13:16:11 +02:00
parent 23d5f82403
commit 35e8ef2482
2 changed files with 175 additions and 147 deletions
+171 -145
View File
@@ -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