-- EmtGenerator.lua by EgalTech s.r.l. 2021/12/28 -- 2018/02/22 DS Funzioni bit32 sostituite con operatori sui bit. -- 2018/08/16 DS Corretta ricorsione di SimulMoveAxis. -- 2018/10/09 DS Controllo nDec anche in EmtLenToString. -- 2019/03/19 DS Modificate SimulMoveAxis e SimulMoveAxes. -- 2019/05/19 DS Aggiunta funzione SetToolForVmill. -- 2019/08/06 DS Aggiunte funzioni AddToCollisionCheck, AddToolToCollisionCheck e DumpCollisionCheck. -- 2020/02/04 DS Modifiche a SetToolForVmill per gestire frese con gambo piccolo. -- 2020/02/05 DS Aggiunto parametro sCollGrp a AddToCollisionCheck e riportato nei dati successivi come Grp. -- 2020/03/23 DS Aggiunta funzione per impostare il numero di decimali nell'emissione coordinate assi. -- 2020/10/06 DS In AddToolToCollisionCheck ora si usano diametro e lunghezza totali, prima quelli di lavoro. -- 2020/10/31 DS Corretta AddToCollisionCheck per riferimenti da calcolarsi in globale. -- 2020/12/07 DS In SetToolForVmill aggiunta gestione WaterJet. -- 2020/12/22 DS In AddToCollisionCheck per cilindri ora raggio precede altezza. -- 2021/01/03 DS Aggiunta funzione AddToolToCollisionObj. In MoveAxis e MoveAxes aggiunta gestione delle collisioni. -- 2021/01/19 DS In AddToolToCollisionCheck aggiunta gestione per mortasatrici/seghe a catena. -- 2021/02/10 DS In SimulMoveAx* migliorata gestione segnalazione collisioni. -- 2021/04/14 DS A AddToolToCollisionObj e AddToolToCollisionCheck aggiunto parametro opzionale bUseDiam. -- 2021/05/24 DS Corretta AddToolToCollisionCheck perchè recuperava sempre l'utensile dell'uscita 1 della testa e uscita indicate. -- Parametro bUseDiam eliminato perchè superato dalle modifiche. -- 2021/06/25 DS In AddToolToCollisionCheck corretta gestione lame ora con lunghezza e spessore. -- 2021/07/12 DS Migliorie a movimento asse/i per simulazione. -- 2021/12/28 DS Anche a Centro e Punto Medio di Arco si sottrae EMT.ADDORI se definito. -- Tavola per definizione modulo (serve ma non usata) local EmtGenerator = {} EgtOutLog( 'EmtGenerator started', 1) -- Include require( 'EgtBase') --------------------------------------------------------------------- -- *** Output *** --------------------------------------------------------------------- function EmtOutput( sOut, nId) if EMT.NUM then if not nId or nId == 1 then EMT.LINENBR = EMT.LINENBR + EMT.LINEINC if EMT.LINEMAX and EMT.LINENBR > EMT.LINEMAX then EMT.LINENBR = EMT.LINEINC end EmtWrite( EMT.Nt .. EMT.LINENBR .. ' ' .. ( sOut or '')) else if not EMT.LINENBRS then EMT.LINENBRS = {} end if not EMT.LINENBRS[nId] then EMT.LINENBRS[nId] = 0 end EMT.LINENBRS[nId] = EMT.LINENBRS[nId] + EMT.LINEINC if EMT.LINEMAX and EMT.LINENBRS[nId] > EMT.LINEMAX then EMT.LINENBRS[nId] = EMT.LINEINC end OutFile( nId, EMT.Nt .. EMT.LINENBRS[nId] .. ' ' .. ( sOut or '')) end else if not nId or nId == 1 then EmtWrite( sOut or '') else OutFile( nId, sOut or '') end end end ----------------------------------------------------------------- -- *** Other Files *** ----------------------------------------------------------------- local s_OutFh = {} ----------------------------------------------------------------- function OpenOutFile( nId, sFile) s_OutFh[nId] = io.open( sFile, 'w') return s_OutFh[nId] end ----------------------------------------------------------------- function OutFile( nId, sOut) if s_OutFh[nId] then s_OutFh[nId]:write( sOut .. '\n') end end ----------------------------------------------------------------- function CloseOutFile( nId) if s_OutFh[nId] then s_OutFh[nId]:close() s_OutFh[nId] = nil end end ----------------------------------------------------------------- -- *** Utilities *** --------------------------------------------------------------------- function EmtUpdatePrev() EMT.L1p = EMT.L1 EMT.L2p = EMT.L2 EMT.L3p = EMT.L3 EMT.R1p = EMT.R1 EMT.R2p = EMT.R2 EMT.R3p = EMT.R3 EMT.R4p = EMT.R4 EMT.L1op = EMT.L1o EMT.L2op = EMT.L2o EMT.L3op = EMT.L3o if EMT.MOVE ~= 0 then if EMT.F then EMT.Fp = EMT.F end else EMT.Fp = nil end end function EmtResetPrevLinear() EMT.L1p = nil EMT.L2p = nil EMT.L3p = nil EMT.L1op = nil EMT.L2op = nil EMT.L3op = nil end function EmtResetPrev() EMT.L1p = nil EMT.L2p = nil EMT.L3p = nil EMT.R1p = nil EMT.R2p = nil EMT.R3p = nil EMT.R4p = nil EMT.L1op = nil EMT.L2op = nil EMT.L3op = nil EMT.Fp = nil end function EmtSetAdditionalOrig( dAddX, dAddY, dAddZ) EMT.ADDORI = Point3d( dAddX, dAddY, dAddZ) end function EmtAdjustLinearAxes() -- salvo i valori rispetto a Zero macchina EMT.L1o = EMT.L1 EMT.L2o = EMT.L2 EMT.L3o = EMT.L3 -- se emetto rispetto all'origine 1 della tavola if EMT.USETO1 then -- sottraggo agli assi lineari l'origine 1 della tavola if EMT.L1 then EMT.L1 = EMT.L1 - EMT.TABORI1[1] if EMT.ADDORI then EMT.L1 = EMT.L1 - EMT.ADDORI[1] end end if EMT.L2 then EMT.L2 = EMT.L2 - EMT.TABORI1[2] if EMT.ADDORI then EMT.L2 = EMT.L2 - EMT.ADDORI[2] end end if EMT.L3 then EMT.L3 = EMT.L3 - EMT.TABORI1[3] if EMT.ADDORI then EMT.L3 = EMT.L3 - EMT.ADDORI[3] end end end -- se emetto rispetto a piano locale if EMT.IPLGL then local ptP = Point3d( EMT.L1, EMT.L2, EMT.L3) ptP:toLoc( EMT.IPLGLFR) EMT.L1 = ptP:getX() EMT.L2 = ptP:getY() EMT.L3 = ptP:getZ() end end function EmtAdjustRotaryAxes() -- salvo i valori rispetto a Zero macchina EMT.R1o = EMT.R1 EMT.R2o = EMT.R2 EMT.R3o = EMT.R3 EMT.R4o = EMT.R4 end function EmtAdjustCenterAxes() -- salvo i valori rispetto a Zero macchina EMT.C1o = EMT.C1 EMT.C2o = EMT.C2 EMT.C3o = EMT.C3 -- se emetto rispetto all'origine 1 della tavola if EMT.USETO1 then -- sottraggo agli assi lineari l'origine 1 della tavola if EMT.C1 then EMT.C1 = EMT.C1 - EMT.TABORI1[1] if EMT.ADDORI then EMT.C1 = EMT.C1 - EMT.ADDORI[1] end end if EMT.C2 then EMT.C2 = EMT.C2 - EMT.TABORI1[2] if EMT.ADDORI then EMT.C2 = EMT.C2 - EMT.ADDORI[2] end end if EMT.C3 then EMT.C3 = EMT.C3 - EMT.TABORI1[3] if EMT.ADDORI then EMT.C3 = EMT.C3 - EMT.ADDORI[3] end end end -- se emetto rispetto a piano locale if EMT.IPLGL then local ptP = Point3d( EMT.C1, EMT.C2, EMT.C3) ptP:toLoc( EMT.IPLGLFR) EMT.C1 = ptP:getX() EMT.C2 = ptP:getY() EMT.C3 = ptP:getZ() end end function EmtAdjustMidPointAxes() -- salvo i valori rispetto a Zero macchina EMT.M1o = EMT.M1 EMT.M2o = EMT.M2 EMT.M3o = EMT.M3 -- se emetto rispetto all'origine 1 della tavola if EMT.USETO1 then -- sottraggo agli assi lineari l'origine 1 della tavola if EMT.M1 then EMT.M1 = EMT.M1 - EMT.TABORI1[1] if EMT.ADDORI then EMT.M1 = EMT.M1 - EMT.ADDORI[1] end end if EMT.M2 then EMT.M2 = EMT.M2 - EMT.TABORI1[2] if EMT.ADDORI then EMT.M2 = EMT.M2 - EMT.ADDORI[2] end end if EMT.M3 then EMT.M3 = EMT.M3 - EMT.TABORI1[3] if EMT.ADDORI then EMT.M3 = EMT.M3 - EMT.ADDORI[3] end end end -- se emetto rispetto a piano locale if EMT.IPLGL then local ptP = Point3d( EMT.M1, EMT.M2, EMT.M3) ptP:toLoc( EMT.IPLGLFR) EMT.M1 = ptP:getX() EMT.M2 = ptP:getY() EMT.M3 = ptP:getZ() end end local function EmtToEmit( V, Vp) if not V then return false end if not EMT.MODAL or not Vp then return true end return ( abs( V - Vp) > 0.001) end function EmtGetAxis( Ax, bRotLikeLin) local Axp = Ax .. 'p' local Axt = Ax .. 't' if EMT[Axt] and EmtToEmit( EMT[Ax], EMT[Axp]) then local nDec = EMT.DECNUM or 3 if not EMT.INCHES or (( Ax == 'R1' or Ax == 'R2' or Ax == 'R3' or Ax == 'R4') and not bRotLikeLin) then return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Ax], nDec), true else return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Ax] / GEO.ONE_INCH, nDec + 1), true end end return '', false end function EmtGetRapidAxis( Ax, bRotLikeLin) local MaskVal = {L1=1,L2=2,L3=4,R1=8,R2=16,R3=32,R4=64} -- per lua 5.2 {L1=0,L2=1,L3=2,R1=3,R2=4,R3=5,R4=6} if ( EMT.MASK & MaskVal[Ax]) ~= 0 then -- per lua 5.2 bit32.extract(EMT.MASK,MaskVal[Ax]) ~= 0 return EmtGetAxis( Ax, bRotLikeLin) end -- mascherato, sistemo attuale come precedente local Axp = Ax .. 'p' local Axt = Ax .. 't' EMT[Ax] = EMT[Axp] return '', false end function EmtGetHomeAxis( Ax, bRotLikeLin) local MaskVal = {L1=1,L2=2,L3=4,R1=8,R2=16,R3=32,R4=64} -- per lua 5.2 {L1=0,L2=1,L3=2,R1=3,R2=4,R3=5,R4=6} if ( EMT.MASK & MaskVal[Ax]) ~= 0 then -- per lua 5.2 bit32.extract(EMT.MASK,MaskVal[Ax]) ~= 0 local Axo = Ax .. 'o' local Axt = Ax .. 't' if EMT[Axt] then local nDec = EMT.DECNUM or 3 if not EMT.INCHES or (( Ax == 'R1' or Ax == 'R2' or Ax == 'R3' or Ax == 'R4') and not bRotLikeLin) then return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Axo], nDec), true else return ' ' .. EMT[Axt] .. EgtNumToString( EMT[Axo] / GEO.ONE_INCH, nDec + 1), true end end end return '', false end function EmtGetHomeAxisByName( Ax, dOffset, bRotLikeLin) local sToken = EgtGetAxisToken( Ax) local bLinear = EgtGetAxisType( Ax) local dVal = EgtGetAxisHomePos( Ax) if dOffset then dVal = dVal + dOffset end if sToken and bLinear ~= nil and dVal then local nDec = EMT.DECNUM or 3 if not EMT.INCHES or ( not bLinear and not bRotLikeLin) then return ' ' .. sToken .. EgtNumToString( dVal, nDec), true else return ' ' .. sToken .. EgtNumToString( dVal / GEO.ONE_INCH, nDec + 1), true end else return '', false end end function EmtGetFeed() if EmtToEmit( EMT.F, EMT.Fp) then if not EMT.INCHES then return ' ' .. EMT.Ft .. EgtNumToString( EMT.F, 0) else return ' ' .. EMT.Ft .. EgtNumToString( EMT.F / GEO.ONE_INCH, 1) end end return '' end function EmtGetArcType( nMove, bInv) if nMove == 2 then if bInv then return 3 else return 2 end elseif nMove == 3 then if bInv then return 2 else return 3 end else return nil end end ------------------------------------------------------------------------------- function EmtGetAngO2( vtZ, vtX, dAngV, dAngO) -- vettore X di riferimento local vtRif = Vector3d( X_AX()) -- lo ruoto prima attorno a Y poi attorno a Z vtRif:rotate( Y_AX(), dAngV) vtRif:rotate( Z_AX(), dAngO) -- prodotto scalare tra vettore riferimento ruotato e vettore vtX local dCos = vtRif * vtX -- prodotto scalare tra vettore prodotto vettoriale dei due e vettore vtZ local dSin = ( vtRif ^ vtX) * vtZ -- restituisco l'angolo di rotazione richiesto return atan2( dSin, dCos) end ------------------------------------------------------------------------------- function EmtGetAngO3( vtZ, vtX, dAngV, dAngO) -- vettore X di riferimento local vtRif = Vector3d( X_AX()) -- vettore asse di rotazione local vtAx = Vector3d( - sin( dAngO), cos( dAngO), 0) -- ruoto X di rif attorno a questo asse vtRif:rotate( vtAx, dAngV) -- prodotto scalare tra vettore riferimento ruotato e vettore vtX local dCos = vtRif * vtX -- prodotto scalare tra vettore prodotto vettoriale dei due e vettore vtZ local dSin = ( vtRif ^ vtX) * vtZ -- restituisco l'angolo di rotazione richiesto return atan2( dSin, dCos) end ------------------------------------------------------------------------------- function EmtLenToString( Val, nDec) nDec = ( nDec or 3) if not EMT.INCHES then return EgtNumToString( Val, nDec) else return EgtNumToString( Val/GEO.ONE_INCH, nDec + 1) end end ------------------------------------------------------------------------------- function EmtNum3ToString( Tav, nDec) nDec = ( nDec or 3) return EgtNumToString( Tav[1], nDec) .. ",".. EgtNumToString( Tav[2], nDec) .. ",".. EgtNumToString( Tav[3], nDec) end ------------------------------------------------------------------------------- function EmtLen3ToString( Tav, nDec) nDec = ( nDec or 3) return EmtLenToString( Tav[1], nDec) .. ",".. EmtLenToString( Tav[2], nDec) .. ",".. EmtLenToString( Tav[3], nDec) end --------------------------------------------------------------------- function EmtSecToHMS( dSec) local nH = floor( dSec / 3600) local nM = floor(( dSec - nH * 3600) / 60) local nS = floor( dSec - nH * 3600 - nM * 60) local sH = EgtIf( nH < 10, '0', '') .. tostring( nH) local sM = EgtIf( nM < 10, '0', '') .. tostring( nM) local sS = EgtIf( nS < 10, '0', '') .. tostring( nS) return sH .. ':' .. sM .. ':' .. sS end --------------------------------------------------------------------- function EmtLenToMF( dLen) local dOut if EMT.INCHES then dOut = dLen / 304.8 else dOut = dLen / 1000 end return EgtIf( dOut < 10, ' ', '') .. EgtNumToString( dOut, -1) end --------------------------------------------------------------------- -- *** Estimation functions *** --------------------------------------------------------------------- local s_TleTitle local s_TleMach = {} local s_TleTool = {} --------------------------------------------------------------------- function EmtTleStart( sTitle) -- inizializzazioni s_TleTitle = sTitle s_TleMach = {} s_TleTool = {} end --------------------------------------------------------------------- function EmtTleAddMachining( sName, sTime, sLen, sTool) table.insert( s_TleMach, { Name = sName, Time = sTime, Len = sLen, Tool = sTool}) end --------------------------------------------------------------------- function EmtTleAddTotal( sTotTime, sTotLen) s_TleMach.Total = { Time = sTotTime, Len = sTotLen} end --------------------------------------------------------------------- function EmtTleAddTool( sName, sLen) table.insert( s_TleTool, { Name = sName, Len = sLen}) end --------------------------------------------------------------------- function EmtTleEnd( sFormat) -- se richiesto formato HTML if sFormat:lower() == 'html' then -- intestazione EmtOutput( '') EmtOutput( '') EmtOutput( '') EmtOutput( ' ') EmtOutput( ' ' .. ( s_TleTitle or '') .. '') EmtOutput( ' ') EmtOutput( '') EmtOutput( '') -- tabella lavorazioni if s_TleMach and #s_TleMach > 0 then EmtOutput( ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' ') for i = 1, #s_TleMach do EmtOutput( ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' ') end EmtOutput( ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' ') EmtOutput( '
Machinings
Time [h:m:s]Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]') .. 'Tool
' .. ( s_TleMach[i].Name or '') .. '' .. ( s_TleMach[i].Time or '') .. '' .. ( s_TleMach[i].Len or '') .. '' .. ( s_TleMach[i].Tool or '') .. '
TOTAL' .. ( s_TleMach.Total.Time or '') .. '' .. ( s_TleMach.Total.Len or '') .. '' .. '
') end -- tabella utensili if s_TleTool and #s_TleTool > 0 then EmtOutput( ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' \r\n' .. ' ') for i = 1, #s_TleTool do EmtOutput( ' \r\n' .. ' \r\n' .. ' \r\n' .. ' ') end EmtOutput( '
Tools
Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]') .. '
' .. ( s_TleTool[i].Name or '') .. '' .. ( s_TleTool[i].Len or '') .. '
') end -- conclusione EmtOutput( '') EmtOutput( '') -- altrimenti formato testo else -- intestazione EmtOutput( ' ' .. ( s_TleTitle or '') .. '\r\n \r\n') -- tabella lavorazioni if s_TleMach and #s_TleMach > 0 then EmtOutput( ' Machinings') EmtOutput( ' ==========') EmtOutput( ' Time [h:m:s] Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]') .. ' Tool') for i = 1, #s_TleMach do local sName = ( s_TleMach[i].Name or '') sName = sName .. string.rep( ' ', 18 - #sName) EmtOutput( sName .. ( s_TleMach[i].Time or '') .. ' ' .. ( s_TleMach[i].Len or '') .. ' ' .. ( s_TleMach[i].Tool or '')) end end EmtOutput( '-------------------------------------------------------') EmtOutput( 'TOTAL ' .. ( s_TleMach.Total.Time or '') .. ' ' .. ( s_TleMach.Total.Len or '')) -- tabella utensili if s_TleTool and #s_TleTool > 0 then EmtOutput( '\r\n\r\n Tools') EmtOutput( ' =====') EmtOutput( ' Len ' .. EgtIf( EMT.INCHES, '[ft]', '[m]')) for i = 1, #s_TleTool do local sName = ( s_TleTool[i].Name or '') sName = sName .. string.rep( ' ', 19 - #sName) EmtOutput( sName .. ( s_TleTool[i].Len or '')) end end end end --------------------------------------------------------------------- -- *** Simulation functions *** --------------------------------------------------------------------- local function MyPrepareAxis( sName, dPos, dStep, nS) if not sName then return nil, nS end local dPrev = EgtGetAxisPos( sName) if not dPrev then return nil, nS end if abs( dStep) > GEO.EPS_SMALL then local nSa = abs( ceil( ( dPos - dPrev) / dStep)) nS = max( nS, nSa) end return dPrev, nS end --------------------------------------------------------------------- local function MySetAxisPos( sName, dPos) local bOk, dNewPos = EgtSetAxisPos( sName, dPos) return ( bOk and abs( dNewPos - dPos) < 10 * GEO.EPS_SMALL) end --------------------------------------------------------------------- function SimulMoveAxis( sName, dPos, dStep) -- salvo step attuale EMT.SIMSTEP = EMT.SIMSTEP or 20 local dSimStep = EMT.SIMSTEP -- preparazione asse local dPrev, nS = MyPrepareAxis( sName, dPos, dStep, 1) -- l'asse deve essere ben definito if not dPrev then return false end -- movimento if nS > 0 then for i = 1, nS do local dCoeff = i / nS local bOk = MySetAxisPos( sName, ( 1 - dCoeff) * dPrev + dCoeff * dPos) EgtDraw() local bCheckOk, nCdInd, nObjInd = EmtExecCollisionCheck() if not bCheckOk then local nPrevErr = EMT.ERR local bCollOk, nErr = EmtOnCollision( nCdInd, nObjInd) if not bCollOk and nErr == 11 then if EgtGetEnableUI() then EgtOutBox( 'Collisione!', 'AVVERTIMENTO', 'WARNING') EMT.SIMUISTAT = MCH_UISIM.PAUSE while EMT.SIMUISTAT == MCH_UISIM.PAUSE do -- Param1 = -11 notifica al simulatore pausa per collisione EgtProcessEvents( -11, 4) end end else EMT.ERR = nPrevErr end end if not bOk then return false end if EgtGetEnableUI() then EgtProcessEvents( 0, 4) while EMT.SIMUISTAT == MCH_UISIM.PAUSE do EgtProcessEvents( 0, 4) end if EMT.SIMUISTAT == MCH_UISIM.STOP then error( 'STOP') end -- se cambia lo step di simulazione richiesto in modo significativo ... if abs( EMT.SIMSTEP - dSimStep) > 5 then local dC = EMT.SIMSTEP / dSimStep return SimulMoveAxis( sName, dPos, dC * dStep) end end end end -- assegno valore finale esatto return MySetAxisPos( sName, dPos) end --------------------------------------------------------------------- function SimulMoveAxes( sName, dPos, dStep, sName2, dPos2, dStep2, sName3, dPos3, dStep3, sName4, dPos4, dStep4, sName5, dPos5, dStep5) -- salvo step attuale EMT.SIMSTEP = EMT.SIMSTEP or 20 local dSimStep = EMT.SIMSTEP -- preparazione dei diversi assi local dPrev, dPrev2, dPrev3, dPrev4, dPrev5 local nS = 1 dPrev, nS = MyPrepareAxis( sName, dPos, dStep, nS) dPrev2, nS = MyPrepareAxis( sName2, dPos2, dStep2, nS) dPrev3, nS = MyPrepareAxis( sName3, dPos3, dStep3, nS) dPrev4, nS = MyPrepareAxis( sName4, dPos4, dStep4, nS) dPrev5, nS = MyPrepareAxis( sName5, dPos5, dStep5, nS) -- il primo asse deve essere ben definito if not dPrev then return false end -- movimento if nS > 0 then for i = 1, nS do local dCoeff = i / nS local bOk = MySetAxisPos( sName, ( 1 - dCoeff) * dPrev + dCoeff * dPos) local bOk2 = not dPrev2 or MySetAxisPos( sName2, ( 1 - dCoeff) * dPrev2 + dCoeff * dPos2) local bOk3 = not dPrev3 or MySetAxisPos( sName3, ( 1 - dCoeff) * dPrev3 + dCoeff * dPos3) local bOk4 = not dPrev4 or MySetAxisPos( sName4, ( 1 - dCoeff) * dPrev4 + dCoeff * dPos4) local bOk5 = not dPrev5 or MySetAxisPos( sName5, ( 1 - dCoeff) * dPrev5 + dCoeff * dPos5) EgtDraw() local bCheckOk, nCdInd, nObjInd = EmtExecCollisionCheck() if not bCheckOk then local nPrevErr = EMT.ERR local bCollOk, nErr = EmtOnCollision( nCdInd, nObjInd) if not bCollOk and nErr == 11 then EMT.ERR = 11 if EgtGetEnableUI() then EgtOutBox( 'Collisione!', 'AVVERTIMENTO', 'WARNING') EMT.SIMUISTAT = MCH_UISIM.PAUSE while EMT.SIMUISTAT == MCH_UISIM.PAUSE do -- Param1 = -11 notifica al simulatore pausa per collisione EgtProcessEvents( -11, 4) end end else EMT.ERR = nPrevErr end end if not ( bOk and bOk2 and bOk3 and bOk4 and bOk5) then return false, bOk, bOk2, bOk3, bOk4, bOk5 end if EgtGetEnableUI() then EgtProcessEvents( 0, 4) while EMT.SIMUISTAT == MCH_UISIM.PAUSE do EgtProcessEvents( 0, 4) end if EMT.SIMUISTAT == MCH_UISIM.STOP then error( 'STOP') end -- se cambia lo step di simulazione richiesto in modo significativo ... if abs( EMT.SIMSTEP - dSimStep) > 5 then local dC = EMT.SIMSTEP / dSimStep return SimulMoveAxes( sName, dPos, dC * dStep, sName2, dPos2, dC * ( dStep2 or 0), sName3, dPos3, dC * ( dStep3 or 0), sName4, dPos4, dC * ( dStep4 or 0), sName5, dPos5, dC * ( dStep5 or 0)) end end end end -- assegno valore finale esatto local bOk = MySetAxisPos( sName, dPos) local bOk2 = not dPrev2 or MySetAxisPos( sName2, dPos2) local bOk3 = not dPrev3 or MySetAxisPos( sName3, dPos3) local bOk4 = not dPrev4 or MySetAxisPos( sName4, dPos4) local bOk5 = not dPrev5 or MySetAxisPos( sName5, dPos5) return ( bOk and bOk2 and bOk3 and bOk4 and bOk5), bOk, bOk2, bOk3, bOk4, bOk5 end --------------------------------------------------------------------- function SetToolForVmill( sTool, sHead, nExit, VMill) -- se Vmill non definito, esco if not VMill then return true end -- se utensile, testa o uscita non definiti, reset ed esco if not sTool or sTool == '' or not sHead or sHead == '' or not nExit then EgtVolZmapResetTool( VMill) return false end -- verifico che l'utensile sia corrente local sOldTool = EgtTdbGetCurrToolParam( MCH_TP.NAME) if sTool ~= sOldTool then if not EgtTdbSetCurrTool( sTool) then return false end end -- dichiaro utensile per Vmill local nType = EgtTdbGetCurrToolParam( MCH_TP.TYPE) local dLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) local dDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) local dCornR = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) local dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) local dMaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) -- ricerca dell'outline e del diametro gambo local nExitId = EgtGetFirstNameInGroup( EgtGetHeadId( sHead) or GDB_ID.NULL, 'T' .. tostring( nExit)) local nToolId = EgtGetFirstNameInGroup( nExitId or GDB_ID.NULL, sTool) local nOutlineId = EgtGetFirstNameInGroup( nToolId or GDB_ID.NULL, 'Outline') local dMaxStemDiam = EgtGetInfo( nToolId or GDB_ID.NULL, 'D_STEM', 'd') or dDiam -- imposto profilo utensile per Vmill if nOutlineId then EgtVolZmapSetGenTool( VMill, sTool, nOutlineId) elseif nType == MCH_TY.MORTISE_STD then EgtVolZmapSetMortiserTool( VMill, sTool, dLen, dDiam, dThick, dCornR) elseif nType == MCH_TY.SAW_STD or nType == MCH_TY.SAW_FLAT then EgtVolZmapSetSawTool( VMill, sTool, dLen, dDiam, dThick, 0, dCornR) elseif nType == MCH_TY.WATERJET then EgtVolZmapSetStdTool( VMill, sTool, dLen + 50, dDiam, dCornR, dMaxMat) elseif abs( dSideAng) < GEO.EPS_ANG_SMALL or abs( dThick) < GEO.EPS_ANG_SMALL then if dDiam <= dMaxStemDiam then EgtVolZmapSetStdTool( VMill, sTool, dLen, dDiam, dCornR, dMaxMat) else EgtVolZmapSetSawTool( VMill, sTool, dLen, dDiam, dMaxMat, 0, dCornR) end else local bExtra = ( dThick > 0) local dTipLen = abs( dThick) local dTotLen = EgtIf( bExtra, dLen + dTipLen, dLen) local dDelta if dSideAng > 0 then if dCornR < GEO.EPS_SMALL then dDelta = 2 * dTipLen * tan( dSideAng) else dDelta = 2 * ( dCornR * cos( dSideAng) + ( dTipLen - dCornR + dCornR * sin( dSideAng)) * tan( dSideAng)) end else dDelta = 2 * tan( dSideAng) * dTipLen end local dStemDiam = EgtIf( bExtra, dDiam, dDiam + dDelta) local dTipDiam = EgtIf( bExtra, dDiam - dDelta, dDiam) EgtVolZmapSetAdvTool( VMill, sTool, dTotLen, dStemDiam, dTipLen, dTipDiam, dCornR, dMaxMat) end -- se l'utensile non era corrente, ripristino il precedente if sTool ~= sOldTool then EgtTdbSetCurrTool( sOldTool) end return true end --------------------------------------------------------------------- local function AddGeomToCollisionCheck( CollGrpId, sClass, vColl) if not CollGrpId then return false end local sCollGrp = EgtGetName( CollGrpId) or '' -- ricerca dei box local BoxId = EgtGetFirstNameInGroup( CollGrpId, 'BOX') while BoxId do local FrameId = BoxId + ( EgtGetInfo( BoxId, 'Frame', 'i') or 0) if FrameId ~= BoxId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then local b3Box = EgtGetBBoxRef( BoxId, GDB_BB.STANDARD, EgtFR( FrameId, GDB_ID.ROOT)) local vtDiag = b3Box:getMax() - b3Box:getMin() local vtM = b3Box:getMin() - ORIG() table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.BOX, Mv=vtM, P1=vtDiag:getX(), P2=vtDiag:getY(), P3=vtDiag:getZ()}) BoxId = EgtGetNextName( BoxId, 'BOX') end end -- ricerca dei cilindri local CylId = EgtGetFirstNameInGroup( CollGrpId, 'CYL') while CylId do local FrameId = CylId + ( EgtGetInfo( CylId, 'Frame', 'i') or 0) if FrameId ~= CylId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then local b3Box = EgtGetBBoxRef( CylId, GDB_BB.STANDARD, EgtFR( FrameId, GDB_ID.ROOT)) local dR = ( b3Box:getDimX() + b3Box:getDimY()) / 4 local dH = b3Box:getDimZ() local vtM = Vector3d( 0, 0, b3Box:getMin():getZ()) table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtM, P1=dR, P2=dH, P3=0}) CylId = EgtGetNextName( CylId, 'CYL') end end -- ricerca delle sfere local SphId = EgtGetFirstNameInGroup( CollGrpId, 'SPH') while SphId do local FrameId = SphId + ( EgtGetInfo( SphId, 'Frame', 'i') or 0) if FrameId ~= SphId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then local b3Box = EgtGetBBoxRef( SphId, GDB_BB.STANDARD, EgtFR( FrameId, GDB_ID.ROOT)) local dR = ( b3Box:getDimX() + b3Box:getDimY() + b3Box:getDimZ()) / 6 local vtM = b3Box:getCenter() - ORIG() table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.SPHE, Mv=vtM, P1=dR, P2=0, P3=0}) SphId = EgtGetNextName( SphId, 'SPH') end end -- ricerca dei tronchi di cono local ConId = EgtGetFirstNameInGroup( CollGrpId, 'CON') while ConId do local FrameId = ConId + ( EgtGetInfo( ConId, 'Frame', 'i') or 0) if FrameId ~= ConId and EgtGetType( FrameId) == GDB_TY.GEO_FRAME then local frRef = EgtFR( FrameId, GDB_ID.ROOT) local vtZ = frRef:getVersZ() local dRb, dRt, dOb, dOt -- ricerca delle facce bottom e top local nFacCnt = EgtSurfTmFacetCount( ConId) for i = 0, nFacCnt - 1 do local vtN = EgtSurfTmFacetNormVersor( ConId, i, GDB_ID.ROOT) if AreSameVectorApprox( vtN, vtZ) then local b3Box = EgtSurfTmGetFacetBBoxRef( ConId, i, GDB_BB.STANDARD, frRef) dRt = ( b3Box:getDimX() + b3Box:getDimY()) / 4 dOt = b3Box:getCenter():getZ() elseif AreOppositeVectorApprox( vtN, vtZ) then local b3Box = EgtSurfTmGetFacetBBoxRef( ConId, i, GDB_BB.STANDARD, frRef) dRb = ( b3Box:getDimX() + b3Box:getDimY()) / 4 dOb = b3Box:getCenter():getZ() end end if dRb and dRt and dOb and dOt then local vtM = Vector3d( 0, 0, dOb) local dH = dOt - dOb table.insert( vColl, { Cl=sClass, Grp=sCollGrp, Fr=FrameId, Ty=MCH_SIM_COB.CONE, Mv=vtM, P1=dRb, P2=dRt, P3=dH}) end ConId = EgtGetNextName( ConId, 'CON') end end return true end --------------------------------------------------------------------- function AddToCollisionCheck( sName, sCollGrp, vColl) if not vColl then return false end -- ricerca del gruppo base local GroupId = EgtGetHeadId( sName) if not GroupId then GroupId = EgtGetAxisId( sName) end if not GroupId then GroupId = EgtGetTableId( sName) end if not GroupId then GroupId = EgtGetBaseId( sName) end if not GroupId then return false end -- ricerca del gruppo di collisione local CAxCollId = EgtGetFirstNameInGroup( GroupId, sCollGrp) if not CAxCollId then return false end -- recupero della geometria di collisione return AddGeomToCollisionCheck( CAxCollId, sName, vColl) end --------------------------------------------------------------------- function AddToolToCollisionCheck( sHeadName, nExit, vColl) if not vColl then return false end local sTool = EgtGetLoadedTool( sHeadName, nExit) if not EgtTdbSetCurrTool( sTool or '') then return false end local nType = EgtTdbGetCurrToolParam( MCH_TP.TYPE) local dTotRad = EgtTdbGetCurrToolParam( MCH_TP.TOTDIAM) / 2 local dTotLen = EgtTdbGetCurrToolParam( MCH_TP.TOTLEN) local HeadId = EgtGetHeadId( sHeadName) local FrameId = EgtGetFirstNameInGroup( HeadId, '_T'..tostring( nExit)) if nType == MCH_TY.SAW_STD or nType == MCH_TY.SAW_FLAT then local vtM = Vector3d( 0, 0, -dTotLen) local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtM, P1=dTotRad, P2=dThick, P3=0}) elseif nType == MCH_TY.DRILL_STD or nType == MCH_TY.DRILL_LONG then local dLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) local vtMc = Vector3d( 0, 0, -dLen) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtMc, P1=dTotRad, P2=dLen, P3=0}) if dTotLen > dLen + 0.1 then local vtMt = Vector3d( 0, 0, -dTotLen) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CONE, Mv=vtMt, P1=0, P2=dTotRad, P3=dTotLen-dLen}) end elseif nType ~= MCH_TY.MORTISE_STD then local dSideAng = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) if abs( dSideAng) < GEO.EPS_ANG_SMALL or abs( dThick) < GEO.EPS_ANG_SMALL then local vtM = Vector3d( 0, 0, -dTotLen) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtM, P1=dTotRad, P2=dTotLen, P3=0}) else local dLen = EgtTdbGetCurrToolParam( MCH_TP.LEN) local dDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM) local bExtra = ( dThick > 0) local dTipLen = abs( dThick) local dTotLen = EgtIf( bExtra, dLen + dTipLen, dLen) local dDelta = 2 * dTipLen * tan( dSideAng) local dStemRad = EgtIf( bExtra, dDiam, dDiam + dDelta) / 2 local dTipRad = EgtIf( bExtra, dDiam - dDelta, dDiam) / 2 local vtMs = Vector3d( 0, 0, -( dTotLen - dTipLen)) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CYL, Mv=vtMs, P1=dStemRad, P2=dTotLen-dTipLen, P3=0}) local vtMt = Vector3d( 0, 0, -dTotLen) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=FrameId, Ty=MCH_SIM_COB.CONE, Mv=vtMt, P1=dTipRad, P2=dStemRad, P3=dTipLen}) end else EgtErase( EgtGetFirstNameInGroup( HeadId, '_TT'..tostring( nExit)) or GDB_ID.NULL) local frRef = EgtFR( FrameId) local SpecFrId = EgtCopy( FrameId, FrameId, GDB_IN.AFTER) EgtSetName( SpecFrId, '_TT'..tostring( nExit)) EgtRotate( SpecFrId, frRef:getOrigin(), frRef:getVersY(), 90) local dThick = EgtTdbGetCurrToolParam( MCH_TP.THICK) local vtMb = Vector3d( 0, -dTotRad, 0) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=SpecFrId, Ty=MCH_SIM_COB.BOX, Mv=vtMb, P1=dTotLen-dTotRad, P2=2*dTotRad, P3=dThick}) local vtMc = Vector3d( dTotLen-dTotRad, 0, 0) table.insert( vColl, { Cl='T_'..sHeadName, Grp=sTool, Fr=SpecFrId, Ty=MCH_SIM_COB.CYL, Mv=vtMc, P1=dTotRad, P2=dThick, P3=0}) end return true end --------------------------------------------------------------------- function DumpCollisionCheck( vColl, sTitle, nDbgLev) if not vColl then return false end if EgtGetDebugLevel() < ( nDbgLev or 1) then return true end if sTitle then EgtOutLog( sTitle, nDbgLev or 1) end for i, Coll in ipairs( vColl) do local sOut = ' Class='..Coll.Cl..' Group='..Coll.Grp..' FrId='..tostring( Coll.Fr)..' Type='..tostring( Coll.Ty)..' Mv='..tostring( Coll.Mv) if Coll.Ty == MCH_SIM_COB.BOX then sOut = sOut .. ' L='..EgtNumToString( Coll.P1, 3)..' W='..EgtNumToString( Coll.P2, 3)..' H='..EgtNumToString( Coll.P3, 3) elseif Coll.Ty == MCH_SIM_COB.CYL then sOut = sOut .. ' R='..EgtNumToString( Coll.P1, 3)..' H='..EgtNumToString( Coll.P2, 3) elseif Coll.Ty == MCH_SIM_COB.SPHE then sOut = sOut .. ' R='..EgtNumToString( Coll.P1, 3) elseif Coll.Ty == MCH_SIM_COB.CONE then sOut = sOut .. ' Rb='..EgtNumToString( Coll.P1, 3)..' Rt='..EgtNumToString( Coll.P2, 3)..' H='..EgtNumToString( Coll.P3, 3) end EgtOutLog( sOut, nDbgLev or 1) end return true end --------------------------------------------------------------------- function AddToolToCollisionObj( sTool, sHeadName, nExit, nInd) local vToolColl = {} AddToolToCollisionCheck( sHeadName, nExit, vToolColl) if #vToolColl == 0 then return false end DumpCollisionCheck( vToolColl, 'Tool Collision Objects :', 4) -- aggiungo la geometria trovata for i = 1, #vToolColl do EmtAddCollisionObjEx( nInd, vToolColl[i].Fr, vToolColl[i].Ty, vToolColl[i].Mv, vToolColl[i].P1, vToolColl[i].P2, vToolColl[i].P3) end return true, vToolColl[1] end --------------------------------------------------------------------- function AddToolHolderToCollisionObj( sTool, sHeadName, nExit, nInd) -- recupero il gruppo dell'utensile local HeadId = EgtGetHeadId( sHeadName) local ExitId = EgtGetFirstNameInGroup( HeadId, 'T'..tostring( nExit)) local ToolId = EgtGetFirstInGroup( ExitId) -- cerco la geometria di collisione in questo gruppo local vThColl = {} if not AddGeomToCollisionCheck( ToolId, 'TH_'..sHeadName, vThColl) then return false end DumpCollisionCheck( vThColl, 'ToolHolder Collision Objects :', 4) -- aggiungo la geometria trovata for i = 1, #vThColl do EmtAddCollisionObjEx( nInd, vThColl[i].Fr, vThColl[i].Ty, vThColl[i].Mv, vThColl[i].P1, vThColl[i].P2, vThColl[i].P3) end return true, #vThColl end --------------------------------------------------------------------- return EmtGenerator