-- Processore macchina Essetre-WALL by EgalTech s.r.l. 2022/03/08 -- Funzioni generiche indipendenti dal controllo -- 2020/07/21 ver 2.3g5 DS Modificata ExecScrapRemove per maggiore precisione nel riconoscere i veri sfridi. -- 2020/09/16 ver 2.3i1 DS Correzione a ExecScrapRemove per evitare crash (va approfondita). -- 2020/09/16 ver 2.3i2 DS Riportato ExecScrapRemove e gestione collisioni da Wall_90480026 (cliente portoghese). -- 2020/10/22 ver 2.3j4 DS Corretto problema mancato posizionamento B1=90 e C1=90 quando si seleziona H14. -- 2022/01/20 ver 2.4a3 DS In ExecScrapRemove migliorato calcolo centro di ogni parte del Vmill. -- 2022/01/20 ver 2.4a3 DS Aggiunta gestione ingombri riferimenti per collisioni. -- 2022/03/08 ver 2.4c1 DS In ExecScrapRemove si accettano pezzi fino a 19% dell'originale. -- Intestazioni require( 'EmtGenerator') EgtEnableDebug( false) --------------------------------------------------------------------- -- *** GENERATION *** --------------------------------------------------------------------- local sBaseDir = EgtGetCurrMachineDir() if NumericalControl == 'NUM' then dofile( sBaseDir .. '\\Essetre-WALL.NUM.mlpe') elseif NumericalControl == 'TPA' then error( 'Numerical Control error : TPA not yet managed') --dofile( sBaseDir .. 'Essetre-WALL.TPA.mlpe') else error( 'Numerical Control error : unkwnown type') end --------------------------------------------------------------------- -- *** SIMULATION *** --------------------------------------------------------------------- local COLL_SAFE_DIST = 2 --------------------------------------------------------------------- function OnSimulStart() -- Carico gli utensili sulle barre portautensili local vTcPos = EgtGetAllTcPosNames() if vTcPos then for i = 1, #vTcPos do local vTools = EgtGetToolsInCurrSetupPos( vTcPos[i]) if vTools and vTools[1] then EgtLoadTool( vTcPos[i], 1, vTools[1]) ShowToolInTcPos( vTcPos[i], true) end end end -- Se reset o home, esco if EMT.SIM1ST then return end -- Non effettuate lavorazioni con sega a catena sul fianco EMT.CSAWFIRST = true -- Non effettuata pausa per rimozione sfridi EMT.SCRAPFIRST = true -- Creo o svuoto gruppo per copia finale degli oggetti virtual milling local nVmGrpId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'VMill') if nVmGrpId then EgtSetStatus( nVmGrpId, GDB_ST.ON) EgtEmptyGroup( nVmGrpId) else nVmGrpId = EgtGroup( GDB_ID.ROOT) EgtSetName( nVmGrpId, 'VMill') EgtSetLevel( nVmGrpId, GDB_LV.TEMP) end -- Preparo lista oggetti da verificare per collisioni EMT.COLLOBJ = {} AddToCollisionCheck( 'B1', 'COLLISION', EMT.COLLOBJ) AddToCollisionCheck( 'C1', 'COLLISION', EMT.COLLOBJ) AddToCollisionCheck( 'C2', 'COLLISION', EMT.COLLOBJ) DumpCollisionCheck( EMT.COLLOBJ, 'Collision Objects :', 4) -- Preparo lista solidi macchina con cui possono collidere gli oggetti sopra riportati (in aggiunta a VMill) EMT.MCODET = {} EMT.MCODET[1] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'TRAV') EMT.MCODET[2] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'COL1') EMT.MCODET[3] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'COL2') EMT.MCODET[4] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'TC1') EMT.MCODET[5] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'TC2') EMT.MCODET[6] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'TC3') EMT.MCODET[7] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'Y'), 'COLLISION'), 'TC4') EMT.MCODET[8] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetAxisId( 'X1'), 'COLLISION'), 'TRAV') EMT.MCODET[9] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'STM') EMT.MCODET[10] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref1_1') EMT.MCODET[11] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref1_2') EMT.MCODET[12] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref1_3') EMT.MCODET[13] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref1_4') EMT.MCODET[14] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref1_5') EMT.MCODET[15] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref3_1') EMT.MCODET[16] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref3_2') EMT.MCODET[17] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref3_3') EMT.MCODET[18] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref3_4') EMT.MCODET[19] = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( EgtGetBaseId( 'Base'), 'COLLISION'), 'Ref3_5') for i = #EMT.MCODET, 1, -1 do if not EMT.MCODET[i] then table.remove( EMT.MCODET, i) EgtOutLog( 'Warning : MCODET element (' .. tostring( i) .. ') is null') end end -- Preparo lista collisioni vuota EMT.COLLIDE = {} end --------------------------------------------------------------------- function OnSimulEnd() if EMT.SCRAPFIRST then EMT.SCRAPFIRST = false ExecScrapRemove() end ExecUnloading() end --------------------------------------------------------------------- --function OnSimulDispositionStarting() --end --------------------------------------------------------------------- function OnSimulDispositionStart() EMT.OPEISDISP = true -- dati del grezzo local nRawId = EgtGetFirstRawPart() local b3Raw = EgtGetRawPartBBox( nRawId or GDB_ID.NULL) -- Se prima disposizione (dovrebbe essere l'unica) if EMT.PHASE == 1 then -- Assegno dimensioni del grezzo EMT.LB = 0 EMT.SB = 0 EMT.HB = 0 if b3Raw then EMT.LB = b3Raw:getDimX() EMT.SB = b3Raw:getDimY() EMT.HB = b3Raw:getDimZ() end -- Carico primo utensile sulla testa 1 local sTool = FindFirstToolOnHead( 'H1') if sTool then EMT.TOOL_1 = sTool --EgtLoadTool( 'H1', 1, EMT.TOOL_1) EgtSetCalcTool( EMT.TOOL_1, 'H1', 1) EgtResetAxisPos( 'C1') EgtResetAxisPos( 'B1') EMT.TCPOS_1 = GetToolTcPos( EMT.TOOL_1) ShowToolInTcPos( EMT.TCPOS_1, false) else EgtUnloadTool( 'H1', 1) end -- Se vero inizio, abilitato e trovato grezzo, creazione Zmap if not EMT.SIM1ST and EgtGetInfo( EgtGetCurrMachGroup(), 'Vm', 'b') and nRawId then -- elimino eventuale vecchio Zmap EgtErase( EgtGetFirstNameInGroup( nRawId, 'VMill') or GDB_ID.NULL) -- determino la risoluzione dello Zmap local dArea = b3Raw:getDimX() * b3Raw:getDimY() + b3Raw:getDimX() * b3Raw:getDimZ() + b3Raw:getDimY() * b3Raw:getDimZ() local dTol = 3.81 if dArea < CoeffVM * 6.0e6 then dTol = 2.03 elseif dArea < CoeffVM * 12.0e6 then dTol = 2.57 elseif dArea < CoeffVM * 24.0e6 then dTol = 3.11 end local nOperCnt = EgtGetGroupObjs( EgtGetFirstNameInGroup( EgtGetCurrMachGroup(), 'Opers')) if nOperCnt > 500 then dTol = 5.71 end -- verifico se grezzo ruotato local refRaw = EgtGetGroupGlobFrame( nRawId) local bRefXYZ = AreSameVectorApprox( refRaw:getVersX(), X_AX()) and AreSameVectorApprox( refRaw:getVersY(), Y_AX()) -- creo lo Zmap if bRefXYZ then EMT.VMILL = EgtVolZmapBox( nRawId, b3Raw:getMin(), b3Raw:getDimX(), b3Raw:getDimY(), b3Raw:getDimZ(), dTol, true, GDB_RT.GLOB) else local nSolId = EgtGetFirstNameInGroup( nRawId, 'RawSolid') EMT.VMILL = EgtVolZmapFromSurfTm( nRawId, nSolId, dTol, true) end if EMT.VMILL then EgtSetName( EMT.VMILL, 'VMill') EgtSetLevel( EMT.VMILL, GDB_LV.TEMP) local nSolId = EgtGetFirstNameInGroup( nRawId, 'RawSolid') EgtSetColor( EMT.VMILL, EgtGetColor( nSolId), false) -- nascondo le altre geometrie local nId = EgtGetFirstInGroup( nRawId) while nId do if nId ~= EMT.VMILL then EgtSetStatus( nId, GDB_ST.OFF) end nId = EgtGetNext( nId) end EgtSetStatus( EMT.SCRAP or GDB_ID.NULL, GDB_ST.OFF) -- imposto eventuale utensile corrente SetToolForVmill( EMT.TOOL, EMT.HEAD, EMT.EXIT, EMT.VMILL) end end end -- se vero inizio, assegno solidi per verifica collisione if not EMT.SIM1ST then EMT.CODET = {} for i = 1, #EMT.MCODET do EMT.CODET[i] = EMT.MCODET[i] end if EMT.VMILL then table.insert( EMT.CODET, EMT.VMILL) end end -- Nascondo tutte le lavorazioni local nMchId = EgtGetFirstOperation() while nMchId do if EgtGetOperationType( nMchId) ~= MCH_OY.DISP then EgtSetOperationStatus( nMchId, false) end nMchId = EgtGetNextOperation( nMchId) end end --------------------------------------------------------------------- function OnSimulDispositionEnd() if EMT.UNLOADING or EMT.FALL then EMT.UNLOADING = false EMT.FALL = false end EMT.OPEISDISP = false end --------------------------------------------------------------------- function OnSimulToolSelect() -- se utensile non definito, è disposizione ed esco if EMT.TOOL == '' then return end -- recupero dati utensile EMT.TOOLTYPE = EgtTdbGetCurrToolParam( MCH_TP.TYPE) EMT.TOOLTOTLEN = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) -- se non lama su rinvio o graffettatrici, carico utensile if EMT.HEAD == 'H1' or EMT.HEAD == 'H3' then -- se sega a catena, imposto subito angolo scelto per asse virtuale A if EMT.HEAD == 'H3' then -- recupero la lavorazione successiva local NextMchId if EMT.MCHID then NextMchId = EgtGetNextActiveOperation( EMT.MCHID) else NextMchId = EgtGetFirstActiveOperation() end if EgtGetOperationType( NextMchId) == MCH_OY.DISP then NextMchId = EgtGetNextActiveOperation( NextMchId) end EgtSetCurrMachining( NextMchId) -- leggo e imposto il valore di A1 local sVal = EgtGetMachiningParam( MCH_MP.BLOCKEDAXIS) local CSawPosA = EgtGetVal( sVal, 'A1', 'd') or 0 EgtSetAxisPos( 'A1', CSawPosA) EmtModifyAxisHome( 'A1', CSawPosA) EgtSetAxisPos( 'C1', GetChainSawCHomeFromVirtualAxis( CSawPosA)) -- se lama grande elseif EMT.HEAD == 'H1' and EMT.TCPOS == 'T203' then EgtSetAxisPos( 'X1', -2200) end EgtResetAxisPos( 'C1') EgtResetAxisPos( 'B1') -- breve pausa EgtPause( 100) EgtOutText( '') EMT.TOOL_1 = EMT.TOOL EMT.TCPOS_1 = EMT.TCPOS -- lo nascondo sul portautensili ShowToolInTcPos( EMT.TCPOS, false) -- se altrimenti graffettatrice su testa 1, tolgo utensile da testa e imposto opportunamente B e C elseif EMT.HEAD == 'H14' then -- nascondo utensile su testa e lo visualizzo su TcPos EgtSetStatus( EgtGetHeadId( 'H1'), GDB_ST.OFF) ShowToolInTcPos( EMT.TCPOS_1, true) EMT.TOOL_1 = nil EMT.TCPOS_1 = nil -- imposto assi rotanti B90 C90 EgtSetAxisPos( 'C1', 90) EgtSetAxisPos( 'B1', 90) end -- se attivo Vmill SetToolForVmill( EMT.TOOL, EMT.HEAD, EMT.EXIT, EMT.VMILL) -- se attivo Collision Check EMT.SAFEDIST = COLL_SAFE_DIST if EMT.COLLOBJ then local nInd = EgtIf( EMT.HEAD ~= 'H2', 1001, 1011) AddToolToCollisionObj( EMT.TOOL, EMT.HEAD, EMT.EXIT, nInd) AddToolHolderToCollisionObj( EMT.TOOL, EMT.HEAD, EMT.EXIT, nInd + 1) for i, Coll in ipairs( EMT.COLLOBJ) do EmtAddCollisionObjEx( i, Coll.Fr, Coll.Ty, Coll.Mv, Coll.P1, Coll.P2, Coll.P3) end end end --------------------------------------------------------------------- function OnSimulToolDeselect() -- Step di simulazione local RapSimStep = 4 * EMT.SIMSTEP local RapSimRotStep = RapSimStep / 10 local CollSimRotStep = min( RapSimRotStep, 5) -- porto la testa in home if EMT.HEAD == 'H2' or EMT.HEAD == 'H21' or EMT.HEAD == 'H22' or EMT.HEAD == 'H23' then SimulMoveAxes( 'X2', MaxX2, RapSimStep, 'C2', EgtGetAxisHomePos( 'C2'), RapSimRotStep, 'B2', EgtGetAxisHomePos( 'B2'), RapSimRotStep) else local ParkX1 = EgtIf( EMT.HEAD == 'H3', ( MinX1 + MaxX1) / 2, MinX1) SimulMoveAxes( 'X1', ParkX1, RapSimStep, 'C1', EgtGetAxisHomePos( 'C1'), RapSimRotStep, 'B1', EgtGetAxisHomePos( 'B1'), RapSimRotStep) end -- se testa attuale è sega a catena devo depositarla if EMT.HEAD == 'H3' then ShowToolInTcPos( EMT.TCPOS_1, true) EgtUnloadTool( 'H3', 1) EMT.TOOL_1 = nil EMT.TCPOS_1 = nil end -- se testa attuale è lama devo depositarla if EMT.HEAD == 'H12' then ShowToolInTcPos( EMT.TCPOS_1, true) EgtUnloadTool( 'H12', 1) EMT.TOOL_1 = nil EMT.TCPOS_1 = nil end -- deposito utensile se non lama su rinvio o graffettatrici if ( EMT.NEXTHEAD == 'H1' or EMT.NEXTHEAD == 'H3') and ( EMT.HEAD == 'H1' or EMT.HEAD == 'H3') then if EMT.NEXTTOOL ~= EMT.TOOL_1 then EgtOutText( 'Tool change in progress...') -- simulo movimento SimulMoveAxes( 'B', 90, CollSimRotStep, 'C', -90, CollSimRotStep) SimulMoveAxis( 'X', 0, RapSimStep) -- breve pausa EgtPause( 100) ShowToolInTcPos( EMT.TCPOS_1, true) -- se segue sega a catena if EMT.NEXTHEAD == 'H3' then -- nascondo l'utensile corrente EgtSetStatus( EgtGetHeadId( EMT.HEAD), GDB_ST.OFF) -- eseguo movimento opportuno SimulMoveAxes( 'B', 0, CollSimRotStep, 'C', -90, CollSimRotStep) end else EMT.TOOL_1 = nil EMT.TCPOS_1 = nil end end end --------------------------------------------------------------------- function OnSimulMachiningStart() -- recupero alcuni dati della lavorazione EMT.MCHNAME = EgtGetOperationName( EMT.MCHID) EMT.MCHTYPE = EgtGetMachiningParam( MCH_MP.TYPE) local sNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) EMT.VMRS = false -- recupero CUTID e TASKID della feature lavorata local vId = EgtGetMachiningGeometry() if vId and #vId > 0 and #vId[1] > 0 then local nPartId = EgtGetParent( EgtGetParent( vId[1][1]) or GDB_ID.NULL) EMT.CUTID = EgtGetInfo( nPartId or GDB_ID.NULL, 'CUTID', 'i') or 0 EMT.TASKID = EgtGetInfo( vId[1][1], 'TASKID', 'i') or 0 ; else EMT.CUTID = 0 EMT.TASKID = 0 end -- eventuale pausa per rimozione sfridi if EMT.SCRAPFIRST then if ( EMT.HEAD == 'H3' and string.sub( EMT.MCHNAME, 1, 5) == 'Csaw_') or EgtExistsInfo( EMT.MCHID, 'MOVE_AFTER') then EMT.SCRAPFIRST = false EgtOutText( 'Pause for Scrap Remove') ParkForScrapRemove() ExecScrapRemove() EgtPause( 500) EgtOutText( '') end end -- se chiodatura in doppio, imposto attivazione testa associata 12 local nDouble = GetValNotes( sNotes, 'Dbl', 'i') if EMT.HEAD == 'H14' and nDouble and nDouble > 0 then EMT.DOUBLE = nDouble EMT.DELTA = GetValNotes( sNotes, 'Dlt', 'd') EgtOutText( 'Machining in Double (D='..EgtNumToString( EMT.DELTA, 1)..')') else EgtOutText( '') end -- non ancora iniziata la lavorazione EMT.MCHFIRST = true end --------------------------------------------------------------------- function OnSimulMachiningEnd() if EMT.UNLOADING or EMT.FALL then EMT.UNLOADING = false EMT.FALL = false end EMT.DOUBLE = nil EMT.DELTA = nil end --------------------------------------------------------------------- --function OnSimulPathStart() --end --------------------------------------------------------------------- function OnSimulPathEnd() -- se attivo VMILL, lavorazione ed è richiesto di eliminare gli sfridi if EMT.VMILL and not EMT.OPEISDISP and EMT.VMRS then EgtOutLog( 'OnSimulPathEnd', 5) local nPart = EgtVolZmapPartCount( EMT.VMILL) if nPart > 1 then -- ricerca del pezzo con massimo volume local nPartMax = 0 local dVolMax = 0 for i = 1, nPart do local dVol = EgtVolZmapPartVolume( EMT.VMILL, i - 1) if dVol > dVolMax then dVolMax = dVol nPartMax = i end end -- eliminazione di tutti i pezzi piccoli for i = nPart, 1, -1 do if i ~= nPartMax then local b3Vmill = EgtVolZmapGetPartBBoxGlob( EMT.VMILL, i - 1, GDB_BB.STANDARD) if b3Vmill:getDimX() < 1200 then EgtRemoveVolZmapPart( EMT.VMILL, i - 1) end end end -- aggiorno visualizzazione EgtDraw() end end end --------------------------------------------------------------------- function OnSimulPathStartAux() --EgtOutLog( 'OnSimulPathStartAux - ' .. EgtNumToString( EMT.AUXIND, 0) .. ' - ' .. EMT.AUX) EgtOutLog( 'OnSimulPathStartAux', 5) -- eseguo il comando --ExecAuxCmd( EMT.AUX) end --------------------------------------------------------------------- function OnSimulPathEndAux() --EgtOutLog( 'OnSimulPathEndAux - ' .. EgtNumToString( EMT.AUXIND, 0) .. ' - ' .. EMT.AUX) EgtOutLog( 'OnSimulPathEndAux', 5) -- eseguo il comando --ExecAuxCmd( EMT.AUX) end --------------------------------------------------------------------- --function OnSimulMoveStart() --end --------------------------------------------------------------------- --function OnSimulMoveEnd() --end --------------------------------------------------------------------- function OnSimulCollision() -- se prima collisione della lavorazione, la segnalo if EMT.MCHNAME ~= EMT.LAST_MCHNAME_COLLIDE then local Class = '' if EMT.SIMCOBIND == 1001 or EMT.SIMCOBIND == 1011 then Class = 'T_'..EMT.HEAD elseif EMT.SIMCOBIND == 1002 or EMT.SIMCOBIND == 1012 then Class = 'TH_'..EMT.HEAD else Class = EMT.COLLOBJ[EMT.SIMCOBIND].Cl end table.insert( EMT.COLLIDE, { Mc = EMT.MCHNAME, Cl = Class, Vm = EMT.SIMVMID}) EMT.LAST_MCHNAME_COLLIDE = EMT.MCHNAME EMT.ERR = 11 local sErr = 'CUTID='..tostring( EMT.CUTID)..'; TASKID='..tostring( EMT.TASKID)..'; Mach='..EMT.MCHNAME..'; Class='..Class..'; VMill='..EMT.SIMVMID EmtSetLastError( 1221, sErr, true) EgtOutLog( 'Collision : ' .. sErr, 1) end end --------------------------------------------------------------------- function ParkForScrapRemove() -- Step di simulazione local RapSimStep = 4 * EMT.SIMSTEP -- Quota di parcheggio local b3Raw = EgtGetRawPartBBox( EgtGetFirstRawPart() or GDB_ID.NULL) local ParkY = min( -( b3Raw:getMin():getX() - 2000), -MinY) --Eseguo SimulMoveAxis( 'Z1', EgtGetAxisHomePos( 'Z1'), RapSimStep) SimulMoveAxis( 'Y', ParkY, RapSimStep) end --------------------------------------------------------------------- function ExecScrapRemove() -- Se non c'è virtual milling attivo, esco if not EMT.VMILL then return end -- Se non ci sono almeno due parti nel virtual milling, esco local nVmPart = EgtVolZmapPartCount( EMT.VMILL) if nVmPart < 2 then return end -- Recupero box e area dei pezzi local vPart = {} local nPartId = EgtGetFirstPartInRawPart( EgtGetFirstRawPart() or GDB_ID.NULL) while nPartId do -- box e area local b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) local dPartArea = b3Part:getDimX() * b3Part:getDimY() -- box espanso local b3PartExp = BBox3d( b3Part) b3PartExp:Add( b3PartExp:getMin() - Vector3d( 10, 10, 0)) b3PartExp:Add( b3PartExp:getMax() + Vector3d( 10, 10, 0)) -- salvo i dati table.insert( vPart, { Box = b3Part, BoxExp = b3PartExp, Area = dPartArea}) -- passo al successivo nPartId = EgtGetNextPartInRawPart( nPartId) end -- Recupero box e area delle parti di Vmill local vVmPart = {} for i = 1, nVmPart do -- recupero il box e calcolo l'area della parte come Vmill local b3VmPart = EgtVolZmapGetPartBBoxGlob( EMT.VMILL, i - 1, GDB_BB.STANDARD) local dVmPartArea = EgtVolZmapPartVolume( EMT.VMILL, i - 1) / b3VmPart:getDimZ() -- box espanso local b3VmPartExp = BBox3d( b3VmPart) b3VmPartExp:Add( b3VmPart:getMin() - Vector3d( 100, 100, 0)) b3VmPartExp:Add( b3VmPart:getMax() + Vector3d( 100, 100, 0)) -- salvo i dati table.insert( vVmPart, { Box = b3VmPart, BoxExp = b3VmPartExp, Area = dVmPartArea}) end -- Tengo solo le parti del Vmill che contengono almeno un box di un pezzo o che interferiscono e sono abbastanza grandi local nValidCnt = 0 for i = #vVmPart, 1, -1 do -- verifiche per parte da eliminare local bToRemove = true -- se area abbastanza grande, allora da verificare if vVmPart[i].Area > 1e4 then -- verifico se sono sicuramente valide (i due box si equivalgono entro la tolleranza) for j = 1, #vPart do if EnclosesXY( vVmPart[i].BoxExp, vPart[j].Box) and EnclosesXY( vPart[j].BoxExp, vVmPart[i].Box) then bToRemove = false vVmPart[i].Part = j nValidCnt = nValidCnt + 1 break end end -- verifico se sono molto probabilmente valide for j = 1, #vPart do if bToRemove and ( OverlapsXY( vVmPart[i].Box, vPart[j].Box) and vVmPart[i].Area > 0.19 * vPart[j].Area) then bToRemove = false break end end end -- se richiesta eliminazione, la eseguo if bToRemove then EgtRemoveVolZmapPart( EMT.VMILL, i - 1) table.remove( vVmPart, i) end end -- Se il numero delle parti sicuramente valide uguaglia il numero dei pezzi, elimino le altre ed ho finito if nValidCnt == #vPart then for i = #vVmPart, 1, -1 do if not vVmPart[i].Part then EgtRemoveVolZmapPart( EMT.VMILL, i - 1) table.remove( vVmPart, i) end end return end -- Calcolo punti interni alle parti di Vmill non già dichiarate valide for i = 1, #vVmPart do if not vVmPart[i].Part then local vtDir = VectorFromRotated( X_AX(), Z_AX(), 45) local ptP = vVmPart[i].Box:getCenter() - vtDir * ( vVmPart[i].Box:getRadius() + 10) local bOk, vIntType, vIntDist = EgtLineVolZmapInters( ptP, vtDir, EMT.VMILL, GDB_RT.GLOB) if bOk then for j = 1, #vIntType do -- se la corrente entra ed esiste la successiva che esce if vIntType[j] == GDB_SLT.IN and j + 1 <= #vIntType and vIntType[j + 1] == GDB_SLT.OUT then local ptC = ptP + vtDir * (( vIntDist[j] + vIntDist[j + 1]) / 2) local nPart = EgtVolZmapGetPartMinDist( EMT.VMILL, ptC, GDB_RT.GLOB) if nPart == i - 1 then vVmPart[i].Cen = ptC break end end end end end end -- Verifico le parti di Vmill non già dichiarate valide for i = #vVmPart, 1, -1 do if not vVmPart[i].Part then local bToRemove = true if vVmPart[i].Cen then for j = 1, #vPart do if EnclosesPointXY( vPart[j].Box, vVmPart[i].Cen) then bToRemove = false break end end for k = 1, #vVmPart do if k ~= i then local vExpBox = BBox3d( vVmPart[k].Box) -- lo espando in XY per sicurezza vExpBox:Add( vExpBox:getMin() - Vector3d( 100, 100, 0)) vExpBox:Add( vExpBox:getMax() + Vector3d( 100, 100, 0)) -- verifico contenimento if EnclosesXY( vExpBox, vVmPart[i].Box) then bToRemove = true break end end end end -- se richiesta eliminazione, la eseguo if bToRemove then EgtRemoveVolZmapPart( EMT.VMILL, i - 1) table.remove( vVmPart, i) end end end end --------------------------------------------------------------------- function ExecUnloading() if EMT.VMILL then -- gruppo dei Vmill local nVmGrpId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'VMill') -- creo un nuovo layer e vi inserisco il nuovo pezzo local nLayId = EgtGroup( nVmGrpId, EgtGetGlobFrame( EMT.VMILL)) EgtRelocate( EMT.VMILL, nLayId) EgtSetLevel( EMT.VMILL, GDB_LV.USER) -- aggiungo gli spigoli local nFirstId, nCount = EgtVolZmapGetEdges( EMT.VMILL, nLayId) if nFirstId then for nId = nFirstId, nFirstId + nCount - 1 do EgtSetColor( nId, Color3d( 96, 96, 96)) end end -- rilascio Vmill EMT.VMILL = nil -- aggiorno la visualizzazione EgtDraw() -- se finito if EMT.PHASE == EgtGetPhaseCount() then -- se impostato di salvare i Vmill, lo faccio local sMachIni = EgtGetCurrMachineDir() .. '\\' .. EgtGetCurrMachineName() .. '.ini' if EgtGetStringFromIni( 'VMill', 'Save', '', sMachIni) == '1' then local sFile = EgtGetCurrFilePath() if sFile then local sDir, sName, sExt = EgtSplitPath( sFile) if sExt and sExt:lower() == ".nge" then sName = sName .. '_VM_' .. EgtGetMachGroupName( EgtGetCurrMachGroup()) EgtSetLevel( nVmGrpId, GDB_LV.USER) EgtSaveObjToFile( nVmGrpId, sDir .. sName .. '.Nge') EgtSetLevel( nVmGrpId, GDB_LV.TEMP) end end end end end end --------------------------------------------------------------------- function ShowToolInTcPos( sTcPos, bShow) -- recupero identificativo della posizione sul TC local TcPosId = EgtGetTcPosId( sTcPos or '') if not TcPosId then return end -- recupero il gruppo dell'utensile local TcExitId = EgtGetFirstNameInGroup( TcPosId or GDB_ID.NULL, 'T1') if not TcExitId then return end -- imposto lo stato di visualizzazione EgtSetStatus( TcExitId, EgtIf( bShow, GDB_ST.ON, GDB_ST.OFF)) -- recupero eventuale gruppo ausiliario da visualizzare/nascondere local TcHSId = EgtGetFirstNameInGroup( TcPosId, sTcPos .. '_HS') if TcHSId then EgtSetStatus( TcHSId, EgtIf( bShow, GDB_ST.ON, GDB_ST.OFF)) end end --------------------------------------------------------------------- function GetToolTcPos( sTool) -- salvo stato iniziale local CurrTool = EgtTdbGetCurrToolParam( MCH_TP.NAME) -- recupero la posizione di cambio utensile dell'utensile indicato local sTcPos if EgtTdbSetCurrTool( sTool) then sTcPos = EgtTdbGetCurrToolParam( MCH_TP.TCPOS) end -- ripristino stato iniziale if CurrTool then EgtTdbSetCurrTool( CurrTool) else EgtTdbSetCurrTool( '') end -- restituisco risultato return sTcPos end --------------------------------------------------------------------- -- *** ESTIMATION T&L *** --------------------------------------------------------------------- local RAPID_X_FEED = 75000 -- mm/min local RAPID_Y_FEED = 100000 -- mm/min local RAPID_Z_FEED = 50000 -- mm/min local RAPID_C_FEED = 15000 -- deg/min local RAPID_B_FEED = 15000 -- deg/min local RAPID_MIN_T = 0.1 -- s local LOAD_T = 2 -- s local CHAR_ONE_MOVE_T = 1 -- s local ROTATION_T = 40 -- s local SPLIT_T = 6 -- s local UNLOAD_T = 4 -- s local FALL_T = 2 -- s --------------------------------------------------------------------- function OnEstimStart() EMT.INCHES = not EgtUiUnitsAreMM() -- unità di misura mm/inches end --------------------------------------------------------------------- function OnEstimEnd() end --------------------------------------------------------------------- function OnEstimProgramStart() -- imposto inizio movimenti da Home EMT.L1 = EgtGetAxisHomePos( 'Y') EMT.L2 = EgtGetAxisHomePos( 'X1') EMT.L3 = EgtGetAxisHomePos( 'Z1') EMT.R1 = EgtGetAxisHomePos( 'C1') EMT.R2 = EgtGetAxisHomePos( 'B1') -- aggiorno valori come precedenti EmtUpdatePrev() -- totalizzatori tempi e lunghezze EMT.TOTCUTLEN = 0 EMT.TOTCUTTIME = 0 EMT.TOTEXTLEN = 0 EMT.TOTEXTTIME = 0 -- variabile per lunghezza taglio utensili EMT.TOOLCUTLEN = {} -- intestazioni EmtTleStart( EMT.INFO) end --------------------------------------------------------------------- function OnEstimProgramEnd() -- stampa dei totali delle lavorazioni EmtTleAddTotal( EmtSecToHMS( EMT.TOTCUTTIME + EMT.TOTEXTTIME), EmtLenToMF( EMT.TOTCUTLEN)) -- stampa dei totali degli utensili for i = 1, #EMT.TOOLCUTLEN do local TCL = EMT.TOOLCUTLEN[i] EmtTleAddTool( TCL.Name, EmtLenToMF( TCL.Len)) end -- completo il file local _, _, sExt = EgtSplitPath( EMT.FILE) EmtTleEnd( sExt:sub( 2)) -- salvo i dati principali nel progetto EgtSetInfo( EgtGetCurrMachGroup(), 'Ttot', EgtNumToString( EMT.TOTCUTTIME + EMT.TOTEXTTIME, 0)) EgtSetInfo( EgtGetCurrMachGroup(), 'Ltot', EgtNumToString( EMT.TOTCUTLEN, 0)) end --------------------------------------------------------------------- function OnEstimDispositionStart() -- inizio disposizione EMT.OPEISDISP = true -- sulla prima fase dichiaro carico barra if EMT.PHASE == 1 then EMT.LOAD = true else EMT.LOAD = false end end --------------------------------------------------------------------- function OnEstimDispositionEnd() -- emetto dati in sospeso if EMT.TLE_NAME then EmtTleAddMachining( EMT.TLE_NAME, EmtSecToHMS( EMT.TLE_TIME), ' - ', ' - ') EMT.TLE_NAME = nil EMT.TLE_TIME = nil end -- termine disposizione EMT.OPEISDISP = false end --------------------------------------------------------------------- function OnEstimToolSelect() -- reset indice utensile in tabella lunghezze EMT.TCLIND = 0 -- verifico che l'utensile sia definito if #EMT.TOOL == 0 then return end -- cerco l'utensile nella tabella for i = 1, #EMT.TOOLCUTLEN do if EMT.TOOLCUTLEN[i].Name == EMT.TOOL then EMT.TCLIND = i break end end -- se non trovato, lo aggiungo if EMT.TCLIND == 0 then table.insert( EMT.TOOLCUTLEN, { Name = EMT.TOOL, Len = 0}) EMT.TCLIND = #EMT.TOOLCUTLEN end end --------------------------------------------------------------------- function OnEstimToolDeselect() end --------------------------------------------------------------------- function OnEstimMachiningStart() EMT.MCHNAME = EgtGetOperationName( EMT.MCHID) EMT.MCHTYPE = EgtGetMachiningParam( MCH_MP.TYPE) EgtOutLog( 'Mach : ' .. EMT.MCHNAME, 5) -- reset contatori di lavorazione EMT.MCHCUTLEN = 0 EMT.MCHCUTTIME = 0 EMT.MCHEXTLEN = 0 EMT.MCHEXTTIME = 0 end --------------------------------------------------------------------- function OnEstimMachiningEnd() -- nel caso di foratura devo dimezzare la lunghezza di taglio perchè comprende anche l'uscita if EMT.MCHTYPE == MCH_MY.DRILLING then EMT.MCHCUTLEN = EMT.MCHCUTLEN / 2 end local sName = EgtGetName( EMT.MCHID) EmtTleAddMachining( sName, EmtSecToHMS( EMT.MCHCUTTIME + EMT.MCHEXTTIME), EmtLenToMF( EMT.MCHCUTLEN), EMT.TOOL) -- aggiorno totali e utensili EMT.TOTCUTLEN = EMT.TOTCUTLEN + EMT.MCHCUTLEN EMT.TOTCUTTIME = EMT.TOTCUTTIME + EMT.MCHCUTTIME EMT.TOTEXTLEN = EMT.TOTEXTLEN + EMT.MCHEXTLEN EMT.TOTEXTTIME = EMT.TOTEXTTIME + EMT.MCHEXTTIME EMT.TOOLCUTLEN[EMT.TCLIND].Len = EMT.TOOLCUTLEN[EMT.TCLIND].Len + EMT.MCHCUTLEN -- emetto dati in sospeso if EMT.TLE_NAME then EmtTleAddMachining( EMT.TLE_NAME, EmtSecToHMS( EMT.TLE_TIME), ' - ', ' - ') EMT.TLE_NAME = nil EMT.TLE_TIME = nil end end --------------------------------------------------------------------- function OnEstimPathStart() EMT.AUXTYPE = nil EMT.MCHMOVEFIRST = true end --------------------------------------------------------------------- function OnEstimPathEnd() EMT.AUXTYPE = nil end --------------------------------------------------------------------- function OnEstimPathStartAux() -- se richiesto, preparo il carico barra if EMT.LOAD then if EMT.AUXIND == EMT.AUXTOT then local dTime = LOAD_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EmtTleAddMachining( 'Loading', EmtSecToHMS( dTime), ' - ', ' - ') EMT.LOAD = false end -- se altrimenti carico dopo rotazione elseif EMT.POSTROT then if EMT.AUXIND == EMT.AUXTOT then local dTime = ROTATION_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EmtTleAddMachining( 'Rotation', EmtSecToHMS( dTime), ' - ', ' - ') EMT.POSTROT = false end -- altrimenti, spostamento carrelli else if EMT.AUXTOT > 2 and EMT.AUXIND == EMT.AUXTOT then local dTime = ( EMT.AUXTOT - 2) * CHAR_ONE_MOVE_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EmtTleAddMachining( 'Charriots move', EmtSecToHMS( dTime), ' - ', ' - ') end end end --------------------------------------------------------------------- function OnEstimPathEndAux() -- verifico tipo di emissione if EMT.OPEISDISP then if not EMT.AUXTYPE then local Cmd = EgtSplitString( EMT.AUX) if Cmd[1] == '0' and Cmd[2] == 'Unloading' then EMT.AUXTYPE = 'U' else EMT.AUXTYPE = 'R' end end else if not EMT.AUXTYPE then local Cmd = EgtSplitString( EMT.AUX) if Cmd[1] == '0' and Cmd[2] == 'Split' then EMT.AUXTYPE = 'S' elseif Cmd[1] == '0' and Cmd[2] == 'Unloading' then EMT.AUXTYPE = 'U' elseif Cmd[1] == '0' and Cmd[2] == 'Fall' then EMT.AUXTYPE = 'F' else EMT.AUXTYPE = 'P' end end end -- per lo scarico della rimanenza if EMT.AUXTYPE == 'R' then if EMT.AUXIND == EMT.AUXTOT then local dTime = LOAD_T + UNLOAD_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EMT.TLE_NAME = 'Remnant unloading' EMT.TLE_TIME = dTime end -- per lo split elseif EMT.AUXTYPE == 'S' then if EMT.AUXIND == EMT.AUXTOT then local dTime = SPLIT_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EMT.TLE_NAME = 'Splitting' EMT.TLE_TIME = dTime end -- per lo scarico elseif EMT.AUXTYPE == 'U' then if EMT.AUXIND == EMT.AUXTOT then local dTime = UNLOAD_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EMT.TLE_NAME = 'Unloading' EMT.TLE_TIME = dTime end -- per lo scarico a caduta elseif EMT.AUXTYPE == 'F' then if EMT.AUXIND == EMT.AUXTOT then local dTime = FALL_T EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime EMT.TLE_NAME = 'Fall' EMT.TLE_TIME = dTime end -- per la pre-rotazione elseif EMT.AUXTYPE == 'P' then ; -- calcolato come parte della rotazione end end --------------------------------------------------------------------- function OnEstimRapid() -- dati movimento local dL1 = EMT.L1 - ( EMT.L1p or 0) local dL2 = EMT.L2 - ( EMT.L2p or 0) local dL3 = EMT.L3 - ( EMT.L3p or 0) local dR1 = 0 if EMT.R1 and EMT.R1p then dR1 = EMT.R1 - EMT.R1p end local dR2 = 0 if EMT.R2 and EMT.R2p then dR2 = EMT.R2 - EMT.R2p end -- se primo posizionamento della lavorazione il movimento di L1 è già conteggiato in quello dei carrelli if EMT.MCHMOVEFIRST then EMT.MCHMOVEFIRST = false dL1 = 0 end -- calcolo lunghezza local dLen = sqrt( dL1 * dL1 + dL2 * dL2 + dL3 * dL3) EMT.MCHEXTLEN = EMT.MCHEXTLEN + dLen -- calcolo tempo local dTime = RAPID_MIN_T local dT1 = abs( dL1) / RAPID_X_FEED * 60 if dT1 > dTime then dTime = dT1 end local dT2 = abs( dL2) / RAPID_Y_FEED * 60 if dT2 > dTime then dTime = dT2 end local dT3 = abs( dL3) / RAPID_Z_FEED * 60 if dT3 > dTime then dTime = dT3 end local dT4 = abs( dR1) / RAPID_C_FEED * 60 if dT4 > dTime then dTime = dT4 end local dT5 = abs( dR2) / RAPID_B_FEED * 60 if dT5 > dTime then dTime = dT5 end EMT.MCHEXTTIME = EMT.MCHEXTTIME + dTime EgtOutLog( string.format( ' G0 Len=%.0f Rot=%.0f° Time=%.2f', dLen, abs( dR1) + abs( dR2), dTime), 5) -- aggiorno valori come precedenti EmtUpdatePrev() end --------------------------------------------------------------------- function OnEstimLinear() -- dati movimento local dL1 = EMT.L1 - EMT.L1p local dL2 = EMT.L2 - EMT.L2p local dL3 = EMT.L3 - EMT.L3p -- calcolo lunghezza local dLen = sqrt( dL1 * dL1 + dL2 * dL2 + dL3 * dL3) EMT.MCHCUTLEN = EMT.MCHCUTLEN + dLen -- calcolo tempo local dTime = dLen / EMT.F * 60 EMT.MCHCUTTIME = EMT.MCHCUTTIME + dTime EgtOutLog( string.format( ' G1 Len=%.0f Time=%.2f', dLen, dTime), 5) -- aggiorno valori come precedenti EmtUpdatePrev() end --------------------------------------------------------------------- function OnEstimArc() -- dati movimento local dLxy = EMT.RR * abs( EMT.AC) * pi / 180 local dLz = abs( ( Point3d( EMT.L1, EMT.L2, EMT.L3) - Point3d( EMT.L1p, EMT.L2p, EMT.L3p)) * Vector3d( EMT.EXTR)) -- calcolo lunghezza local dLen = sqrt( dLxy * dLxy + dLz * dLz) EMT.MCHCUTLEN = EMT.MCHCUTLEN + dLen -- calcolo tempo local dTime = dLen / EMT.F * 60 EMT.MCHCUTTIME = EMT.MCHCUTTIME + dTime EgtOutLog( string.format( ' G2 Len=%.0f Time=%.2f', dLen, dTime), 5) -- aggiorno valori come precedenti EmtUpdatePrev() end --------------------------------------------------------------------- -- *** GENERAL *** --------------------------------------------------------------------- function FindFirstToolOnHead( sH1) -- salvo stato iniziale local CurrMachId = EgtGetCurrMachining() local CurrTool = EgtTdbGetCurrToolParam( MCH_TP.NAME) -- cerco lavorazione con utensile su testa indicata local sTool, nTlen local OpId = EgtGetFirstActiveOperation() while OpId do local nType = EgtGetOperationType( OpId) if nType ~= MCH_OY.NONE and nType ~= MCH_OY.DISP then if EgtSetCurrMachining( OpId) then local sTest = EgtGetMachiningParam( MCH_MP.TOOL) if EgtTdbSetCurrTool( sTest) then local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD) if sHead and ( sHead == sH1) then sTool = sTest nTlen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) break end end end end OpId = EgtGetNextActiveOperation( OpId) end -- ripristino stato iniziale if CurrMachId then EgtSetCurrMachining( CurrMachId) else EgtResetCurrMachining() end if CurrTool then EgtTdbSetCurrTool( CurrTool) else EgtTdbSetCurrTool( '') end -- restituisco risultato return sTool, nTlen end --------------------------------------------------------------------- -- *** END GENERAL *** ---------------------------------------------------------------------