Files
andrea.villa 67ac2fd53b - Aggiunta gestione squadratura
- Nuova funzione RemoveScraps
2025-01-16 15:50:23 +01:00

1000 lines
37 KiB
Plaintext

-- Processore macchina Essetre-WALL by EgalTech s.r.l. 2023/09/01
-- Funzioni generiche indipendenti dal controllo
-- 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
EgtSetStatus( EgtGetFirstNameInGroup( EgtGetTableId( 'Tab') or GDB_ID.NULL, 'GEO2') or GDB_ID.NULL, GDB_ST.OFF)
-- 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( 'B2', '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 = {}
local McdData = { { Grp = 'Tab', Sub = 'COLLISION', Name = 'STM'},
{ Grp = 'Tab2', Sub = 'COLLISION', Name = 'STM'},
{ Grp = 'Base', Sub = 'COLLISION', Name = 'TRAV'},
{ Grp = 'Base', Sub = 'COLLISION', Name = 'COL1'},
{ Grp = 'Base', Sub = 'COLLISION', Name = 'COL2'},
{ Grp = 'Base', Sub = 'COLLISION', Name = 'TC'},
{ Grp = 'Base', Sub = 'COLLISION', Name = 'CSAW'},
{ Grp = 'Base', Sub = 'COLLISION', Name = 'TRUC'}}
EgtOutLog( 'MCODET Objects :', 4)
local nMcdNullCnt = 0
for i = 1, #McdData do
local nGrpId
if McdData[i].Grp == 'Base' then
nGrpId = EgtGetBaseId( 'Base')
else
nGrpId = EgtGetAxisId( McdData[i].Grp) or EgtGetTableId( McdData[i].Grp)
end
local nId = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( nGrpId, McdData[i].Sub), McdData[i].Name)
if nId then
table.insert( EMT.MCODET, nId)
EgtOutLog( 'Element ' .. McdData[i].Grp .. '/' .. McdData[i].Sub .. '/' .. McdData[i].Name .. ' (' .. tostring( nId) .. ') is ok', 4)
else
nMcdNullCnt = nMcdNullCnt + 1
EgtOutLog( 'Element ' .. McdData[i].Grp .. '/' .. McdData[i].Sub .. '/' .. McdData[i].Name .. ' is null', 4)
end
end
if nMcdNullCnt > 0 then
EgtOutLog( 'Warning : MCODET with one or more null Element(s) ')
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
-- Se prima disposizione (dovrebbe essere l'unica)
if EMT.PHASE == 1 then
-- Determino dimensioni del grezzo
local nSolId = EgtGetFirstNameInGroup( EgtGetFirstRawPart() or GDB_ID.NULL, 'RawSolid') or GDB_ID.NULL
local b3Sol = EgtGetBBoxGlob( nSolId, GDB_BB.STANDARD)
EMT.LB = 0
EMT.SB = 0
EMT.HB = 0
if b3Sol then
EMT.LB = b3Sol:getDimX()
EMT.SB = b3Sol:getDimY()
EMT.HB = b3Sol:getDimZ()
end
-- se lunghezza pezzo oltre il limite imposto le due tavole
EMT.TAB2 = nil
if EMT.LB > GantryTabs then
EMT.TAB2 = true
EgtSetAxisPos( 'Y2', EgtGetAxisPos( 'Y') - DimTabX - OffsetTabs)
end
-- Carico primo utensile sulla testa 1
local sTool = FindFirstToolOnHead( 'H1')
if sTool then
EMT.TOOL_1 = sTool
EgtLoadTool( 'H1', 1, EMT.TOOL_1)
EMT.TCPOS_1 = GetToolTcPos( EMT.TOOL_1)
ShowToolInTcPos( EMT.TCPOS_1, false)
else
EgtUnloadTool( 'H1', 1)
end
-- Imposto la corretta posizione Home della Testa 1 (dipende se attivo utensile o sega a catena)
local nH1Mod = EgtGetMode( EgtGetHeadId( 'H1'))
if nH1Mod == GDB_MD.STD then
EgtSetAxisPos( 'X1', MinX1)
EgtSetAxisPos( 'Z1', MaxZ1)
else
EgtSetAxisPos( 'X1', ParkChSawX1)
EgtSetAxisPos( 'Z1', ParkChSawZ1)
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
-- dati del grezzo e suo aggancio alla tavola
EMT.RAWID = EgtGetFirstRawPart()
local b3Raw = EgtGetRawPartBBox( EMT.RAWID or GDB_ID.NULL)
EmtLinkRawPartToGroup( EMT.RAWID or GDB_ID.NULL, 'Tab')
-- Se abilitato e trovato grezzo, creazione Zmap
if EgtGetInfo( EgtGetCurrMachGroup(), 'Vm', 'b') and EMT.RAWID then
-- Se vero inizio, creo Zmap
if not EMT.SIM1ST then
-- elimino eventuale vecchio Zmap
EgtErase( EgtGetFirstNameInGroup( EMT.RAWID, 'VMill') or GDB_ID.NULL)
-- recupero il solido
local nSolId = EgtGetFirstNameInGroup( EMT.RAWID, 'RawSolid')
-- determino la risoluzione dello Zmap
local b3Sol = EgtGetBBoxGlob( nSolId, GDB_BB.STANDARD)
local dArea = b3Sol:getDimX() * b3Sol:getDimY() + b3Sol:getDimX() * b3Sol:getDimZ() + b3Sol:getDimY() * b3Sol:getDimZ()
local dTol = 6.13
if dArea < CoeffVM * 6.0e6 then
dTol = 2.81
elseif dArea < CoeffVM * 12.0e6 then
dTol = 3.77
elseif dArea < CoeffVM * 24.0e6 then
dTol = 5.03
end
-- creo lo Zmap
EMT.VMILL = EgtVolZmapBox( EMT.RAWID, b3Raw:getMin(), b3Raw:getDimX(), b3Raw:getDimY(), b3Raw:getDimZ(), dTol, true, GDB_RT.GLOB)
if EMT.VMILL then
EgtSetName( EMT.VMILL, 'VMill')
EgtSetLevel( EMT.VMILL, GDB_LV.TEMP)
EgtSetColor( EMT.VMILL, EgtGetColor( nSolId), false)
-- nascondo le altre geometrie
local nId = EgtGetFirstInGroup( EMT.RAWID)
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
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)
-- se lama su sua testa, verifico che l'altra sia dalla parte opposta
if EMT.HEAD == 'H2' then
EgtSetAxisPos( 'X1', MinX1)
-- altrimenti carico utensile
else
-- 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 dPosA = EgtGetVal( sVal, 'A1', 'd') or 0
EmtModifyAxisHome( 'A1', dPosA)
EgtResetAxisPos( 'A1')
EmtModifyAxisHome( 'C1', -dPosA)
EgtResetAxisPos( 'C1')
EgtSetAxisPos( 'X1', ParkChSawX1)
EgtSetAxisPos( 'Z1', ParkChSawZ1)
end
-- breve pausa
EgtPause( 100)
EgtOutText( '')
EMT.TOOL_1 = EMT.TOOL
EMT.TCPOS_1 = EMT.TCPOS
-- lo nascondo sul portautensili
ShowToolInTcPos( EMT.TCPOS, false)
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
AddToolToCollisionObj( EMT.TOOL, EMT.HEAD, EMT.EXIT, 1001)
AddToolHolderToCollisionObj( EMT.TOOL, EMT.HEAD, EMT.EXIT, 1002)
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()
-- porto la testa in home
if EMT.HEAD == 'H2' then
SimulMoveAxes( 'X2', MaxX2, MCH_SIM_STEP.RAPID, 'C2', EgtGetAxisHomePos( 'C2'), MCH_SIM_STEP.COLLROT, 'B2', EgtGetAxisHomePos( 'B2'), MCH_SIM_STEP.COLLROT)
elseif EMT.NEXTHEAD == 'H2' then
SimulMoveAxes( 'X1', MinX1, MCH_SIM_STEP.RAPID, 'C1', EgtGetAxisHomePos( 'C1'), MCH_SIM_STEP.COLLROT, 'B1', EgtGetAxisHomePos( 'B1'), MCH_SIM_STEP.COLLROT)
end
-- deposito utensile se non lama su sua testa
if EMT.NEXTHEAD ~= 'H2' then
if EMT.NEXTTOOL ~= EMT.TOOL_1 then
EgtOutText( 'Tool change in progress...')
-- simulo movimento
SimulMoveAxes( 'B1', 0, MCH_SIM_STEP.COLLROT, 'C1', 0, MCH_SIM_STEP.COLLROT)
SimulMoveAxis( 'X1', MinX1, MCH_SIM_STEP.RAPID)
-- 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( 'H1'), GDB_ST.OFF)
-- eseguo movimenti opportuni
SimulMoveAxis( 'X1', ParkChSawX1, MCH_SIM_STEP.RAPID)
SimulMoveAxis( 'Z1', ParkChSawZ1, MCH_SIM_STEP.RAPID)
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.MCHUSERNOTES = 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
local bSystemSR = ( EMT.SCRAPFIRST and (( EMT.HEAD == 'H3' and string.sub( EMT.MCHNAME, 1, 5) == 'Csaw_') or EgtExistsInfo( EMT.MCHID, 'MOVE_AFTER')))
local bUserSR = ( EgtGetValInNotes( EMT.MCHUSERNOTES, 'ScrapRemove', 'i') == 1)
if bSystemSR or bUserSR then
if bSystemSR then EMT.SCRAPFIRST = false end
EgtOutText( 'Pause for Scrap Remove')
ParkForScrapRemove()
ExecScrapRemove()
EgtPause( 500)
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
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()
-- se lunghezza pezzo oltre il limite, aggancio le tavole
if EMT.TAB2 then
EgtSetAxisPos( 'Y2', EgtGetAxisPos( 'Y') - DimTabX - OffsetTabs)
EMT.AuxAxes = 1
EMT.A1n = 'Y2'
EMT.A1m = 'Y'
end
-- se rapido a fine lavorazione con testa bassa, prima risalgo opportunamente in Z
if EMT.HEAD == 'H1' and EMT.MOVE == 0 and EMT.FLAG == 3 and EMT.L3p < SafeZ1 then
SimulMoveAxis( 'Z1', SafeZ1, MCH_SIM_STEP.RAPID)
end
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 then
Class = 'T_H1'
elseif EMT.SIMCOBIND == 1002 then
Class = 'TH_H1'
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 = 1
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()
local b3Raw = EgtGetRawPartBBox( EMT.RAWID)
local ParkY = min( ( MaxY + b3Raw:getMin():getX() + b3Raw:getDimX() + 3000), MaxY)
SimulMoveAxis( 'Z1', EgtGetAxisHomePos( 'Z1'), MCH_SIM_STEP.RAPID)
if EMT.TAB2 then
SimulMoveAxes( 'Y', ParkY, MCH_SIM_STEP.RAPID, 'Y2', ParkY - DimTabX - OffsetTabs, MCH_SIM_STEP.RAPID)
else
SimulMoveAxis( 'Y', ParkY, MCH_SIM_STEP.RAPID)
end
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( EMT.RAWID)
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()
local nOlEntId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( nPartId, 'Outline') or GDB_ID.NULL)
while nOlEntId do
if EgtGetType( nOlEntId) == GDB_TY.SRF_FRGN and EgtSurfFrNormVersor( nOlEntId, GDB_ID.ROOT):getZ() > 0.8 then
dPartArea = EgtSurfArea( nOlEntId)
break
end
nOlEntId = EgtGetNext( nOlEntId)
end
-- 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, Outline = nOlEntId})
-- 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
-- se presente squadratura, tengo tutti i pezzi all'interno
local nRawId = EgtGetFirstRawPart()
local SquaringEntities = {}
SquaringEntities = EgtGetNameInGroup( nRawId, 'SquaringGeometry')
local b3SquaringBox = nil
if SquaringEntities then
for i = 1, #SquaringEntities do
if i == 1 then
b3SquaringBox = EgtGetBBoxGlob( SquaringEntities[i], GDB_BB.STANDARD)
else
if b3SquaringBox then
b3SquaringBox:Add( EgtGetBBoxGlob( SquaringEntities[i], GDB_BB.STANDARD))
end
end
end
if b3SquaringBox then
b3SquaringBox:expand( 50)
end
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
-- se presente squadratura, verifico che il VMILL sia all'interno del BOX squadratura
if not b3SquaringBox or EnclosesXY( b3SquaringBox, vVmPart[i].Box) then
-- verifico se sono sicuramente valide (i due box si equivalgono entro la tolleranza)
for j = 1, #vPart do
if ( vPart[j].Outline and vVmPart[i].Area > 0.95 * vPart[j].Area and vVmPart[i].Area < 1.05 * vPart[j].Area) or
( 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.25 * vPart[j].Area) then
bToRemove = false
break
end
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
if not vVmPart[i].Cen then
vVmPart[i].Cen = ptC
elseif not vVmPart[i].Cen2 then
vVmPart[i].Cen2 = ptC
else
vVmPart[i].Cen3 = ptC
break
end
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
elseif vVmPart[i].Cen2 and EnclosesPointXY( vPart[j].Box, vVmPart[i].Cen2) then
bToRemove = false
break
elseif vVmPart[i].Cen3 and EnclosesPointXY( vPart[j].Box, vVmPart[i].Cen3) then
bToRemove = false
break
end
-- controllo per gestire squadratura inserita manualmente da operatore
-- verifico se il box del part è completamente incluso nel box del VM, allora non posso cancellarlo
if Encloses( vVmPart[i].BoxExp, vPart[j].Box) 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 il gruppo dell'utensile
local TcExitId = EgtGetFirstNameInGroup( EgtGetTcPosId( sTcPos or '') 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))
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 = 20000 -- mm/min
local RAPID_Z_FEED = 50000 -- mm/min
local RAPID_C_FEED = 5000 -- deg/min
local RAPID_B_FEED = 10000 -- deg/min
local RAPID_MIN_T = 0.1 -- s
local SCRAP_REMOVE_T = 30 -- s
---------------------------------------------------------------------
function OnEstimStart()
EMT.INCHES = not EgtUiUnitsAreMM() -- unità di misura mm/inches
-- Non effettuata pausa per rimozione sfridi
EMT.SCRAPFIRST = true
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)
-- 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
local dTime = SCRAP_REMOVE_T
EMT.TOTEXTTIME = EMT.TOTEXTTIME + dTime
EmtTleAddMachining( 'Scrap remove', EmtSecToHMS( dTime), ' - ', ' - ')
end
end
-- 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()
end
---------------------------------------------------------------------
function OnEstimPathEndAux()
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 ***
---------------------------------------------------------------------