From 21da5f633db04f1c18f5b502d7a596b9c2e75147 Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Mon, 4 Nov 2024 16:52:42 +0100 Subject: [PATCH] - Prima bozza gestione matrice delle rotazioni - Adeguamento strategia 0002 e SPLITCUT a nuovo metodo gestione matrice --- LuaLibs/BeamExec.lua | 269 +++++++++++++++++++++- LuaLibs/BeamLib.lua | 48 ++++ LuaLibs/FeatureData.lua | 14 +- LuaLibs/MachiningLib.lua | 2 - Strategies/Standard/SPLITCUT/SPLITCUT.lua | 6 + Strategies/Standard/STR0002/STR0002.lua | 4 + 6 files changed, 330 insertions(+), 13 deletions(-) diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 15d3b86..ecb6445 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -101,9 +101,6 @@ function BeamExec.GetToolsFromDB() -- se verifica condizioni minime, recupero tutti gli altri dati if bToolLoadedOnSetup and sToolType then - -- TODO Tool.AName -> da rimuovere perchè non serve. Per il momento lo manteniamo solo perchè è più facile vedere e interpretare la lista utensili nella watch di zerobrane - -- Nell'utilizzo, si legge sempre il Tool.Name - Tool.AName = Tool.sName Tool.sTcPos = sToolTCPos Tool.sFamily = sToolFamily Tool.sType = sToolType @@ -673,6 +670,8 @@ local function GetIndexBestStrategyFromComparison( AvailableStrategies, nIndex1, -- controllo indici if nIndex1 == 0 and nIndex2 == 0 then dChosenIndex = 0 + elseif nIndex1 == nIndex2 then + dChosenIndex = nIndex1 elseif nIndex1 == 0 then -- basta che sia applicabile if AvailableStrategies[nIndex2].Result and ( AvailableStrategies[nIndex2].Result.sStatus == 'Completed' or AvailableStrategies[nIndex2].Result.sStatus == 'Not-Completed') then @@ -695,8 +694,8 @@ local function GetIndexBestStrategyFromComparison( AvailableStrategies, nIndex1, -- se le due strategie hanno stesso stato e sono entrambe applicabili (quindi entrambe complete o entrambe non-complete) if AvailableStrategies[nIndex1].Result.sStatus ~= 'Not-Applicable' and AvailableStrategies[nIndex2].Result.sStatus ~= 'Not-Applicable' and AvailableStrategies[nIndex1].Result.sStatus == AvailableStrategies[nIndex2].Result.sStatus then - local dCompositeRatingStrategy1 = AvailableStrategies[nIndex1].Result.nQuality * AvailableStrategies[nIndex1].Result.nCompletionIndex * AvailableStrategies[nIndex1].Result.dMRR - local dCompositeRatingStrategy2 = AvailableStrategies[nIndex2].Result.nQuality * AvailableStrategies[nIndex2].Result.nCompletionIndex * AvailableStrategies[nIndex2].Result.dMRR + local dCompositeRatingStrategy1 = AvailableStrategies[nIndex1].Result.dCompositeRating + local dCompositeRatingStrategy2 = AvailableStrategies[nIndex2].Result.dCompositeRating -- si predilige strategia con rating composito più alto if dCompositeRatingStrategy1 > dCompositeRatingStrategy2 then dChosenIndex = nIndex1 @@ -756,6 +755,7 @@ local function CalculateStrategies( vProcSingleRot, Part) -- 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) + Proc.AvailableStrategies[nIndexCurrentStrategy].Result = FeatureData.CalculateCompositeRating( Proc.AvailableStrategies[nIndexCurrentStrategy].Result) -- 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 Proc.AvailableStrategies[nIndexCurrentStrategy].Result.sStatus == 'Complete' then @@ -924,12 +924,259 @@ function BeamExec.GetProcessings( PROCESSINGS, PARTS) end ------------------------------------------------------------------------------------------------------------- -local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart) - -- TODO funziona da sviluppare completamente - local BestCombination = {} - BestCombination = ProcessingsOnPart.Rotation[1] - return BestCombination +-- funzione che controlla validità delle combinazioni proposte +local function IsCombinationAvailable( sCombination, nUnloadPos) + -- TODO : DA COMPLETARE CON LE POSSIBILI TIPOLOGIA DI SCELTA ROTAZIONE + local ExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3) + + -- NON VALIDA SE : rotazione di partenza non attiva o se attiva la 3 rotazione(non gestita attualmente) + if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, ExtraRotation, ExtraRotation) == '1' then + return false + else + return true + end end + +------------------------------------------------------------------------------------------------------------- +-- funzione che decide le combinazioni di rotazione per lavorare la trave +local function GetBestCombination( ListToCompare) + -- TODO scellta combinazione da fare!!! + local ChosenCombination = ListToCompare[1] + + return ChosenCombination +end + +------------------------------------------------------------------------------------------------------------- +-- funzione che decide le combinazioni di rotazione per lavorare la trave +local function GetProcessingListFromCombination( BestCombination) + local vProc = {} + + -- aggiungo processing da fare in fase ribaltata + if #BestCombination.Rot180 > 0 then + for i = 1, #BestCombination.Rot180 do + BestCombination.Rot180[i].bDown = true + table.insert( vProc, BestCombination.Rot180[i]) + end + end + + -- aggiungo processing da fare in fase ruotata + if #BestCombination.Rot90 > 0 then + for i = 1, #BestCombination.Rot90 do + BestCombination.Rot90[i].bSide = true + table.insert( vProc, BestCombination.Rot90[i]) + end + end + + -- aggiungo processing da fare in ultima fase + if #BestCombination.Rot0 > 0 then + for i = 1, #BestCombination.Rot0 do + table.insert( vProc, BestCombination.Rot0[i]) + end + end + + return vProc +end + +------------------------------------------------------------------------------------------------------------- +-- funzione che ritorna la Proc nella rotazione scelta +local function GetProcBestMachRotationFromList( ListToCompare) + local Data = {} + local Proc = {} + local nIndexChosenProcInRot = 1 + + -- se ci sono almeno 2 possibili soluzioni, scelgo la posizione migliore di lavorazione + if #ListToCompare > 1 then + -- formatto lista strategie disponibili come se le aspetta la funzione di compare + local AvailableStrategiesInRot = {} + for i = 1, #ListToCompare do + table.insert( AvailableStrategiesInRot, ListToCompare[i][1].ChosenStrategy) + end + for nIndexCurrentStrategy = 1, #AvailableStrategiesInRot do + -- la scelta tra le differenti strategie tra le rotazioni utilizza gli stessi criteri della scelta strategie all'interno della feature stessa + nIndexChosenProcInRot = GetIndexBestStrategyFromComparison( AvailableStrategiesInRot, nIndexCurrentStrategy, nIndexChosenProcInRot) + end + -- altrimenti prendo la prima + else + nIndexChosenProcInRot = 1 + end + + Proc = ListToCompare[nIndexChosenProcInRot][1] + Data.nIndexRotation = ListToCompare[nIndexChosenProcInRot].nRotation + Data.dCompositeRating = ListToCompare[nIndexChosenProcInRot][1].ChosenStrategy.Result.dCompositeRating + Data.bComplete = ListToCompare[nIndexChosenProcInRot][1].ChosenStrategy.Result.sStatus == 'Completed' + Data.bNotComplete = ListToCompare[nIndexChosenProcInRot][1].ChosenStrategy.Result.sStatus == 'Not-Completed' + Data.bNotExecute = ListToCompare[nIndexChosenProcInRot][1].ChosenStrategy.Result.sStatus == 'Not-Applicable' + return Proc, Data +end + +------------------------------------------------------------------------------------------------------------- +local function WriteMatrixLog( ProcessingsOnPart) + EgtOutLog( ' === === === === === === === === === === ROTATION MATRIX === === === === === === === === === === === === ===') + EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |') + EgtOutLog( '----------------------------------------------------------------------------------------------------------') + + for ProcLog = 1, #ProcessingsOnPart.Rotation[1] do + local sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[1][ProcLog].id) + while string.len( sLogLine) <= 20 do + sLogLine = sLogLine .. ' ' + end + sLogLine = sLogLine .. '|' + for nRotLog = 1, 4 do + if ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy then + local sLogLineProc = tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.dCompositeRating) .. + ' (' .. tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.sStrategyId) .. ') |' + while string.len( sLogLineProc) <= 20 do + sLogLineProc = ' ' .. sLogLineProc + end + sLogLine = sLogLine .. sLogLineProc + else + sLogLine = sLogLine .. ' 0 (STR----) |' + end + end + EgtOutLog( sLogLine) + end + EgtOutLog( '----------------------------------------------------------------------------------------------------------') +end +------------------------------------------------------------------------------------------------------------- +local function WriteCombinationLog( CombinationsList, BestCombination) + EgtOutLog( ' === === === === === === === === === === COMBINATIONS === === === === === === ') + EgtOutLog( ' COMBI (UNL) | RATING | COMPLETE | NO COMPL | NO EXEC | ROTATE |') + EgtOutLog( '---------------------------------------------------------------------------') + + for CombiLog = 1, #CombinationsList do + local sLogLine = ' ' .. CombinationsList[CombiLog].sBitIndexCombination .. ' (' .. CombinationsList[CombiLog].nUnloadPos .. ') |' + -- rating + local sOtherField = tostring( CombinationsList[CombiLog].dTotalRating) .. ' |' + while string.len( sOtherField) <= 11 do + sOtherField = ' ' .. sOtherField + end + sLogLine = sLogLine .. sOtherField + -- completed + sOtherField = tostring( CombinationsList[CombiLog].nComplete) .. ' |' + while string.len( sOtherField) <= 11 do + sOtherField = ' ' .. sOtherField + end + sLogLine = sLogLine .. sOtherField + -- not completed + sOtherField = tostring( CombinationsList[CombiLog].nNotComplete) .. ' |' + while string.len( sOtherField) <= 11 do + sOtherField = ' ' .. sOtherField + end + sLogLine = sLogLine .. sOtherField + -- not executed + sOtherField = tostring( CombinationsList[CombiLog].nNotExecute) .. ' |' + while string.len( sOtherField) <= 11 do + sOtherField = ' ' .. sOtherField + end + sLogLine = sLogLine .. sOtherField + -- rotations + sOtherField = tostring( CombinationsList[CombiLog].nRotations) .. ' |' + while string.len( sOtherField) <= 11 do + sOtherField = ' ' .. sOtherField + end + sLogLine = sLogLine .. sOtherField + + EgtOutLog( sLogLine) + end + EgtOutLog( '----------------------------------------') + EgtOutLog( ' BEST ROTATION : ' .. BestCombination.sBitIndexCombination .. ' (' .. BestCombination.nUnloadPos .. ')') + EgtOutLog( '---------------------------------------------------------------------------') +end + +------------------------------------------------------------------------------------------------------------- +-- funzione che decide le combinazioni di rotazione per lavorare la trave +local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart) + -- TODO funzione da sviluppare completamente + local BestCombination = {} + local CombinationsList = {} + + -- scrittura nel log della matrice delle rotazioni + if EgtGetDebugLevel() >= 3 then + WriteMatrixLog( ProcessingsOnPart) + end + + -- per ogni posizione di scarico + for nUnloadPos = 1, 4 do + -- verifico tutte le combinazioni che ripettano lo scarico come desiderato + for i = 1, BeamLib.BinaryToDecimal( 1111) do + local nBitIndexCombination = BeamLib.DecimalToBinary( i) + local sBitIndexCombination = BeamLib.CalculateStringBinaryFormat( nBitIndexCombination, 4) + if IsCombinationAvailable( sBitIndexCombination, nUnloadPos) then + local bRot90, bRot180 + local SingleCombination = {} + SingleCombination.nRotations = 0 + SingleCombination.dTotalRating = 0 + SingleCombination.nComplete = 0 + SingleCombination.nNotComplete = 0 + SingleCombination.nNotExecute = 0 + SingleCombination.sBitIndexCombination = sBitIndexCombination + SingleCombination.nUnloadPos = nUnloadPos + -- creo liste dei proc suddivisi per rotazione + SingleCombination.Rot0 = {} + SingleCombination.Rot90 = {} + SingleCombination.Rot180 = {} + + -- ciclo su tutte le feature + for nProc = 1, #ProcessingsOnPart.Rotation[1] do + -- ciclo sulle rotazioni + local nNextRot = nUnloadPos + local ResultsList = {} + for nRotation = 1, 3 do + -- se rotazione abilitata da combinazione + if string.sub( sBitIndexCombination, nNextRot, nNextRot) == '1' then + -- controllo se è stata scelta una strategia + if ProcessingsOnPart.Rotation[nRotation][nProc].ChosenStrategy then + local Proc = {} + Proc.nRotation = nNextRot + table.insert( Proc, ProcessingsOnPart.Rotation[nNextRot][nProc]) + table.insert( ResultsList, Proc) + end + end + nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1) + end + + -- se la feature può essere lavorata in almeno una rotazione + if #ResultsList > 0 then + local Proc, Data = GetProcBestMachRotationFromList( ResultsList) + -- inserisco la Proc nell'apposita lista + if Data.nIndexRotation == nUnloadPos then + table.insert( SingleCombination.Rot0, Proc) + elseif Data.nIndexRotation == nUnloadPos + 1 then + table.insert( SingleCombination.Rot90, Proc) + bRot90 = true + else + table.insert( SingleCombination.Rot180, Proc) + bRot180 = true + end + + SingleCombination.dTotalRating = SingleCombination.dTotalRating + Data.dCompositeRating + SingleCombination.nComplete = SingleCombination.nComplete + EgtIf( Data.bComplete, 1, 0) + SingleCombination.nNotComplete = SingleCombination.nNotComplete + EgtIf( Data.bNotComplete, 1, 0) + SingleCombination.nNotExecute = SingleCombination.nNotExecute + EgtIf( Data.bNotExecute, 1, 0) + else + SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1 + end + end + -- aggiungo rotazioni + SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0) + -- aggiungo la combinazione all'elenco delle combinazioni disponibili + table.insert( CombinationsList, SingleCombination) + end + end + end + + BestCombination = GetBestCombination( CombinationsList) + + -- scrittura nel log delle combinazioni possibili + if EgtGetDebugLevel() >= 3 then + WriteCombinationLog( CombinationsList, BestCombination) + end + + local vFinalProc = GetProcessingListFromCombination( BestCombination) + + return vFinalProc +end + ------------------------------------------------------------------------------------------------------------- function BeamExec.ProcessMachinings( PROCESSINGS, PARTS) -- ciclo sui pezzi @@ -1003,6 +1250,8 @@ function BeamExec.ProcessMachinings( PROCESSINGS, PARTS) MachiningLib.AddOperations( vProc, PARTS[nPart]) EgtOutLog( ' *** End AddMachinings ***', 1) + -- azzero lavorazioni per pezzo successivo + MACHININGS = {} -- indice pezzo successivo nOrd = nOrd + 1 end diff --git a/LuaLibs/BeamLib.lua b/LuaLibs/BeamLib.lua index fa9b14e..5cddb0a 100644 --- a/LuaLibs/BeamLib.lua +++ b/LuaLibs/BeamLib.lua @@ -350,5 +350,53 @@ function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut) return '' end +--------------------------------------------------------------------- +function BeamLib.BinaryToDecimal( dNumber) + local sNumberToConvert = tostring( dNumber) + local dResult = 0 + local k = 0 + + for i = #sNumberToConvert, 1, -1 do + k = k + 1 + local n = string.sub(sNumberToConvert, k, k) + dResult = dResult + n*(2^(i-1)) + end + + return dResult +end + +--------------------------------------------------------------------- +function BeamLib.DecimalToBinary( dNumber) + local sNumberToConvert = tostring( dNumber) + local n = sNumberToConvert + local tmp = {} + local sResult = "" + + for i = sNumberToConvert, 0, -1 do + local q = math.modf(n) + n = n/2 + local b = q%2 + table.insert(tmp, b) + + if (q == 1) then + break + end + end + + for i = #tmp, 1, -1 do + sResult = sResult..tmp[i] + end + + return tonumber( sResult) +end + +--------------------------------------------------------------------- +function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber) + local NumberString = tostring( dNumber) + while #NumberString < CharNumber do + NumberString = '0' .. NumberString + end + return NumberString +end ------------------------------------------------------------------------------------------------------------- return BeamLib diff --git a/LuaLibs/FeatureData.lua b/LuaLibs/FeatureData.lua index d9a3e28..0489858 100644 --- a/LuaLibs/FeatureData.lua +++ b/LuaLibs/FeatureData.lua @@ -275,12 +275,24 @@ function FeatureData.GetFeatureQuality( sTypeTools) end -- se si utilizzano più utensili si perde in qualità if #TypeTools > 1 then - nQuality = nQuality - 1 + nQuality = max( nQuality - 1, 0.5) end return nQuality end +------------------------------------------------------------------------------------------------------------- +-- funzione che calcola il 'CompositeRating' di ogni strategia +function FeatureData.CalculateCompositeRating( StrategyResult) + -- se ho tutti i dati che mi servono calcolo il rating della strategia applicato alla feature + if StrategyResult and StrategyResult.nQuality and StrategyResult.nCompletionIndex and StrategyResult.dMRR then + StrategyResult.dCompositeRating = ceil( StrategyResult.nQuality * StrategyResult.nCompletionIndex * StrategyResult.dMRR) + else + StrategyResult.dCompositeRating = 0 + end + + return StrategyResult +end ------------------------------------------------------------------------------------------------------------- return FeatureData \ No newline at end of file diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua index f0f74a5..f9f377e 100644 --- a/LuaLibs/MachiningLib.lua +++ b/LuaLibs/MachiningLib.lua @@ -527,7 +527,6 @@ function MachiningLib.AddOperations( vProc, Part) EgtSetOperationMode( nOperationId, false) end - -- TODO è giusto inserire queste info alla fine della lavorazione? oppure conviene creare un record in MACHININGS apposito per la disposizione? -- se era taglio di separazione, aggiungo nuova fase if MACHININGS[i].AuxiliaryData.bAddNewPhase then @@ -542,7 +541,6 @@ function MachiningLib.AddOperations( vProc, Part) EgtSetInfo( nDispId, 'TYPE', 'END') EgtSetInfo( nDispId, 'ORD', MACHININGS[i].Proc.nIndexPartInParts) end - else return false, 'UNEXPECTED ERROR: Error on creating machining' end diff --git a/Strategies/Standard/SPLITCUT/SPLITCUT.lua b/Strategies/Standard/SPLITCUT/SPLITCUT.lua index 4a6cd6f..831df7e 100644 --- a/Strategies/Standard/SPLITCUT/SPLITCUT.lua +++ b/Strategies/Standard/SPLITCUT/SPLITCUT.lua @@ -183,6 +183,7 @@ local function GetSplitStrategy( Proc, Part) -- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos) -- BladeSideSingle (taglio di lama singolo di fianco) if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then + Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade') Machining.sTypeMachining = 'BladeSideSingle' Machining[2].bIsApplicable = false Machining[3].bIsApplicable = false @@ -191,6 +192,8 @@ local function GetSplitStrategy( Proc, Part) -- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos) -- BladeSideDouble (taglio di lama doppio di fianco) elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then + Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade') + Strategy.Result.dMRR = Strategy.Result.dMRR/2 Machining.sTypeMachining = 'BladeSideDouble' Machining[2].bIsApplicable = false Machining[3].bIsApplicable = false @@ -198,6 +201,7 @@ local function GetSplitStrategy( Proc, Part) return Machining -- BladeHorizontalSingle (taglio di lama singolo orizzontale) elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then + Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade') Machining.sTypeMachining = 'BladeHorizontalSingle' Machining[2].bIsApplicable = false Machining[3].bIsApplicable = false @@ -206,6 +210,8 @@ local function GetSplitStrategy( Proc, Part) -- BladeHorizontalDouble (taglio di lama doppio orizzontale) elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and ( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then + Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade') + Strategy.Result.dMRR = Strategy.Result.dMRR/2 Machining.sTypeMachining = 'BladeHorizontalDouble' Machining[3].bIsApplicable = false Machining[4].bIsApplicable = false diff --git a/Strategies/Standard/STR0002/STR0002.lua b/Strategies/Standard/STR0002/STR0002.lua index ede2c79..b480ca0 100644 --- a/Strategies/Standard/STR0002/STR0002.lua +++ b/Strategies/Standard/STR0002/STR0002.lua @@ -134,6 +134,10 @@ local function GetBestPocketingStrategy( Proc) Milling.ToolInfo = {} Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters) if Milling.ToolInfo.nToolIndex then + -- se utensile scelto è su aggregato, ricalcolo la qualità + if TOOLS[Milling.ToolInfo.nToolIndex].SetupInfo.bToolOnAggregate then + Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'MillOnAggregate') + end Milling.bIsApplicable = true local ParametersMRR = {} ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex