2370 lines
99 KiB
Plaintext
2370 lines
99 KiB
Plaintext
-- Special Operations macchina Saomad-KAIROS by EgalWare s.r.l. 2023/12/01
|
|
|
|
-- Intestazioni
|
|
require( 'EmtGenerator')
|
|
EgtEnableDebug( false)
|
|
|
|
-- Carico i dati globali
|
|
local sBaseDir = EgtGetCurrMachineDir()
|
|
local BD = dofile( sBaseDir .. '\\Beam\\BeamData.lua')
|
|
|
|
---------------------------------------------------------------------
|
|
-- *** Generic Machinings ***
|
|
---------------------------------------------------------------------
|
|
pcall( require, 'EmtGenMachining') -- si fa una require con PCALL perchè la libreria è opzionale
|
|
|
|
---------------------------------------------------------------------
|
|
-- *** Special Link moves ***
|
|
---------------------------------------------------------------------
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
function OnSpecialLink()
|
|
|
|
-- se fresa su testa 1
|
|
if EMC.HEAD == 'H1' then
|
|
-- se inizio lavorazione con prelievo utensile
|
|
if EMC.LINKTYPE == 1 then
|
|
-- se fine lavorazione con deposito utensile
|
|
elseif EMC.LINKTYPE == 2 then
|
|
-- altrimenti collegamento tra due lavorazioni (3)
|
|
else
|
|
end
|
|
-- se motosega
|
|
elseif EMC.HEAD == 'H3' then
|
|
end
|
|
EMC.ERR = 0
|
|
end
|
|
|
|
---------- OnSpecialApplyDisposition & OnPostApplyMachining ---------
|
|
----------------------- Costanti ------------------------------------
|
|
local AGG_LOAD = 0
|
|
local MaxLenSmT = 1500 -- massima lunghezza pezzo scaricato con nastri verdi
|
|
|
|
----------------------- Variabili -----------------------------------
|
|
local Test = false
|
|
|
|
---------------------------------------------------------------------
|
|
local function PrepareClGroup( nParentId)
|
|
|
|
local nClId = EgtGetFirstNameInGroup( nParentId, 'CL')
|
|
-- se non c'è, lo aggiunge
|
|
if not nClId then
|
|
nClId = EgtGroup( EMC.DISPID)
|
|
if not nClId then
|
|
return nil
|
|
end
|
|
EgtSetName( nClId, 'CL')
|
|
-- altrimenti lo svuoto
|
|
else
|
|
EgtEmptyGroup( nClId)
|
|
end
|
|
|
|
return nClId
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsStartPhase( nPhase)
|
|
local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE')
|
|
return ( sVal == 'START')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsStartOrRestPhase( nPhase)
|
|
local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE')
|
|
return ( sVal == 'START' or sVal == 'REST')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsMidPhase( nPhase)
|
|
local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE')
|
|
return ( sVal == 'MID')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsEndPhase( nPhase)
|
|
local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE')
|
|
return ( sVal == 'END')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsMid2Phase( nPhase)
|
|
local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE')
|
|
return ( sVal == 'MID2')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsEnd2Phase( nPhase)
|
|
local sVal = EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE')
|
|
return ( sVal == 'END2')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function GetNextStartOrRestPhase( nPhase)
|
|
local nNextPhase = nPhase + 1
|
|
while nNextPhase <= EgtGetPhaseCount() do
|
|
if IsStartOrRestPhase( nNextPhase) then
|
|
break ;
|
|
end
|
|
nNextPhase = nNextPhase + 1
|
|
end
|
|
return nNextPhase
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function GetPhaseRot( nPhase)
|
|
return ( EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'ROT', 'i') or 0)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsLastOperationBeforeRotation( nOperId)
|
|
-- se ultima fase o ultima fase del pezzo, ritorno risultato negativo
|
|
if EMC.PHASE == EgtGetPhaseCount() or IsEndPhase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE) then
|
|
return false
|
|
end
|
|
-- recupero la successiva operazione attiva
|
|
local nNextOperId = EgtGetNextActiveOperation( nOperId)
|
|
-- se non esiste o non è una disposizione, ritorno risultato negativo
|
|
if not nNextOperId or EgtGetOperationType( nNextOperId) ~= MCH_OY.DISP then
|
|
return false
|
|
end
|
|
-- recupero le rotazioni della fase corrente e della prossima fase
|
|
local nRot = GetPhaseRot( EMC.PHASE)
|
|
local nNextRot = GetPhaseRot( EMC.PHASE + 1)
|
|
-- ritorno se sono diverse
|
|
return ( nRot ~= nNextRot)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function IsFirstMachiningAfterRotation( nMchId)
|
|
-- se prima fase o prima fase del pezzo, ritorno risultato negativo
|
|
if EMC.PHASE == 1 or IsStartOrRestPhase( EMC.PHASE) then
|
|
return false
|
|
end
|
|
-- recupero la precedente operazione attiva
|
|
local nPrevOperId = EgtGetPrevActiveOperation( nMchId)
|
|
-- se non esiste o non è una disposizione, ritorno risultato negativo
|
|
if not nPrevOperId or EgtGetOperationType( nPrevOperId) ~= MCH_OY.DISP then
|
|
return false
|
|
end
|
|
-- recupero le rotazioni della fase corrente e della fase precedente
|
|
local nRot = GetPhaseRot( EMC.PHASE)
|
|
local nPrevRot = GetPhaseRot( EMC.PHASE - 1)
|
|
-- ritorno se sono diverse
|
|
return ( nRot ~= nPrevRot)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function GetCUTID()
|
|
-- recupero CUTID del pezzo in lavoro
|
|
local nOrd = GetPhaseOrd( EMC.PHASE)
|
|
local nPartRawId
|
|
local nRawId = EgtGetFirstRawPart()
|
|
while nRawId do
|
|
local nRawOrd = EgtGetInfo( nRawId, 'ORD', 'i')
|
|
if nRawOrd == nOrd then
|
|
nPartRawId = nRawId
|
|
break
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
local CutID = EgtGetInfo( EgtGetFirstPartInRawPart( nPartRawId or GDB_ID.NULL) or GDB_ID.NULL, 'CUTID', 'i') or 0
|
|
return CutID
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function AddZmaxMove( vCmd)
|
|
table.insert( vCmd, { 1, 'Z', EgtGetAxisHomePos( 'Z')})
|
|
return vCmd
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function EmitComment( vCmd, sOut)
|
|
EgtOutLog( ' ' .. sOut, 1)
|
|
if Test then
|
|
table.insert( vCmd, { 0, sOut})
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function OnSpecialApplyDisposition()
|
|
|
|
EgtOutLog( ' *** Fase : ' .. EgtNumToString( EMC.PHASE, 0) .. ' ***', 1)
|
|
|
|
-- Inizializzo codice di errore
|
|
EMC.ERR = 0
|
|
|
|
-- Campi obbligatori ma non usati
|
|
EMC.HEAD = ""
|
|
EMC.EXIT = 1
|
|
EMC.TCPOS = ""
|
|
EMC.SHIFTS = 0
|
|
EMC.SBH = false
|
|
|
|
-- Se disposizione da saltare non devo fare alcunché
|
|
if EgtExistsInfo( EMC.DISPID, 'SKIP') then return end
|
|
|
|
-- Assegno flag di pezzo separato dal resto del grezzo
|
|
local bSplit = IsEndPhase( EMC.PHASE) or IsMid2Phase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE)
|
|
|
|
-- Recupero il tipo dell'operazione successiva
|
|
local nNextOpeType = EgtGetOperationType( EgtGetNextActiveOperation( EMC.DISPID) or GDB_ID.NULL)
|
|
|
|
-- Se ci sono lavorazioni successive non devo fare alcunché
|
|
if nNextOpeType ~= MCH_OY.NONE and nNextOpeType ~= MCH_OY.DISP then return end
|
|
|
|
-- Imposto gruppo e path di movimento
|
|
local nClId = PrepareClGroup( EMC.DISPID)
|
|
if not nClId then
|
|
EMC.ERR = 3
|
|
return
|
|
end
|
|
local nPathId = EgtGroup( nClId)
|
|
if not nPathId then
|
|
EMC.ERR = 6
|
|
return
|
|
end
|
|
EgtSetName( nPathId, 'Empty')
|
|
EMC.PATHID = nPathId
|
|
EMC.SHIFTS = -1
|
|
|
|
-- Se l'operazione successiva è una disposizione con rotazione, devo preparare il pezzo alla rotazione
|
|
if IsLastOperationBeforeRotation( EMC.DISPID) then
|
|
-- aggiornamento posizioni
|
|
if IsStartPhase( EMC.PHASE) then
|
|
-- carico le posizioni
|
|
local dPosT = EgtGetInfo( EMC.DISPID, 'TPOS', 'd')
|
|
local dPosX1 = EgtGetInfo( EMC.DISPID, 'X1POS', 'd')
|
|
EMC.TPOS = dPosT
|
|
EMC.X1DELTA = dPosX1 - dPosT
|
|
EMC.X2DELTA = nil
|
|
else
|
|
local nPrevOpeId = EgtGetPrevActiveOperation( EMC.DISPID)
|
|
local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL)
|
|
local nLastEntId = EgtGetLastInGroup( nLastPathId)
|
|
local vAxes = EmtGetAxesPos( nLastEntId)
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
EMC.X1DELTA = EgtGetInfo( nLastPathId, 'X1DELTA', 'd')
|
|
EMC.X2DELTA = EgtGetInfo( nLastPathId, 'X2DELTA', 'd')
|
|
EMC.DISTFRONT = EgtGetInfo( nLastPathId, 'DISTFRONT', 'd') or 0
|
|
EMC.DISTBACK = EgtGetInfo( nLastPathId, 'DISTBACK', 'd') or 0
|
|
end
|
|
-- Determinazione delle dimensioni del grezzo in lavoro
|
|
local b3Raw = BBox3d()
|
|
local nRawId = EgtGetFirstRawPart()
|
|
while nRawId do
|
|
if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) then
|
|
b3Raw = EgtGetRawPartBBox( nRawId)
|
|
break
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
EMC.LENGTHBEAM = b3Raw:getDimX() + 10 * GEO.EPS_SMALL
|
|
-- Assegno sovramateriale di testa e ingombro tagli di testa e di coda
|
|
EMC.HOVM = EgtGetInfo( nRawId, 'HOVM', 'd') or 0
|
|
EMC.HCING = 0
|
|
EMC.TCING = EgtGetInfo( nRawId, 'TCING', 'd') or 0
|
|
-- Eseguo preparazione alla rotazione
|
|
local vCmd = SpecCalcPreRot()
|
|
SpecOutputCmds( vCmd, true)
|
|
return
|
|
end
|
|
|
|
-- Se l'operazione successiva è ancora una disposizione, devo scaricare il pezzo
|
|
if nNextOpeType == MCH_OY.DISP and bSplit and not IsEnd2Phase( EMC.PHASE) then
|
|
-- aggiornamento posizioni
|
|
local nPrevOpeId = EgtGetPrevActiveOperation( EMC.DISPID)
|
|
local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL)
|
|
local nLastEntId = EgtGetLastInGroup( nLastPathId)
|
|
local vAxes = EmtGetAxesPos( nLastEntId)
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
EMC.X1DELTA = EgtGetInfo( nLastPathId, 'X1DELTA', 'd')
|
|
EMC.X2DELTA = EgtGetInfo( nLastPathId, 'X2DELTA', 'd')
|
|
EMC.DISTFRONT = EgtGetInfo( nLastPathId, 'DISTFRONT', 'd') or 0
|
|
EMC.DISTBACK = EgtGetInfo( nLastPathId, 'DISTBACK', 'd') or 0
|
|
-- Determinazione delle dimensioni del grezzo in lavoro
|
|
local b3Raw = BBox3d()
|
|
local nRawId = EgtGetFirstRawPart()
|
|
while nRawId do
|
|
if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) and not EgtVerifyRawPartPhase( nRawId, EMC.PHASE + 1) then
|
|
b3Raw = EgtGetRawPartBBox( nRawId)
|
|
break
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
EMC.LENGTHBEAM = b3Raw:getDimX() + 10 * GEO.EPS_SMALL
|
|
EMC.HOVM = EgtGetInfo( nRawId or GDB_ID.NULL, 'HOVM', 'd') or 0
|
|
-- Eseguo scarico
|
|
local vCmd = SpecCalcUnload()
|
|
SpecOutputCmds( vCmd, true)
|
|
return
|
|
end
|
|
|
|
-- Verifico ci sia un solo grezzo nella fase corrente
|
|
local nRawCount = 0
|
|
local nCurrRawId = GDB_ID.NULL
|
|
local nRawId = EgtGetFirstRawPart()
|
|
while nRawId do
|
|
if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) then
|
|
nRawCount = nRawCount + 1
|
|
nCurrRawId = nRawId
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
|
|
-- Determinazione delle sue dimensioni
|
|
local b3Raw = EgtGetRawPartBBox( nCurrRawId)
|
|
if not b3Raw or b3Raw:isEmpty() then
|
|
EMC.ERR = 11
|
|
return
|
|
end
|
|
EMC.LENGTHBEAM = b3Raw:getDimX() + 10 * GEO.EPS_SMALL
|
|
EMC.WIDTHBEAM = b3Raw:getDimY()
|
|
EMC.HEIGHTBEAM = b3Raw:getDimZ()
|
|
EMC.ZMIN = b3Raw:getMin():getZ()
|
|
|
|
-- Aggiorno limiti di presa e tolleranza
|
|
UpdateMinJoinDeltaTol( EMC.WIDTHBEAM, EMC.HEIGHTBEAM, EMC.LENGTHBEAM)
|
|
|
|
-- TODO per il momento si ha solo area proibita in testa e coda, ma servirebbe dinamico che cambi ad ogni lavorazione eseguita.
|
|
-- Assegno sovramateriale di testa e ingombro tagli di testa e di coda
|
|
EMC.HOVM = EgtGetInfo( nCurrRawId, 'HOVM', 'd') or 0
|
|
EMC.HCING = EgtGetInfo( nCurrRawId, 'HCING', 'd') or 0
|
|
EMC.TCING = EgtGetInfo( nCurrRawId, 'TCING', 'd') or 0
|
|
|
|
-- Devo scaricare il grezzo rimasto (deve essere unico)
|
|
-- Posizione trave
|
|
local dPosT
|
|
|
|
-- Se fase 1 o dopo rotazione eseguo carico con carrello X1
|
|
local vCmd = {}
|
|
if EMC.PHASE == 1 or IsEnd2Phase( EMC.PHASE) then
|
|
dPosT = LoadT
|
|
if IsEnd2Phase( EMC.PHASE) then dPosT = dPosT + TurnerOffs end
|
|
vCmd = GetLoadCmd( dPosT, 0, min( EMC.LENGTHBEAM - MinOther - AGG_LOAD, MaxX1 - dPosT))
|
|
-- se altrimenti fase successiva alla prima di tipo inizio o rimanenza
|
|
elseif IsStartOrRestPhase( EMC.PHASE) then
|
|
-- recupero posizione trave e quota di aggancio carrello
|
|
dPosT = EgtGetInfo( EMC.DISPID, 'TPOS', 'd')
|
|
local dPosX1 = EgtGetInfo( EMC.DISPID, 'X1POS', 'd')
|
|
-- se carrello agganciato
|
|
if dPosX1 then
|
|
-- confermo i nuovi parametri di aggancio
|
|
table.insert( vCmd, { 21, dPosX1 - dPosT, 0})
|
|
-- recupero CNT
|
|
local nPrevOpeId = EgtGetPrevActiveOperation( EMC.DISPID)
|
|
if EgtGetOperationType( nPrevOpeId) == MCH_OY.DISP and EgtExistsInfo( nPrevOpeId, 'SKIP') then
|
|
nPrevOpeId = EgtGetPrevActiveOperation( nPrevOpeId)
|
|
end
|
|
local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL)
|
|
-- altrimenti è grezzo scaricato al carico e devo ricaricarlo
|
|
else
|
|
vCmd = GetLoadCmd( dPosT, 0, min( EMC.LENGTHBEAM - MinOther - AGG_LOAD, MaxX1 - dPosT))
|
|
end
|
|
-- altrimenti fase successiva pari
|
|
else
|
|
local dPosX2 = EgtGetInfo( EMC.DISPID, 'X2POS', 'd')
|
|
EMC.X2DELTA = dPosX2
|
|
end
|
|
-- Se fase inizio o rimanenza, eseguo scambio per avere solo pinza X2
|
|
local vCmd2 = {}
|
|
if IsStartOrRestPhase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE) then
|
|
EMC.TPOS = dPosT
|
|
SpecSetCarrPosFromCmds( vCmd)
|
|
local CurrUnloadT = EgtIf( EMC.LENGTHBEAM < MaxLenSmT, UnloadSmT, UnloadT)
|
|
local dDistFront = EgtIf( EMC.LENGTHBEAM < abs( MinX2 - CurrUnloadT), MinJoin, EMC.LENGTHBEAM - abs( MinX2 - CurrUnloadT) + MinJoin + DeltaTol)
|
|
local dDistBack = 0
|
|
vCmd2 = GetCarriagesCmdFromMachEncumbrance( dDistFront, dDistBack)
|
|
if vCmd and #vCmd > 1 and vCmd2 and #vCmd2 > 1 then
|
|
table.insert( vCmd, { 0, 'CARR_MOVE'})
|
|
end
|
|
end
|
|
-- eseguo scarico
|
|
SpecSetCarrPosFromCmds( vCmd2)
|
|
local vCmd3 = SpecCalcUnload()
|
|
-- unisco ed emetto i comandi
|
|
vCmd = EgtJoinTables( vCmd, vCmd2)
|
|
vCmd = EgtJoinTables( vCmd, vCmd3)
|
|
SpecOutputCmds( vCmd, true)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function OnPostApplyMachining()
|
|
-- Inizializzo codice di errore
|
|
EMC.ERR = 0
|
|
-- Verifico se ultima lavorazione della fase
|
|
local nNextOpeId = EgtGetNextActiveOperation( EMC.MCHID)
|
|
local bMchLast = ( not nNextOpeId or EgtGetOperationPhase( nNextOpeId) ~= EMC.PHASE) -- Agisco sui diversi percorsi della lavorazione
|
|
local nPathId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( EMC.MCHID, 'CL') or GDB_ID.NULL)
|
|
while nPathId do
|
|
-- recupero id del successivo
|
|
nPathId = EgtGetNext( nPathId)
|
|
-- verifico se ultimo percorso di ultima lavorazione della fase
|
|
local bLast = ( bMchLast and ( not nPathId))
|
|
-- se ultimo, elimino ritorno in home
|
|
if bLast then EgtRemoveOperationHome( EMC.MCHID) end
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function OnSpecialApplyMachining()
|
|
|
|
EgtOutLog( ' Lavorazione : ' .. EgtGetName( EMC.MCHID), 1)
|
|
|
|
-- Inizializzo codice di errore
|
|
EMC.ERR = 0
|
|
|
|
-- Recupero la posizione della trave e dei carrelli al termine della precedente operazione
|
|
local nPrevOpeId = EgtGetPrevActiveOperation( EMC.MCHID)
|
|
-- se precedente operazione non esiste, errore
|
|
if not nPrevOpeId then
|
|
EMC.ERR = 1
|
|
return
|
|
-- se precedente operazione è disposizione
|
|
elseif EgtGetOperationType( nPrevOpeId) == MCH_OY.DISP then
|
|
if EMC.PHASE == 1 or IsFirstMachiningAfterRotation( EMC.MCHID) then
|
|
-- posizioni home
|
|
EMC.TPOS = nil
|
|
EMC.X1DELTA = nil
|
|
EMC.X2DELTA = nil
|
|
EMC.HCING_IGNORE = true
|
|
elseif IsStartOrRestPhase( EMC.PHASE) then
|
|
-- carico le posizioni
|
|
local dPosT = EgtGetInfo( nPrevOpeId, 'TPOS', 'd')
|
|
local dPosX1 = EgtGetInfo( nPrevOpeId, 'X1POS', 'd')
|
|
-- se carrello agganciato
|
|
if dPosX1 then
|
|
EMC.TPOS = dPosT
|
|
EMC.X1DELTA = dPosX1 - dPosT
|
|
EMC.X2DELTA = nil
|
|
-- altrimenti è grezzo scaricato al carico e devo ricaricarlo
|
|
else
|
|
EMC.TPOS = nil
|
|
EMC.X1DELTA = nil
|
|
EMC.X2DELTA = nil
|
|
end
|
|
EMC.HCING_IGNORE = true
|
|
else
|
|
-- aggiornamento posizioni (da lavorazione precedente a disposizione)
|
|
local nPrev2OpeId = EgtGetPrevActiveOperation( nPrevOpeId)
|
|
if not nPrev2OpeId then
|
|
EMC.ERR = 2
|
|
return
|
|
end
|
|
local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrev2OpeId, 'CL') or GDB_ID.NULL)
|
|
local nLastEntId = EgtGetLastInGroup( nLastPathId)
|
|
local vAxes = EmtGetAxesPos( nLastEntId or GDB_ID.NULL)
|
|
if not vAxes then
|
|
EMC.ERR = 3
|
|
return
|
|
end
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
EMC.X1DELTA = EgtGetInfo( nLastPathId, 'X1DELTA', 'd')
|
|
EMC.X2DELTA = EgtGetInfo( nLastPathId, 'X2DELTA', 'd')
|
|
EMC.DISTFRONT = EgtGetInfo( nLastPathId, 'DISTFRONT', 'd') or 0
|
|
EMC.DISTBACK = EgtGetInfo( nLastPathId, 'DISTBACK', 'd') or 0
|
|
end
|
|
-- altrimenti precedente operazione è lavorazione
|
|
else
|
|
-- aggiornamento posizioni
|
|
local nLastPathId = EgtGetLastInGroup( EgtGetFirstNameInGroup( nPrevOpeId, 'CL') or GDB_ID.NULL)
|
|
local nLastEntId = EgtGetLastInGroup( nLastPathId)
|
|
local vAxes = EmtGetAxesPos( nLastEntId or GDB_ID.NULL)
|
|
if not vAxes then
|
|
EMC.ERR = 4
|
|
return
|
|
end
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
EMC.X1DELTA = EgtGetInfo( nLastPathId, 'X1DELTA', 'd')
|
|
EMC.X2DELTA = EgtGetInfo( nLastPathId, 'X2DELTA', 'd')
|
|
EMC.DISTFRONT = EgtGetInfo( nLastPathId, 'DISTFRONT', 'd') or 0
|
|
EMC.DISTBACK = EgtGetInfo( nLastPathId, 'DISTBACK', 'd') or 0
|
|
end
|
|
|
|
-- Verifico se ultima lavorazione della fase
|
|
local nNextOpeId = EgtGetNextActiveOperation( EMC.MCHID)
|
|
local bMchLast = ( not nNextOpeId or EgtGetOperationPhase( nNextOpeId) ~= EMC.PHASE)
|
|
|
|
-- Verifico se ultima lavorazione prima di una rotazione
|
|
local bPreRotMch = IsLastOperationBeforeRotation( EMC.MCHID)
|
|
|
|
-- Verifico flag di separazione e fase di scarico
|
|
local sNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
|
|
local bPreSplit = ( sNotes:find( 'Presplit') ~= nil)
|
|
local bSplitting = ( sNotes:find( 'Split') ~= nil)
|
|
local bPreCut = ( sNotes:find( 'Precut') ~= nil)
|
|
local bCutting = ( sNotes:find( 'Cut') ~= nil)
|
|
local bUnload = IsEndPhase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE)
|
|
if bPreSplit or bPreCut then
|
|
EgtSetInfo( EMC.MCHID, 'IS_PRE', '1')
|
|
else
|
|
EgtRemoveInfo( EMC.MCHID, 'IS_PRE')
|
|
end
|
|
|
|
-- Agisco sui diversi percorsi della lavorazione
|
|
local nPathId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( EMC.MCHID, 'CL') or GDB_ID.NULL)
|
|
while nPathId do
|
|
-- assegno id percorso da elaborare
|
|
EMC.PATHID = nPathId
|
|
-- recupero id del successivo
|
|
nPathId = EgtGetNext( nPathId)
|
|
-- verifico se ultimo percorso di ultima lavorazione della fase
|
|
local bLast = ( bMchLast and ( not nPathId))
|
|
-- se ultimo, elimino ritorno in home
|
|
if bLast then EgtRemoveOperationHome( EMC.MCHID) end
|
|
-- salvo lo stato di trave e carrelli
|
|
local OriTPos = EMC.TPOS
|
|
local OriX1Delta = EMC.X1DELTA
|
|
local OriX2Delta = EMC.X2DELTA
|
|
-- eseguo le elaborazioni
|
|
SpecApplyPath( bPreSplit, bSplitting, bPreCut, bCutting, bLast and bUnload, bLast and bPreRotMch)
|
|
-- se separazione, verifico il risultato
|
|
if bSplitting then
|
|
-- recupero CUTID del pezzo in lavoro
|
|
local CutID = GetCUTID()
|
|
-- in caso di errore mancato pinzaggio uscita riprovo dopo aver disabilitato le lavorazioni finali
|
|
if EMC.ERR == 18 then
|
|
-- segnalazione warning
|
|
EMC.ERR = -101
|
|
EMC.MSG = 'Warning : skipped final processes (WRN=101,CUTID='..tostring( CutID)..')'
|
|
-- ripristino lo stato originale di trave e carrelli
|
|
EMC.TPOS = OriTPos
|
|
EMC.X1DELTA = OriX1Delta
|
|
EMC.X2DELTA = OriX2Delta
|
|
-- eseguo le elaborazioni
|
|
SpecApplyPath( bPreSplit, bSplitting, bPreCut, bCutting, bLast and bUnload, bLast and bPreRotMch)
|
|
-- pinzaggio ancora impossibile, pezzo a caduta
|
|
if EMC.ERR == 18 then
|
|
-- segnalazione warning
|
|
EMC.ERR = -102
|
|
EMC.MSG = 'Warning : skipped final processes and unload by fall (WRN=102,CUTID='..tostring( CutID)..')'
|
|
end
|
|
-- scarico standard
|
|
elseif EMC.ERR == 0 then
|
|
-- segnalazione warning
|
|
EMC.ERR = -100
|
|
EMC.MSG = 'Warning : standard unload (WRN=100,CUTID='..tostring( CutID)..')'
|
|
end
|
|
-- se taglio del residuo finale, scarico standard
|
|
elseif bCutting then
|
|
-- recupero CUTID del pezzo in lavoro
|
|
local CutID = GetCUTID()
|
|
-- se non ci sono errori, segnalazione warning
|
|
if EMC.ERR == 0 then
|
|
EMC.ERR = -100
|
|
EMC.MSG = 'Warning : standard unload (WRN=100,CUTID='..tostring( CutID)..')'
|
|
end
|
|
end
|
|
if EMC.ERR > 0 then return end
|
|
-- determino la posizione finale della trave
|
|
local nLastEntId = EgtGetLastInGroup( EMC.PATHID)
|
|
local vAxes = EmtGetAxesPos( nLastEntId)
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecApplyPath( bPreSplit, bSplitting, bPreCut, bCutting, bUnload, bPreRotMch)
|
|
|
|
-- Assegno flag di pezzo separato dal resto del grezzo
|
|
local bSplit = IsEndPhase( EMC.PHASE) or IsMid2Phase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE)
|
|
|
|
-- Determinazione delle dimensioni totali dei grezzi e del grezzo in lavoro
|
|
local b3Tot = BBox3d()
|
|
local b3Raw = BBox3d()
|
|
local nNextOddPhase = GetNextStartOrRestPhase( EMC.PHASE)
|
|
local nRawId = EgtGetFirstRawPart()
|
|
local nCurrRawId = GDB_ID.NULL
|
|
while nRawId do
|
|
if EgtVerifyRawPartPhase( nRawId, EMC.PHASE) then
|
|
local b3Tmp = EgtGetRawPartBBox( nRawId)
|
|
b3Tot:Add( b3Tmp)
|
|
if EgtGetPartInRawPartCount( nRawId) > 0 and not EgtVerifyRawPartPhase( nRawId, nNextOddPhase) then
|
|
b3Raw = b3Tmp
|
|
nCurrRawId = nRawId
|
|
end
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
if b3Tot:isEmpty() then
|
|
EMC.ERR = 11
|
|
return
|
|
end
|
|
EMC.LENGTHBEAM = EgtIf( bSplit, b3Raw:getDimX(), b3Tot:getDimX()) + 10 * GEO.EPS_SMALL
|
|
EMC.WIDTHBEAM = b3Tot:getDimY()
|
|
EMC.HEIGHTBEAM = b3Tot:getDimZ()
|
|
EMC.LENGTHRAW = b3Raw:getDimX() + 10 * GEO.EPS_SMALL
|
|
EMC.YMIN = b3Raw:getMin():getY()
|
|
EMC.ZMIN = b3Raw:getMin():getZ()
|
|
|
|
-- Aggiorno limiti di presa e tolleranza
|
|
UpdateMinJoinDeltaTol( EMC.WIDTHBEAM, EMC.HEIGHTBEAM, EMC.LENGTHBEAM)
|
|
|
|
-- Recupero sovramateriale di testa e ingombro tagli di testa e di coda dal pezzo
|
|
EMC.HOVM = EgtGetInfo( nCurrRawId, 'HOVM', 'd') or 0 -- head over material
|
|
EMC.HCING = EgtGetInfo( nCurrRawId, 'HCING', 'd') or 0 -- head cutting
|
|
EMC.TCING = EgtGetInfo( nCurrRawId, 'TCING', 'd') or 0 -- tail cutting
|
|
EMC.XMAX = b3Raw:getMax():getX() - EMC.HOVM
|
|
|
|
local idDisp = EgtGetPhaseDisposition( EMC.PHASE)
|
|
local dHCING = EgtGetInfo( idDisp, 'HCING', 'd') or 0
|
|
if dHCING then
|
|
EMC.HCING = dHCING
|
|
end
|
|
local dTCING = EgtGetInfo( idDisp, 'TCING', 'd') or 0
|
|
if dTCING then
|
|
EMC.TCING = dTCING
|
|
end
|
|
|
|
local dDistFront, dDistBack
|
|
local bClampsSamePosition = EgtGetInfo( EMC.MCHID, 'ClampFIX', 'd') == 1 or false
|
|
-- se la posizione è già stata calcolata a partire da una lavorazione precedente
|
|
if bClampsSamePosition and EMC.DISTFRONT and EMC.DISTBACK then
|
|
dDistFront = EMC.DISTFRONT
|
|
dDistBack = EMC.DISTBACK
|
|
-- altrimenti si ricalcola la posizione a partire dalla lavorazione attuale
|
|
else
|
|
-- se sono stati calcolati gli ingombri
|
|
local bEntirePhaseCalculated = false
|
|
|
|
-- ingombro lavorazione attuale
|
|
dDistFront, dDistBack = GetMachiningEncumbrance( EMC.MCHID, bPreCut)
|
|
|
|
if not dDistFront or not dDistBack then return end
|
|
if bPreSplit or bSplitting then
|
|
local dDistF, dDistB = GetPhaseEncumbrance( EMC.PHASE + 1)
|
|
dDistFront = min( dDistFront, dDistF)
|
|
local dNextHOVM = EgtGetInfo( EgtGetNextRawPart( nCurrRawId) or GDB_ID.NULL, 'HOVM', 'd') or 0
|
|
local dBackOther = b3Tot:getDimX() - b3Raw:getDimX() - MinOther - dNextHOVM
|
|
local dDistBackStartPhase = GetStartPhaseEncumbrance( EMC.PHASE + 2)
|
|
if dDistBackStartPhase then
|
|
dDistBack = min( dDistBack, dDistBackStartPhase)
|
|
end
|
|
EgtOutLog( 'DistBack='..EgtNumToString( dDistBack)..' OtherBack='..EgtNumToString( dBackOther), 3)
|
|
dDistBack = min( dDistBack, dBackOther)
|
|
bEntirePhaseCalculated = true
|
|
elseif bPreCut or bCutting then
|
|
local dDistF = GetPhaseEncumbrance( EMC.PHASE + 1)
|
|
dDistFront = min( dDistFront, dDistF)
|
|
dDistBack = 0.0
|
|
bEntirePhaseCalculated = true
|
|
end
|
|
|
|
-- Verifico lunghezza pezzo
|
|
if not bSplit and not VerifyPartLength() then
|
|
return
|
|
end
|
|
|
|
-- posizione pinze in base a ingombro lavorazione attuale
|
|
local _, dX1DeltaCurrMach, dX2DeltaCurrMach = CalcCarriagesNewPositions( dDistFront, dDistBack)
|
|
|
|
-- se è già stato calcolata per tutta la fase successiva, si controlla che il pinzaggio sia valido
|
|
if bEntirePhaseCalculated then
|
|
if dX1DeltaCurrMach or dX2DeltaCurrMach then
|
|
-- se la posizione è calcolata sull'intera fase successiva, si setta nota su tutte le lavorazioni di quella fase
|
|
local nNextMchId = EgtGetNextActiveOperation( EMC.MCHID)
|
|
while nNextMchId and EgtGetOperationPhase( nNextMchId) <= EMC.PHASE + 1 do
|
|
if EgtGetOperationType( nNextMchId) ~= MCH_OY.DISP then
|
|
EgtSetInfo( nNextMchId, 'ClampFIX', 1)
|
|
end
|
|
-- prossima lavorazione
|
|
nNextMchId = EgtGetNextActiveOperation( nNextMchId)
|
|
end
|
|
end
|
|
-- altrimenti significa che è solo una lavorazione normale, si prende ingombro lavorazioni successive
|
|
else
|
|
-- controllo se schema cambia lo schema di pinzaggio
|
|
local function IsConsistentClamping( dPrev, dNext)
|
|
return ( dPrev == nil and dNext == nil) or ( dPrev ~= nil and dNext ~= nil)
|
|
end
|
|
|
|
-- se sono in una fase di start e X1DELTA è già calcolato e è più lontano del corrente, dico che X1DELTA è il corrente
|
|
-- si entra in questo caso quando la separazione precedente occupa di più delle lavorazioni di testa del pezzo successivo
|
|
if IsStartPhase( EMC.PHASE) and EMC.X1DELTA and dX1DeltaCurrMach and not EMC.X2DELTA then
|
|
if EMC.X1DELTA > dX1DeltaCurrMach then
|
|
dX1DeltaCurrMach = EMC.X1DELTA
|
|
end
|
|
end
|
|
|
|
-- in caso di pinzaggio singolo, mi salvo intervallo minimo e massimo
|
|
local dX1DeltaMin, dX1DeltaMax = dX1DeltaCurrMach, dX1DeltaCurrMach
|
|
local dX2DeltaMin, dX2DeltaMax = dX2DeltaCurrMach, dX2DeltaCurrMach
|
|
local nNextMchId = EgtGetNextActiveOperation( EMC.MCHID)
|
|
local bUseSameClampingConfig = true
|
|
while nNextMchId and EgtGetOperationType( nNextMchId) ~= MCH_OY.DISP and bUseSameClampingConfig do
|
|
local dNextDistFront, dNextDistBack, InfoUserNotes = GetMaxEncumbranceOtherMachining( nNextMchId)
|
|
if dNextDistFront and dNextDistBack then
|
|
-- se la lavorazione che sto controllando è una di separazione, allora si controlla tutta la fase successiva
|
|
if InfoUserNotes.bPreSplit or InfoUserNotes.bSplitting then
|
|
local dDistF, dDistB = GetPhaseEncumbrance( EMC.PHASE + 1)
|
|
dNextDistFront = min( dNextDistFront, dDistF)
|
|
local dNextHOVM = EgtGetInfo( EgtGetNextRawPart( nCurrRawId) or GDB_ID.NULL, 'HOVM', 'd') or 0
|
|
local dBackOther = b3Tot:getDimX() - b3Raw:getDimX() - MinOther - dNextHOVM
|
|
local dDistBackStartPhase = GetStartPhaseEncumbrance( EMC.PHASE + 2)
|
|
if dDistBackStartPhase then
|
|
dNextDistBack = min( dNextDistBack, dDistBackStartPhase)
|
|
end
|
|
EgtOutLog( 'DistBack='..EgtNumToString( dNextDistBack)..' OtherBack='..EgtNumToString( dBackOther), 3)
|
|
dNextDistBack = min( dNextDistBack, dBackOther)
|
|
bEntirePhaseCalculated = true
|
|
elseif InfoUserNotes.bPreCut or InfoUserNotes.bCutting then
|
|
-- possono esserci altri tagli di precut, scorro tutte fino a fine fase
|
|
local nLastMchId = EgtGetNextActiveOperation( nNextMchId)
|
|
while nLastMchId and EgtGetOperationType( nLastMchId) ~= MCH_OY.DISP do
|
|
local dLastDistFront = GetMaxEncumbranceOtherMachining( nLastMchId)
|
|
dNextDistFront = min( dNextDistFront, dLastDistFront)
|
|
nLastMchId = EgtGetNextActiveOperation( nLastMchId)
|
|
end
|
|
local dDistF = GetPhaseEncumbrance( EMC.PHASE + 1)
|
|
dNextDistFront = min( dNextDistFront, dDistF)
|
|
dNextDistBack = 0.0
|
|
bEntirePhaseCalculated = true
|
|
end
|
|
end
|
|
|
|
local _, dNextNewX1Delta, dNextNewX2Delta = CalcCarriagesNewPositions( dNextDistFront, dNextDistBack)
|
|
|
|
local bUnloadIsOk = true
|
|
if dNextNewX2Delta and dX2DeltaCurrMach and ( InfoUserNotes.bPreSplit or InfoUserNotes.bSplitting) then
|
|
local dLastX2Delta = min( dX2DeltaCurrMach, dNextNewX2Delta)
|
|
-- controllo che si riesca a scaricare restando nelle corse
|
|
if ( b3Raw:getDimX() - dLastX2Delta - UnloadT) + MinX2 > -100 then
|
|
bUseSameClampingConfig = false
|
|
bUnloadIsOk = false
|
|
end
|
|
end
|
|
|
|
if IsConsistentClamping( dX1DeltaCurrMach, dNextNewX1Delta) and IsConsistentClamping( dX2DeltaCurrMach, dNextNewX2Delta) and bUnloadIsOk then
|
|
-- se entrambe le morse in presa
|
|
if dX1DeltaCurrMach and dX2DeltaCurrMach then
|
|
if ( ( max( dX1DeltaCurrMach, dNextNewX1Delta) - min( dX2DeltaCurrMach, dNextNewX2Delta)) < CLAMP_MAXDIST_2CLAMP) then
|
|
if dNextNewX1Delta > dX1DeltaCurrMach then dX1DeltaCurrMach = dNextNewX1Delta end
|
|
if dNextNewX2Delta < dX2DeltaCurrMach then dX2DeltaCurrMach = dNextNewX2Delta end
|
|
dDistFront = min( dDistFront, dNextDistFront)
|
|
dDistBack = min( dDistBack, dNextDistBack)
|
|
bUseSameClampingConfig = true
|
|
else
|
|
bUseSameClampingConfig = false
|
|
end
|
|
-- se in presa solo pinza 1
|
|
elseif dX1DeltaCurrMach then
|
|
-- se la posizione richiesta della pinza non è oltre la posizione attuale e non sono troppo distante, prendo valori vecchi
|
|
if ( dX1DeltaMax - dNextNewX1Delta) < CLAMP_MAXDIST_1CLAMP and ( dNextNewX1Delta - dX1DeltaMin) < CLAMP_MAXDIST_1CLAMP then
|
|
dX1DeltaMax = max( dX1DeltaMax, dNextNewX1Delta)
|
|
dX1DeltaMin = min( dX1DeltaMin, dNextNewX1Delta)
|
|
dDistBack = min( dDistBack, dNextDistBack)
|
|
bUseSameClampingConfig = true
|
|
else
|
|
bUseSameClampingConfig = false
|
|
end
|
|
-- se in presa solo pinza 2
|
|
elseif dX2DeltaCurrMach then
|
|
-- se la posizione richiesta della pinza non è oltre la posizione attuale e non sono troppo distante, prendo valori vecchi
|
|
if ( dX2DeltaMax - dNextNewX2Delta) < CLAMP_MAXDIST_1CLAMP and ( dNextNewX2Delta - dX2DeltaMin) < CLAMP_MAXDIST_1CLAMP then
|
|
dX2DeltaMax = max( dX2DeltaMax, dNextNewX2Delta)
|
|
dX2DeltaMin = min( dX2DeltaMin, dNextNewX2Delta)
|
|
dDistFront = min( dDistFront, dNextDistFront)
|
|
bUseSameClampingConfig = true
|
|
else
|
|
bUseSameClampingConfig = false
|
|
end
|
|
end
|
|
else
|
|
bUseSameClampingConfig = false
|
|
end
|
|
|
|
-- se posso usare la stessa configurazione, allora si setta che la posizione è già calcolata
|
|
if bUseSameClampingConfig then
|
|
EgtSetInfo( nNextMchId, 'ClampFIX', 1)
|
|
-- se la posizione è calcolata sull'intera fase successiva, si setta nota su tutte le lavorazioni di quella fase
|
|
if bEntirePhaseCalculated then
|
|
-- prossima lavorazione
|
|
nNextMchId = EgtGetNextActiveOperation( nNextMchId)
|
|
while nNextMchId and EgtGetOperationPhase( nNextMchId) <= EMC.PHASE + 1 do
|
|
if EgtGetOperationType( nNextMchId) ~= MCH_OY.DISP then
|
|
EgtSetInfo( nNextMchId, 'ClampFIX', 1)
|
|
end
|
|
-- prossima lavorazione
|
|
nNextMchId = EgtGetNextActiveOperation( nNextMchId)
|
|
end
|
|
end
|
|
-- altrimenti si rimuove info in caso fosse stata settata in un calolo precedente
|
|
else
|
|
EgtRemoveInfo( nNextMchId, 'ClampFIX')
|
|
end
|
|
|
|
-- se non è già all'ultima lavorazione, chiedo la successiva
|
|
if nNextMchId and EgtGetOperationPhase( nNextMchId) <= EMC.PHASE + 1 then
|
|
nNextMchId = EgtGetNextActiveOperation( nNextMchId)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- si salvano i valori
|
|
EMC.DISTFRONT = dDistFront
|
|
EMC.DISTBACK = dDistBack
|
|
|
|
-- Se inizio o appena dopo rotazione, eseguo il carico
|
|
if not EMC.TPOS then
|
|
local dPosT = LoadT
|
|
if IsFirstMachiningAfterRotation( EMC.MCHID) then dPosT = dPosT + TurnerOffs end
|
|
local vCmd = GetLoadCmd( dPosT, dDistFront, max( dDistBack, MinJoin))
|
|
local vCmd2 = GetCarriagesCmdFromMachEncumbrance( dDistFront, dDistBack)
|
|
if vCmd2 and #vCmd2 > 1 then
|
|
table.insert( vCmd, { 0, 'CARR_MOVE'})
|
|
end
|
|
EgtJoinTables( vCmd, vCmd2)
|
|
table.insert( vCmd, { 0, 'Move_End'})
|
|
SpecOutputCmds( vCmd)
|
|
|
|
-- Se altrimenti carri entrambi diponibili, eseguo calcoli per carrelli
|
|
elseif not IsEndPhase( EMC.PHASE) then
|
|
local vCmd = GetCarriagesCmdFromMachEncumbrance( dDistFront, dDistBack)
|
|
-- Se non ci sono spostamenti, confermo i parametri di aggancio
|
|
if SpecTestOnlyRemarkInCmds( vCmd) then
|
|
table.insert( vCmd, { 21, EgtIf( EMC.X1DELTA, EMC.X1DELTA, 0), EgtIf( EMC.X2DELTA, EMC.X2DELTA, 0)})
|
|
end
|
|
SpecOutputCmds( vCmd)
|
|
|
|
-- Altrimenti, non muovo i carrelli rispetto alla trave
|
|
else
|
|
local vCmd = {}
|
|
SpecOutputCmds( vCmd)
|
|
end
|
|
EMC.HCING_IGNORE = nil
|
|
|
|
-- Se taglio di separazione
|
|
local vCmd = {}
|
|
if bSplitting then
|
|
-- rimuovo eventuale vecchia info di Skip
|
|
local NextDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) or GDB_ID.NULL
|
|
EgtRemoveInfo( NextDispId, 'SKIP')
|
|
EMC.MAXLENLEFT = EgtGetInfo( idDisp, 'MAXLENLEFT', 'd')
|
|
-- verifico se separazione con caduta
|
|
if not EMC.X2DELTA then
|
|
EgtOutLog( ' Warning SPLITTING -> separazione con caduta pezzo')
|
|
if IsEndPhase( EMC.PHASE + 1) then
|
|
EgtSetInfo( NextDispId, 'SKIP', '1')
|
|
local NextOpeId = EgtGetNextOperation( NextDispId)
|
|
while NextOpeId and EgtGetOperationPhase( NextOpeId) == EMC.PHASE + 1 do
|
|
EgtSetOperationMode( NextOpeId, false)
|
|
NextOpeId = EgtGetNextOperation( NextOpeId)
|
|
end
|
|
end
|
|
EMC.ERR = 18
|
|
-- verifico che la barra sia agganciata ad entrambi i carrelli
|
|
elseif not EMC.X1DELTA or not EMC.X2DELTA then
|
|
EMC.ERR = 19
|
|
EMC.MSG = ' Error SPLIT : X1 or X2 not clamped'
|
|
return false
|
|
end
|
|
if not IsMid2Phase( EMC.PHASE + 1) then
|
|
vCmd = SpecCalcSplit( b3Raw:getDimX())
|
|
else
|
|
vCmd = SpecCalcSplitRot( b3Raw:getDimX())
|
|
EMC.DISTBACK = nil
|
|
end
|
|
end
|
|
-- Se taglio finale di grezzo a perdere
|
|
if bCutting then
|
|
-- salvo distanza carrello X2 da inizio grezzo rimasto nella disposizione della prossima fase
|
|
local NextDispId = EgtGetPhaseDisposition( EMC.PHASE + 1)
|
|
if NextDispId then
|
|
EgtSetInfo( NextDispId, 'X2POS', EMC.X2DELTA)
|
|
end
|
|
end
|
|
|
|
-- Se previsto scarico, lo eseguo
|
|
if bUnload then
|
|
EMC.LENGTHBEAM = b3Raw:getDimX() + 10 * GEO.EPS_SMALL
|
|
local vCmdTmp = SpecCalcUnload()
|
|
vCmd = EgtJoinTables( vCmd, vCmdTmp)
|
|
end
|
|
|
|
-- Se ritorno al carico per rotazione
|
|
if bPreRotMch then
|
|
-- determino posizione testa trave
|
|
local nLastEntId = EgtGetLastInGroup( EMC.PATHID)
|
|
local vAxes = EmtGetAxesPos( nLastEntId)
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
-- eseguo movimento prima di rotazione
|
|
local vCmdTmp = SpecCalcPreRot()
|
|
vCmd = EgtJoinTables( vCmd, vCmdTmp)
|
|
end
|
|
|
|
-- Emetto eventuali comandi di separazione e/o scarico
|
|
if #vCmd > 0 then
|
|
SpecOutputCmds( vCmd, true)
|
|
end
|
|
|
|
end --SpecApplyPath( bLast)
|
|
|
|
---------------------------------------------------------------------
|
|
function GetMachiningEncumbrance( nMchId, bPreCut)
|
|
-- gruppi della lavorazione
|
|
local nClId = EgtGetFirstNameInGroup( nMchId, 'CL')
|
|
local nPathId = EgtGetFirstInGroup( nClId or GDB_ID.NULL)
|
|
if not nPathId then
|
|
EMC.ERR = 12
|
|
return
|
|
end
|
|
-- recupero ptMin ptMax della lavorazione
|
|
local ptMin = EgtGetInfo( nClId, 'MMIN', 'p')
|
|
local ptMax = EgtGetInfo( nClId, 'MMAX', 'p')
|
|
if not ptMin or not ptMax then
|
|
EMC.ERR = 13
|
|
return
|
|
end
|
|
-- se pre-taglio, aggiorno ptMax con quello del taglio finale
|
|
if bPreCut then
|
|
local ptFinMax = GetFinalCutPmax( nMchId)
|
|
if ptFinMax then
|
|
ptMax = ptFinMax
|
|
end
|
|
end
|
|
-- Recupero del vettore estrusione (coincide con il vettore utensile)
|
|
local vtTool = EgtGetInfo( nPathId, 'EXTR', 'v')
|
|
if not vtTool then
|
|
EMC.ERR = 14
|
|
return
|
|
end
|
|
-- Recupero testa
|
|
local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
-- Calcolo del vettore ausiliario
|
|
local vAxes = EmtGetAxesPos( EgtGetFirstInGroup( nPathId))
|
|
if not vAxes or #vAxes < 5 or ( sHead == 'H3' and #vAxes < 6) then
|
|
EMC.ERR = 15
|
|
return
|
|
end
|
|
local vtAux = EgtGetCalcAuxDirFromAngles( vAxes[4], vAxes[5], vAxes[6])
|
|
if not vtAux then
|
|
EMC.ERR = 16
|
|
return
|
|
end
|
|
local vtArm = vtAux
|
|
-- Recupero dei dati dell'utensile
|
|
local nToolType = EgtTdbGetCurrToolParam( MCH_TP.TYPE)
|
|
local bSaw = ( nToolType == MCH_TY.SAW_STD or nToolType == MCH_TY.SAW_FLAT)
|
|
local bChain = ( nToolType == MCH_TY.MORTISE_STD)
|
|
local dTLen = EgtTdbGetCurrToolParam( MCH_TP.LEN)
|
|
local dTDiam = EgtTdbGetCurrToolParam( MCH_TP.DIAM)
|
|
local dTDist = EgtIf( EgtTdbGetCurrToolParam( MCH_TP.DIST) > 1, EgtTdbGetCurrToolParam( MCH_TP.DIST), ChSawLen)
|
|
-- Se sega a catena, devo correggere il versore Aux per farlo coincidere con la direzione del braccio C
|
|
if bChain then
|
|
if abs( vAxes[6] or 0) < 1 then
|
|
vtArm = vtTool
|
|
else
|
|
vtArm = vtTool ^ vtAux
|
|
end
|
|
end
|
|
-- Calcolo limiti derivanti dalla lavorazione
|
|
local dDistFront, dDistBack = SpecCalcEncumbrance( vtTool, vtArm, vtAux, ptMin, ptMax, bSaw, bChain, dTLen, dTDiam, dTDist)
|
|
return dDistFront, dDistBack
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetMaxEncumbranceOtherMachining( nMchId)
|
|
-- Salvo lavorazione e utensile correnti, per ripristinarli alla fine
|
|
local nOrigMchId = EgtGetCurrMachining()
|
|
local sOrigTool = EgtTdbGetCurrToolParam( MCH_TP.NAME)
|
|
local sOrigHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
local nOrigExit = EgtTdbGetCurrToolParam( MCH_TP.EXIT)
|
|
|
|
-- imposto lavorazione e utensile correnti
|
|
EgtSetCurrMachining( nMchId)
|
|
local sTool = EgtGetMachiningParam( MCH_MP.TOOL)
|
|
if not EgtTdbSetCurrTool( sTool) then
|
|
local sTuuid = EgtGetMachiningParam( MCH_MP.TUUID)
|
|
sTool = EgtTdbGetToolFromUUID( sTuuid)
|
|
EgtTdbSetCurrTool( sTool)
|
|
end
|
|
local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
local nExit = EgtTdbGetCurrToolParam( MCH_TP.EXIT)
|
|
if sTool and sHead and nExit then EgtSetCalcTool( sTool, sHead, nExit) end
|
|
-- calcolo ingombri
|
|
local dDistF, dDistB = GetMachiningEncumbrance( nMchId)
|
|
local InfoNotes = {}
|
|
-- Verifico flag di separazione e fase di scarico
|
|
InfoNotes.sNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
|
|
InfoNotes.bPreSplit = ( InfoNotes.sNotes:find( 'Presplit') ~= nil)
|
|
InfoNotes.bSplitting = ( InfoNotes.sNotes:find( 'Split') ~= nil)
|
|
InfoNotes.bPreCut = ( InfoNotes.sNotes:find( 'Precut') ~= nil)
|
|
InfoNotes.bCutting = ( InfoNotes.sNotes:find( 'Cut') ~= nil)
|
|
|
|
-- Ripristino lavorazione e utensile correnti
|
|
if nOrigMchId then EgtSetCurrMachining( nOrigMchId) end
|
|
if sOrigTool then EgtTdbSetCurrTool( sOrigTool) end
|
|
if sOrigTool and sOrigHead and nOrigExit then EgtSetCalcTool( sOrigTool, sOrigHead, nOrigExit) end
|
|
-- Restituisco gli ingombri trovati
|
|
return dDistF, dDistB, InfoNotes
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetStartPhaseEncumbrance( nPhase)
|
|
-- si pre-calcola solo se è una fase di start dopo uno split
|
|
if not IsStartPhase( nPhase) then
|
|
return nil
|
|
end
|
|
|
|
local dDistBack = nil
|
|
local dX1DeltaStartPhaseMin = nil
|
|
local dX1DeltaStartPhaseMax = nil
|
|
local nMchId = EgtGetNextActiveOperation( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL)
|
|
|
|
if nMchId then
|
|
local bGetNext = true
|
|
while bGetNext do
|
|
local dDistFrontStartPhase, dDistBackStartPhase = GetMachiningEncumbrance( nMchId, false)
|
|
local _, dX1DeltaStartPhaseCurr, dX2DeltaStartPhaseCurr = CalcCarriagesNewPositions( dDistFrontStartPhase, dDistBackStartPhase)
|
|
-- se in presa anche pinza 2, esco subito, non sarà possibile posizionamento diretto
|
|
if not dX1DeltaStartPhaseCurr or dX2DeltaStartPhaseCurr then
|
|
break
|
|
else
|
|
-- se non ancora settato, minimo e massimo assumono il valore attuale
|
|
if not dX1DeltaStartPhaseMin and not dX1DeltaStartPhaseMax then
|
|
dX1DeltaStartPhaseMin = dX1DeltaStartPhaseCurr
|
|
dX1DeltaStartPhaseMax = dX1DeltaStartPhaseCurr
|
|
dDistBack = dDistBackStartPhase
|
|
else
|
|
-- se la posizione richiesta della pinza non è oltre la posizione attuale e non sono troppo distante, prendo valori vecchi
|
|
if ( dX1DeltaStartPhaseMax - dX1DeltaStartPhaseCurr) < CLAMP_MAXDIST_1CLAMP and ( dX1DeltaStartPhaseCurr - dX1DeltaStartPhaseMin) < CLAMP_MAXDIST_1CLAMP then
|
|
dX1DeltaStartPhaseMax = max( dX1DeltaStartPhaseMax, dX1DeltaStartPhaseCurr)
|
|
dX1DeltaStartPhaseMin = min( dX1DeltaStartPhaseMin, dX1DeltaStartPhaseCurr)
|
|
dDistBack = min( dDistBack, dDistBackStartPhase)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
nMchId = EgtGetNextActiveOperation( nMchId)
|
|
if EgtGetOperationPhase( nMchId) ~= nPhase then
|
|
bGetNext = false
|
|
end
|
|
end
|
|
-- se ho trovato un valore, allora si corregge con lunghezza del pezzo attuale perchè sto guardando al pezzo successivo,
|
|
-- ma le misure ecc sono calcolate con pezzo attuale ancora presente
|
|
if dDistBack then
|
|
dDistBack = dDistBack - EMC.LENGTHRAW
|
|
end
|
|
end
|
|
|
|
return dDistBack
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetPhaseEncumbrance( nPhase)
|
|
-- Deve essere la fase finale di lavorazione di un pezzo (già staccato dal resto della trave)
|
|
local dDistFront = EMC.LENGTHBEAM
|
|
local dDistBack = EMC.LENGTHBEAM
|
|
-- Salvo lavorazione e utensile correnti, per ripristinarli alla fine
|
|
local nOrigMchId = EgtGetCurrMachining()
|
|
local sOrigTool = EgtTdbGetCurrToolParam( MCH_TP.NAME)
|
|
local sOrigHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
local nOrigExit = EgtTdbGetCurrToolParam( MCH_TP.EXIT)
|
|
-- Ciclo sulle lavorazioni
|
|
local nMchId = EgtGetNextActiveOperation( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL)
|
|
while nMchId and EgtGetOperationPhase( nMchId) == nPhase do
|
|
-- imposto lavorazione e utensile correnti
|
|
EgtSetCurrMachining( nMchId)
|
|
local sTool = EgtGetMachiningParam( MCH_MP.TOOL)
|
|
if not EgtTdbSetCurrTool( sTool) then
|
|
local sTuuid = EgtGetMachiningParam( MCH_MP.TUUID)
|
|
sTool = EgtTdbGetToolFromUUID( sTuuid)
|
|
EgtTdbSetCurrTool( sTool)
|
|
end
|
|
local sHead = EgtTdbGetCurrToolParam( MCH_TP.HEAD)
|
|
local nExit = EgtTdbGetCurrToolParam( MCH_TP.EXIT)
|
|
if sTool and sHead and nExit then EgtSetCalcTool( sTool, sHead, nExit) end
|
|
-- calcolo ingombri
|
|
local dDistF, dDistB = GetMachiningEncumbrance( nMchId)
|
|
if dDistF and dDistB then
|
|
dDistFront = min( dDistFront, dDistF)
|
|
dDistBack = min( dDistBack, dDistB)
|
|
end
|
|
nMchId = EgtGetNextActiveOperation( nMchId)
|
|
end
|
|
-- Ripristino lavorazione e utensile correnti
|
|
if nOrigMchId then EgtSetCurrMachining( nOrigMchId) end
|
|
if sOrigTool then EgtTdbSetCurrTool( sOrigTool) end
|
|
if sOrigTool and sOrigHead and nOrigExit then EgtSetCalcTool( sOrigTool, sOrigHead, nOrigExit) end
|
|
-- Restituisco gli ingombri trovati
|
|
return dDistFront, dDistBack
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetFinalCutPmax( nMchId)
|
|
local nFinalCutId
|
|
local nId = EgtGetNextActiveOperation( nMchId)
|
|
while nId and EgtGetOperationPhase( nId) == EMC.PHASE do
|
|
nFinalCutId = nId
|
|
nId = EgtGetNextActiveOperation( nId)
|
|
end
|
|
if not nFinalCutId then return end
|
|
local nCLId = EgtGetFirstNameInGroup( nFinalCutId, 'CL')
|
|
if not nCLId then return end
|
|
return EgtGetInfo( nCLId, 'MMAX', 'p')
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
-- TODO FUNZIONE DA RIVEDERE
|
|
-- il calcolo ingombro non deve essere a casi, ma calcolato preciso con intersezione di solidi
|
|
function SpecCalcEncumbrance( vtTool, vtArm, vtAux, ptMin, ptMax, bSaw, bChain, dTLen, dTDiam, dTDist)
|
|
-- Quota in Z dal punto di inclinazione dei carrelli
|
|
local dCompZ = sqrt( 1 - vtTool:getZ() * vtTool:getZ())
|
|
local dZup = ptMin:getZ() - 0.5 * dCompZ * dTDiam - ( EMC.ZMIN + 130)
|
|
-- Posizione min e max del naso mandrino (rispetto a testa pezzo in X e riferimento pezzo in Y e Z)
|
|
local ptHeadMin = ptMin + vtTool * dTLen - Vector3d( EMC.XMAX, EMC.YMIN + EMC.WIDTHBEAM, EMC.ZMIN)
|
|
local ptHeadMax = ptMax + vtTool * dTLen - Vector3d( EMC.XMAX, EMC.YMIN + EMC.WIDTHBEAM, EMC.ZMIN)
|
|
-- Ingombro a sinistra
|
|
local dDistBack = EMC.LENGTHBEAM + ptMin:getX() + LoadT
|
|
local dHeadBack = 350
|
|
if bSaw then
|
|
if vtTool:getX() > 0 and abs( vtTool:getY()) < 0.088 and abs( vtTool:getZ()) < 0.088 then
|
|
dHeadBack = 50 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
elseif abs( vtTool:getZ()) < 0.26 and abs( vtTool:getX()) < 0.35 then
|
|
dHeadBack = EgtIf( vtArm:getX() < 0, 540, 350)
|
|
elseif abs( vtTool:getZ()) < 0.26 and abs( vtTool:getX()) < 0.71 then
|
|
if vtArm:getX() < 0 then
|
|
dHeadBack = 460
|
|
else
|
|
dHeadBack = EgtIf( vtTool:getX() > 0, 50, 90) + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
end
|
|
elseif ( vtTool:getX() > 0.7 and abs( vtTool:getY()) < 0.2 and ptMax:getZ() > EMC.ZMIN + 0.9 * EMC.HEIGHTBEAM) then
|
|
if vtTool:getZ() > 0 then
|
|
dHeadBack = max( 50, 90 - 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX()))
|
|
else
|
|
dHeadBack = max( 50, 40 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX()))
|
|
end
|
|
if ptMax:getZ() < EMC.ZMIN + BD.VICE_MINH then
|
|
dHeadBack = dHeadBack + BD.VICE_MINH
|
|
end
|
|
elseif ( vtTool:getX() > 0.2 and abs( vtTool:getZ()) < 0.5) then
|
|
dHeadBack = max( 90, 40 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX()))
|
|
elseif abs( vtTool:getZ()) < 0.93 then
|
|
if vtTool:getX() > 0 and abs( vtTool:getY()) < 0.2 and ptMax:getZ() > EMC.ZMIN + BD.VICE_MINH then
|
|
dHeadBack = 180
|
|
elseif vtTool:getX() > -0.05 then
|
|
dHeadBack = 50 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
elseif vtTool:getX() > -0.3 then
|
|
dHeadBack = 250
|
|
elseif vtTool:getX() > -0.707 then
|
|
dHeadBack = 350
|
|
elseif vtTool:getX() > -0.8667 then
|
|
dHeadBack = 400
|
|
else
|
|
dHeadBack = 520
|
|
end
|
|
else
|
|
dHeadBack = 50 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
end
|
|
-- per limiti corsa asse X1
|
|
dHeadBack = max( dHeadBack, MinX1 + 1 - vtTool:getX() * ( MillOffs + dTLen))
|
|
else
|
|
if ( vtTool:getX() > -0.1 and vtArm:getX() > -0.1) or
|
|
( abs( vtTool:getX()) < 0.1 and abs( vtTool:getZ()) < 0.1) then
|
|
dHeadBack = 130
|
|
elseif ( vtTool:getX() > -0.1 and vtArm:getX() > -0.95) then
|
|
dHeadBack = 180
|
|
elseif ( vtTool:getX() < -0.8) then
|
|
dHeadBack = 375
|
|
elseif ( vtTool:getX() < -0.75) then
|
|
dHeadBack = 350
|
|
elseif ( vtTool:getX() < -0.5) then
|
|
dHeadBack = 350
|
|
end
|
|
if vtTool:getX() < -0.25 then
|
|
dHeadBack = dHeadBack + max( dTLen - 130, 0) * abs( vtTool:getX())
|
|
elseif vtTool:getX() < 0 then
|
|
dHeadBack = dHeadBack + ( dTLen + 180) * abs( vtTool:getX())
|
|
end
|
|
if vtTool:getX() > 0.866 then
|
|
dHeadBack = 50
|
|
elseif vtTool:getX() >= 0 and dZup > 0 then
|
|
dHeadBack = max( 130, dHeadBack - dZup)
|
|
end
|
|
if abs( vtTool:getX()) < 0.5 and abs( vtTool:getZ()) > 0.259 and dZup < 0 then
|
|
if vtArm:getX() < -0.259 then
|
|
dHeadBack = 410
|
|
else
|
|
dHeadBack = EgtIf( vtTool:getZ() > 0.966, 160, 280)
|
|
end
|
|
end
|
|
-- per fresature longitudinali con utensile di fianco
|
|
if abs( vtTool:getX()) < 0.1 and vtTool:getZ() < 0.707 and vtArm:getX() < -0.5 then
|
|
dHeadBack = 400
|
|
end
|
|
-- per sega a catena di fianco
|
|
if bChain and vtTool:getX() < 0.5 and vtTool:getZ() < 0.5 and vtArm:getX() < -0.5 then
|
|
dHeadBack = max( dHeadBack, 510)
|
|
end
|
|
-- per fresa diretta quasi esattamente come X1+/- e con la testa non troppo nel pezzo
|
|
if not bChain and abs( vtTool:getX()) < 0.017 and abs( vtTool:getZ()) < 0.017 and
|
|
(( vtTool:getY() > 0 and ptHeadMin:getY() > 80) or ( vtTool:getY() < 0 and ptHeadMax:getY() < -EMC.WIDTHBEAM - 80)) then
|
|
dHeadBack = 130
|
|
end
|
|
-- per limiti corsa asse X1
|
|
if not bChain then
|
|
dHeadBack = max( dHeadBack, MinX1 + 1 - vtTool:getX() * ( MillOffs + dTLen))
|
|
else
|
|
dHeadBack = max( dHeadBack, MinX1 + 1 - vtAux:getX() * ( MillOffs + dTDist) - vtTool:getX() * dTLen)
|
|
end
|
|
end
|
|
-- Ingombro a destra
|
|
local dDistFront = - ptMax:getX() - LoadT
|
|
local dHeadFront = 350
|
|
if bSaw then
|
|
if vtTool:getX() < 0 and abs( vtTool:getY()) < 0.088 and abs( vtTool:getZ()) < 0.088 then
|
|
dHeadFront = 50 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
elseif abs( vtTool:getZ()) < 0.26 and abs( vtTool:getX()) < 0.35 then
|
|
dHeadFront = EgtIf( vtArm:getX() > 0, 540, 350)
|
|
elseif abs( vtTool:getZ()) < 0.26 and abs( vtTool:getX()) < 0.71 then
|
|
if vtArm:getX() > 0 then
|
|
dHeadFront = 350
|
|
else
|
|
dHeadFront = EgtIf( vtTool:getX() < 0, 50, 90) + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
end
|
|
elseif ( vtTool:getX() < - 0.7 and abs( vtTool:getY()) < 0.2 and ptMax:getZ() > EMC.ZMIN + 0.9 * EMC.HEIGHTBEAM) then
|
|
if vtTool:getZ() > 0 then
|
|
dHeadFront = max( 50, 90 - 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX()))
|
|
else
|
|
dHeadFront = max( 50, 40 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX()))
|
|
end
|
|
if ptMax:getZ() < EMC.ZMIN + BD.VICE_MINH then
|
|
dHeadFront = dHeadFront + BD.VICE_MINH
|
|
end
|
|
elseif ( vtTool:getX() < -0.2 and abs( vtTool:getZ()) < 0.5) then
|
|
dHeadFront = max( 90, 40 + 0.5 * dTDiam * sqrt( vtTool:getY() * vtTool:getY() + vtTool:getZ() * vtTool:getZ()))
|
|
elseif abs( vtTool:getZ()) < 0.93 then
|
|
if vtTool:getX() < 0 and abs( vtTool:getY()) < 0.2 and ptMax:getZ() > EMC.ZMIN + BD.VICE_MINH then
|
|
dHeadFront = 180
|
|
elseif vtTool:getX() < 0.05 then
|
|
dHeadFront = 50 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
elseif vtTool:getX() < 0.3 then
|
|
dHeadFront = 250
|
|
elseif vtTool:getX() < 0.707 then
|
|
dHeadFront = 350
|
|
elseif vtTool:getX() < 0.8667 then
|
|
dHeadFront = 450
|
|
else
|
|
dHeadFront = 480
|
|
end
|
|
else
|
|
dHeadFront = 50 + 0.5 * dTDiam * sqrt( 1 - vtTool:getX() * vtTool:getX())
|
|
end
|
|
-- per limiti corsa asse X2
|
|
dHeadFront = max( dHeadFront, -MaxX2 + 1 + vtTool:getX() * ( MillOffs + dTLen))
|
|
else
|
|
if ( vtTool:getX() < -0.5 and vtArm:getX() < 0.1) then
|
|
dHeadFront = max( 50, dTDiam / 2 * abs( vtTool:getZ()) + 20)
|
|
elseif ( vtTool:getX() < 0.1 and vtArm:getX() < 0.1) or
|
|
( abs( vtTool:getX()) < 0.1 and abs( vtTool:getZ()) < 0.1) then
|
|
dHeadFront = 130
|
|
elseif ( vtTool:getX() < 0.1 and vtArm:getX() < 0.95) then
|
|
dHeadFront = 180
|
|
elseif ( vtTool:getX() > 0.5) then
|
|
dHeadFront = 450
|
|
end
|
|
if vtTool:getX() > 0.25 then
|
|
dHeadFront = dHeadFront + max( dTLen - 130, 0) * vtTool:getX()
|
|
elseif vtTool:getX() > 0 then
|
|
dHeadFront = dHeadFront + ( dTLen + 180) * vtTool:getX()
|
|
end
|
|
if vtTool:getX() < -0.866 then
|
|
dHeadFront = 50
|
|
elseif vtTool:getX() <= 0 and dZup > 0 then
|
|
dHeadFront = max( 130, dHeadFront - dZup)
|
|
end
|
|
if abs( vtTool:getX()) < 0.5 and abs( vtTool:getZ()) > 0.259 and dZup < 0 then
|
|
if vtArm:getX() > 0.259 then
|
|
dHeadFront = 410
|
|
else
|
|
dHeadFront = EgtIf( vtTool:getZ() > 0.966, 160, 280)
|
|
end
|
|
end
|
|
-- per fresature longitudinali con utensile di fianco
|
|
if abs( vtTool:getX()) < 0.1 and vtTool:getZ() < 0.707 and vtArm:getX() > 0.5 then
|
|
dHeadFront = 400
|
|
end
|
|
-- per sega a catena di fianco
|
|
if bChain and vtTool:getX() > -0.5 and vtTool:getZ() < 0.5 and vtArm:getX() > 0.5 then
|
|
dHeadFront = max( dHeadFront, 510)
|
|
end
|
|
-- per fresa diretta quasi esattamente come X1+/- e con la testa non troppo nel pezzo
|
|
if not bChain and abs( vtTool:getX()) < 0.017 and abs( vtTool:getZ()) < 0.017 and
|
|
(( vtTool:getY() > 0 and ptHeadMin:getY() > 80) or ( vtTool:getY() < 0 and ptHeadMax:getY() < -EMC.WIDTHBEAM - 80)) then
|
|
dHeadFront = 130
|
|
end
|
|
-- per limiti corsa asse X2
|
|
if not bChain then
|
|
dHeadFront = max( dHeadFront, -MaxX2 + 1 + vtTool:getX() * ( MillOffs + dTLen))
|
|
else
|
|
dHeadFront = max( dHeadFront, -MaxX2 + 1 + vtAux:getX() * ( MillOffs + dTDist) + vtTool:getX() * dTLen)
|
|
end
|
|
end
|
|
-- Stampe debug
|
|
EgtOutLog( ' Tdir=' .. tostring( vtTool) .. ' Adir=' .. tostring( vtArm) .. ' Zup=' .. EgtNumToString( dZup), 3)
|
|
EgtOutLog( ' DistFront=' .. EgtNumToString( dDistFront) .. ' DistBack=' .. EgtNumToString( dDistBack) ..
|
|
' HeadFront=' .. EgtNumToString( dHeadFront) .. ' HeadBack=' .. EgtNumToString( dHeadBack), 3)
|
|
-- Restituisco ingombri effettivi
|
|
dHeadFront = dHeadFront + 30
|
|
dHeadBack = dHeadBack + 30
|
|
return ( dDistFront - dHeadFront), ( dDistBack - dHeadBack)
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function VerifyPartLength()
|
|
|
|
-- Verifico lunghezza pezzo
|
|
if EMC.LENGTHBEAM < MinJoin + MinOther + AGG_LOAD + EMC.HCING + EMC.HOVM then
|
|
EgtOutLog( ' Error CLAMP -> pezzo troppo corto')
|
|
EMC.ERR = 17
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetLoadCmd( dPosT, dDistFront, dDistBack)
|
|
--[L]
|
|
local dMinDistBack= max( dDistBack, MinJoin + EgtIf( IsMid2Phase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE), EMC.TCING, 0))
|
|
local dNewX1Delta = max( EMC.LENGTHBEAM - dMinDistBack, MinOther + AGG_LOAD + EMC.HCING + EMC.HOVM)
|
|
local dNewX2Delta = nil
|
|
local dNewX1 = dPosT + TurnerOffs + dNewX1Delta
|
|
local vCmd = {}
|
|
EgtOutLog( ' *[L]', 1)
|
|
-- [L-1]
|
|
if dNewX1 - MaxX1 > 0 then
|
|
dNewX1Delta = min( EMC.LENGTHBEAM - MinJoin + AGG_LOAD, MaxX1 - dPosT - TurnerOffs)
|
|
EgtOutLog( ' *[L1]', 1)
|
|
end
|
|
--[L-2]
|
|
if EMC.LENGTHBEAM - dNewX1Delta < MinJoin then
|
|
dNewX1Delta = min( EMC.LENGTHBEAM - MinJoin + AGG_LOAD, MaxX1 - dPosT - TurnerOffs)
|
|
EgtOutLog( ' *[L2]', 1)
|
|
end
|
|
-- Commento
|
|
table.insert( vCmd, { 0, 'Loading'})
|
|
-- risalita testa a Zmax
|
|
vCmd = AddZmaxMove( vCmd)
|
|
-- Apro entrambe le morse
|
|
table.insert( vCmd, { 11, 0})
|
|
table.insert( vCmd, { 12, 0})
|
|
-- Sposto il carrello X1 per il carico
|
|
table.insert( vCmd, { 2, 'X1', dPosT + dNewX1Delta, 'X2', ParkX2})
|
|
-- Chiudo morsa X1
|
|
table.insert( vCmd, { 11, EgtIf( EMC.LENGTHBEAM - dNewX1Delta < LenToPress, 1, 2)})
|
|
-- confermo i nuovi parametri di aggancio
|
|
table.insert( vCmd, { 21, dNewX1Delta, 0})
|
|
-- Assegno stato corrente
|
|
EMC.TPOS = dPosT
|
|
EMC.X1DELTA = dNewX1Delta
|
|
EMC.X2DELTA = nil
|
|
-- Restituisco i comandi
|
|
return vCmd
|
|
end -- SpecAdjustLoad [L]
|
|
|
|
---------------------------------------------------------------------
|
|
function GetMachiningStartingPoint( idPath)
|
|
local idFirstObj = EgtGetFirstInGroup( idPath)
|
|
-- se esiste l'oggetto, recupero la coordinata del primo punto
|
|
if idFirstObj then
|
|
local vAxes = EmtGetAxesPos( idFirstObj)
|
|
if #vAxes > 0 then
|
|
return vAxes[1]
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function CalcCarriagesNewPositions( dDistFront, dDistBack)
|
|
local MinFrontJoin = MinJoin + EMC.HCING + EMC.HOVM
|
|
local MinBackJoin = MinJoin + EgtIf( IsMid2Phase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE), EMC.TCING, 0)
|
|
|
|
local dDistFrontEff = min( dDistFront, EMC.LENGTHBEAM - MinOther - EMC.TCING)
|
|
local dDistBackEff = min( dDistBack, EMC.LENGTHBEAM - MinOther - EMC.HCING - EMC.HOVM)
|
|
|
|
local dNewX1Delta = nil
|
|
local dNewX2Delta = nil
|
|
|
|
-- [A] se posso mettere solo carrello X1
|
|
if dDistFrontEff < MinFrontJoin and dDistBackEff > MinBackJoin - GEO.EPS_SMALL then
|
|
dNewX1Delta = EMC.LENGTHBEAM - dDistBackEff
|
|
dNewX2Delta = nil
|
|
-- [B] se altrimenti posso mettere entrambi i carrelli X1 e X2
|
|
elseif dDistBackEff > MinBackJoin - GEO.EPS_SMALL and dDistFrontEff > MinFrontJoin - GEO.EPS_SMALL then
|
|
dNewX1Delta = EMC.LENGTHBEAM - dDistBackEff
|
|
dNewX2Delta = dDistFrontEff
|
|
-- [C] se altrimenti posso mettere solo carrello X2
|
|
elseif dDistBackEff < MinBackJoin and dDistFrontEff > MinFrontJoin - GEO.EPS_SMALL then
|
|
dNewX2Delta = dDistFrontEff
|
|
dNewX1Delta = nil
|
|
-- altrimenti errore
|
|
else
|
|
if EgtGetDebugLevel() < 3 then
|
|
EgtOutLog( ' Dist/Min : Back=' .. EgtNumToString( dDistBackEff, 1) .. '/' .. EgtNumToString( MinBackJoin, 1) ..
|
|
' Front=' .. EgtNumToString( dDistFrontEff, 1) .. '/' .. EgtNumToString( MinFrontJoin, 1))
|
|
end
|
|
EgtOutLog( ' Error CLAMP impossible')
|
|
EMC.ERR = 18
|
|
return nil
|
|
end
|
|
return true, dNewX1Delta, dNewX2Delta
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetCarriagesCmdFromMachEncumbrance( dDistFront, dDistBack)
|
|
|
|
local bOk, dNewX1Delta, dNewX2Delta = CalcCarriagesNewPositions( dDistFront, dDistBack)
|
|
|
|
if not bOk then
|
|
return {}
|
|
end
|
|
|
|
local dPosT = EMC.TPOS
|
|
local dX1Delta = EMC.X1DELTA
|
|
local dX2Delta = EMC.X2DELTA
|
|
local dNewPosT
|
|
-- se sono già settati, non calcolo posizione finale
|
|
if not EMC.X1DELTANEXT and not EMC.X2DELTANEXT then
|
|
dNewPosT = GetMachiningStartingPoint( EMC.PATHID)
|
|
end
|
|
|
|
-- salvo valori finali
|
|
EMC.X1DELTANEXT = dNewX1Delta
|
|
EMC.X2DELTANEXT = dNewX2Delta
|
|
|
|
-- se la posizione è già corretta, no nserve riposizionare
|
|
local bCarriagesPosIsOK = true
|
|
|
|
local vCmd = {}
|
|
local bSpecialStartCarrInPos = false
|
|
if IsStartPhase( EMC.PHASE) and EMC.X1DELTA and not EMC.X2DELTA then
|
|
if EMC.X1DELTANEXT and EMC.X1DELTA > EMC.X1DELTANEXT and EMC.X2DELTA == nil and EMC.X2DELTANEXT == nil then
|
|
bSpecialStartCarrInPos = true
|
|
end
|
|
end
|
|
|
|
if not bSpecialStartCarrInPos then
|
|
if ( EMC.X1DELTA == nil and EMC.X1DELTANEXT) or ( EMC.X1DELTA and EMC.X1DELTANEXT == nil) then
|
|
bCarriagesPosIsOK = bCarriagesPosIsOK and false
|
|
end
|
|
if ( EMC.X1DELTA and EMC.X1DELTANEXT and abs( EMC.X1DELTA - EMC.X1DELTANEXT) > 1000 * GEO.EPS_SMALL) then
|
|
bCarriagesPosIsOK = bCarriagesPosIsOK and false
|
|
end
|
|
if ( EMC.X2DELTA == nil and EMC.X2DELTANEXT) or ( EMC.X2DELTA and EMC.X2DELTANEXT == nil) then
|
|
bCarriagesPosIsOK = bCarriagesPosIsOK and false
|
|
end
|
|
if ( EMC.X2DELTA and EMC.X2DELTANEXT and abs( EMC.X2DELTA - EMC.X2DELTANEXT) > 1000 * GEO.EPS_SMALL) then
|
|
bCarriagesPosIsOK = bCarriagesPosIsOK and false
|
|
end
|
|
end
|
|
|
|
|
|
if not bCarriagesPosIsOK then
|
|
GetCarriagesRepositioningCmd( vCmd, dPosT, dX1Delta, dX2Delta, dNewPosT, dNewX1Delta, dNewX2Delta)
|
|
end
|
|
|
|
return vCmd
|
|
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecCalcSplit( dLenRaw)
|
|
local vCmd = {}
|
|
EgtOutLog( ' *[S]', 1)
|
|
local bSplit = ( EMC.X2DELTA ~= nil)
|
|
local ParkT = LoadT
|
|
table.insert( vCmd, { 0, EgtIf( EMC.X2DELTA, 'Split', 'Fall')})
|
|
-- determino i grezzi da agganciare al carrello X1 (sono quelli presenti nella fase successiva dispari)
|
|
local nNextOddPhase = GetNextStartOrRestPhase( EMC.PHASE)
|
|
local nRawId = EgtGetFirstRawPart()
|
|
while nRawId do
|
|
if EgtVerifyRawPartPhase( nRawId, nNextOddPhase) then
|
|
table.insert( vCmd, { 31, nRawId, 'X1'})
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
-- riporto il carrello X1 al carico con il resto della trave
|
|
local dLDelta = EMC.X1DELTA - dLenRaw
|
|
table.insert( vCmd, { 1, 'X1', ParkT + dLDelta})
|
|
table.insert( vCmd, { 21, 0, EMC.X2DELTA or 0})
|
|
-- imposto subito X1 non più attaccato al trave in lavoro
|
|
EMC.X1DELTA = nil
|
|
-- salvo posizione carrello X1 in disposizione del pezzo dopo split
|
|
local PostDispId = EgtGetPhaseDisposition( EMC.PHASE + 1)
|
|
if PostDispId then
|
|
if not bSplit then
|
|
EgtSetInfo( PostDispId, 'TPOS', ParkT)
|
|
else
|
|
EgtRemoveInfo( PostDispId, 'TPOS')
|
|
EgtSetInfo( PostDispId, 'TPARK', ParkT)
|
|
end
|
|
EgtSetInfo( PostDispId, 'X1POS', ParkT + dLDelta)
|
|
end
|
|
-- salvo posizione grezzo rimasto e posizione carrello X1 nella disposizione iniziale del pezzo succ (prossima fase dispari)
|
|
local NextDispId = EgtGetPhaseDisposition( nNextOddPhase)
|
|
if NextDispId then
|
|
EgtSetInfo( NextDispId, 'TPOS', ParkT)
|
|
EgtSetInfo( NextDispId, 'X1POS', ParkT + dLDelta)
|
|
end
|
|
return vCmd
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecCalcSplitRot( dLenRaw)
|
|
local vCmd = {}
|
|
EgtOutLog( ' *[SR]', 1)
|
|
table.insert( vCmd, { 0, 'SplitRot'})
|
|
-- determino i grezzi da agganciare al carrello X1 (sono quelli presenti nella fase successiva dispari)
|
|
local vRaw = {}
|
|
local nNextOddPhase = GetNextStartOrRestPhase( EMC.PHASE)
|
|
local nRawId = EgtGetFirstRawPart()
|
|
while nRawId do
|
|
if EgtVerifyRawPartPhase( nRawId, nNextOddPhase) then
|
|
table.insert( vRaw, nRawId)
|
|
end
|
|
nRawId = EgtGetNextRawPart( nRawId)
|
|
end
|
|
for _, nId in ipairs( vRaw) do
|
|
table.insert( vCmd, { 31, nId, 'X1'})
|
|
end
|
|
-- riporto il carrello X1 al carico con il resto della trave
|
|
local dLDelta = EMC.X1DELTA - dLenRaw
|
|
table.insert( vCmd, { 1, 'X1', LoadT + TurnerOffs + dLDelta})
|
|
table.insert( vCmd, { 21, 0, EMC.X2DELTA})
|
|
-- imposto subito X1 non più attaccato alla trave in lavoro
|
|
EMC.X1DELTA = nil
|
|
-- apro il carrello X1
|
|
table.insert( vCmd, { 11, 0})
|
|
-- sgancio i grezzi dal carrello X1
|
|
for _, nId in ipairs( vRaw) do
|
|
table.insert( vCmd, { 31, nId, ''})
|
|
end
|
|
-- lo porto in parcheggio
|
|
table.insert( vCmd, { 1, 'X1', ParkX1})
|
|
-- salvo posizione grezzo rimasto nella disposizione iniziale del pezzo succ (prossima fase dispari)
|
|
local NextDispId = EgtGetPhaseDisposition( nNextOddPhase)
|
|
if NextDispId then
|
|
EgtSetInfo( NextDispId, 'TPOS', LoadT)
|
|
end
|
|
return vCmd
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecCalcUnload()
|
|
local vCmdPre = {}
|
|
EgtOutLog( ' *[U]', 1)
|
|
-- Se pinza X1 chiusa , devo effettuare uno scambio
|
|
if EMC.X1DELTA then
|
|
-- determino posizione testa trave
|
|
local nLastEntId = EgtGetLastInGroup( EMC.PATHID)
|
|
local vAxes = EmtGetAxesPos( nLastEntId)
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
local dX2CurrPos = EgtIf( EMC.X2DELTA, EMC.X2DELTA, EMC.TPOS + MaxX2)
|
|
local dX2LastPos = max( ( MinX2 + ( EMC.LENGTHBEAM - UnloadT)), EMC.X1DELTA - ( MinX1 - MaxX2))
|
|
EMC.X1DELTANEXT = nil
|
|
EMC.X2DELTANEXT = dX2LastPos
|
|
-- effettuo scambio
|
|
vCmdPre = GetCarriagesRepositioningCmd( vCmdPre, EMC.TPOS, EMC.X1DELTA, nil, nil, nil, dX2LastPos)
|
|
if EMC.ERR ~= 0 then
|
|
return {}
|
|
end
|
|
-- recupero nuova posizione carrelli
|
|
SpecSetCarrPosFromCmds( vCmdPre)
|
|
EgtOutLog( ' *[U1]', 1)
|
|
end
|
|
local vCmd = {}
|
|
-- Tipo di scarico
|
|
local bStdUl = ( MaxUnloadLen < 1 or EMC.LENGTHBEAM - EMC.HOVM < MaxUnloadLen + 1)
|
|
-- Commento
|
|
table.insert( vCmd, { 0, 'Unloading', EgtIf( bStdUl, 'Unloading', 'Manual Unloading')})
|
|
-- risalita testa a Zmax
|
|
vCmd = AddZmaxMove( vCmd)
|
|
-- Se pinza X1 chiusa, la apro
|
|
if EMC.X1DELTA then
|
|
table.insert( vCmd, { 11, 0})
|
|
end
|
|
-- Se non supero la lunghezza massima di scarico, sposto il pezzo in posizione di scarico
|
|
if bStdUl then
|
|
local dFinT = EgtIf( EMC.LENGTHBEAM < MaxLenSmT, UnloadSmT, UnloadT) - EMC.LENGTHBEAM
|
|
local dFinX2 = dFinT + EMC.X2DELTA
|
|
table.insert( vCmd, { 2, 'T', dFinT, 'X2', dFinX2})
|
|
else
|
|
table.insert( vCmd, { 1, 'X2', MaxX2})
|
|
end
|
|
-- apro la morsa
|
|
table.insert( vCmd, { 12, 0})
|
|
-- riporto il carrello in home
|
|
table.insert( vCmd, { 1, 'X2', ParkX2})
|
|
|
|
-- eventuale unione tabelle
|
|
if #vCmdPre > 0 then
|
|
vCmd = EgtJoinTables( vCmdPre, vCmd)
|
|
end
|
|
|
|
return vCmd
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecCalcPreRot()
|
|
local vCmdPre = {}
|
|
EgtOutLog( ' *[PR]', 1)
|
|
-- Se pinza X2 chiusa , devo effettuare uno scambio
|
|
if EMC.X2DELTA then
|
|
-- determino posizione testa trave
|
|
local nLastEntId = EgtGetLastInGroup( EMC.PATHID)
|
|
local vAxes = EmtGetAxesPos( nLastEntId)
|
|
if #vAxes > 0 then EMC.TPOS = vAxes[1] end
|
|
local dX1CurrPos = EgtIf( EMC.X1DELTA, EMC.X1DELTA, nil)
|
|
local dX1LastPos = min ( MaxX1 - LoadT, EMC.X2DELTA + ( MinX1 - MaxX2))
|
|
EMC.X1DELTANEXT = dX1LastPos
|
|
EMC.X2DELTANEXT = nil
|
|
-- effettuo scambio
|
|
vCmdPre = GetCarriagesRepositioningCmd( vCmdPre, EMC.TPOS, dX1CurrPos, EMC.X2DELTA, nil, dX1LastPos, nil)
|
|
-- recupero nuova posizione carrelli
|
|
SpecSetCarrPosFromCmds( vCmdPre)
|
|
EgtOutLog( ' *[PR1]', 1)
|
|
end
|
|
-- porto il pezzo alla zona di rotazione con il carro X1
|
|
local vCmd = {}
|
|
-- Commento
|
|
table.insert( vCmd, { 0, 'Pre-Rotation'})
|
|
-- risalita testa a Zmax
|
|
vCmd = AddZmaxMove( vCmd)
|
|
-- Se pinza X2 chiusa, la apro
|
|
if EMC.X2DELTA then
|
|
table.insert( vCmd, { 12, 0})
|
|
end
|
|
-- riporto la trave al carico
|
|
local RotT = LoadT + TurnerOffs - EMC.HOVM
|
|
table.insert( vCmd, { 2, 'X1', RotT + EMC.X1DELTA, 'T', RotT})
|
|
-- apro la morsa
|
|
table.insert( vCmd, { 11, 0})
|
|
-- riporto il carrello in home
|
|
table.insert( vCmd, { 1, 'X1', ParkX1})
|
|
|
|
-- dichiaro fine movimenti
|
|
table.insert( vCmd, { 0, 'Move_End'})
|
|
|
|
-- eventuale unione tabelle
|
|
if #vCmdPre > 0 then
|
|
vCmd = EgtJoinTables( vCmdPre, vCmd)
|
|
end
|
|
|
|
return vCmd
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
local function CalcCharStatus( sType, dDelta)
|
|
-- se per carrello X1
|
|
if sType == 'X1' then
|
|
return EgtIf( EMC.LENGTHBEAM - dDelta < LenToPress, 1, 2)
|
|
-- altrimenti per carrello X2
|
|
else
|
|
return EgtIf( dDelta < LenToPress, 1, 2)
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function GetCarriagesRepositioningCmd( vCmd, dTPosI, dX1DeltaI, dX2DeltaI, dTPosF, dX1DeltaF, dX2DeltaF)
|
|
local dX1PosA, dX2PosA, dTPosA
|
|
local dGainOnReclamping = BD.GAIN_RECLAMPING or 1000
|
|
|
|
-- se primo scambio
|
|
local MyMinX1 = MinX1
|
|
|
|
-- se pinza non in presa, setto offset minimo in base all'altra che sta pinzando
|
|
if not dX1DeltaI then
|
|
dX1DeltaI = dX2DeltaI + ( MyMinX1 - MaxX2)
|
|
end
|
|
if not dX2DeltaI then
|
|
dX2DeltaI = dX1DeltaI - ( MyMinX1 - MaxX2)
|
|
end
|
|
if not dX1DeltaF then
|
|
dX1DeltaF = dX2DeltaF + ( MyMinX1 - MaxX2)
|
|
end
|
|
if not dX2DeltaF then
|
|
dX2DeltaF = dX1DeltaF - ( MyMinX1 - MaxX2)
|
|
end
|
|
|
|
-- se non c'è posizione finale, è lo scarico. Allora setto al minimo della morsa allo scarico.
|
|
if not dTPosF then
|
|
dTPosF = MaxX2 - dX2DeltaF
|
|
end
|
|
|
|
-- se il pinzaggio deve essere invertito forzo entrata nei riposizionamenti
|
|
-- altrimenti posizioni iniziali e finali sono coincidenti dato che la pinza non in presa viene posizionata alla distanza minima a quella in presa
|
|
local bInvertClamping = not EMC.PILGRIMSTEP and EMC.X1DELTA ~= EMC.X1DELTANEXT and EMC.X2DELTA ~= EMC.X2DELTANEXT
|
|
-- verifico che le morse non sono in posizione
|
|
if ( abs( dX1DeltaF - dX1DeltaI) > 10 * GEO.EPS_SMALL or abs( dX2DeltaF - dX2DeltaI) > 10 * GEO.EPS_SMALL or bInvertClamping) and
|
|
( EMC.X1DELTA ~= EMC.X1DELTANEXT or EMC.X2DELTA ~= EMC.X2DELTANEXT) then
|
|
if #vCmd == 0 then
|
|
table.insert( vCmd, { 0, 'Clamp repositioning'})
|
|
-- risalita testa a Zmax
|
|
vCmd = AddZmaxMove( vCmd)
|
|
end
|
|
|
|
-- si ribadisce il pinzaggio
|
|
if EMC.X1DELTA then
|
|
table.insert( vCmd, { 11, 1})
|
|
end
|
|
if EMC.X2DELTA then
|
|
table.insert( vCmd, { 12, 1})
|
|
end
|
|
|
|
-- ricavo posizione delle morse nelle corse
|
|
local dX1PosI = max( MyMinX1, dTPosI + dX1DeltaI)
|
|
local dX2PosI = min( MaxX2, dTPosI + dX2DeltaI)
|
|
|
|
-- calcolo eventuale massimo riposizionamento con passo del pellegrino.
|
|
-- al primo step si calcolano posizioni attuali delle morse
|
|
-- al secondo step si considerano le corse massime
|
|
local dMaxMovePilgrimStepDoubleClamp, dMaxMovePilgrimStepSingleClampX1, dMaxMovePilgrimStepSingleClampX2
|
|
if not EMC.PILGRIMSTEP then
|
|
dMaxMovePilgrimStepDoubleClamp = MaxX1 - dX1PosI - MinX2 + dX2PosI
|
|
dMaxMovePilgrimStepSingleClampX1 = MaxX1 - dX1PosI
|
|
dMaxMovePilgrimStepSingleClampX2 = - MinX2 + dX2PosI
|
|
else
|
|
dMaxMovePilgrimStepDoubleClamp = MaxX1 - MinX1 - MinX2 + MaxX2
|
|
dMaxMovePilgrimStepSingleClampX1 = MaxX1 - MinX1
|
|
dMaxMovePilgrimStepSingleClampX2 = - MinX2 + MaxX2
|
|
end
|
|
|
|
-- calcolo delta spostamento trave
|
|
local dDeltaBeam = dTPosI - dTPosF -- se positivo, la trave si sposta dal carico allo scarico
|
|
local dBeamMove = 0
|
|
|
|
-- PRIMO CASO -> SCAMBIO DIRETTO : X2 IN POSIZIONE FINALE
|
|
-- X2 può andare in posizione direttamente se :
|
|
-- * rispetta interasse minimo con X1
|
|
-- * deve effettivamente spostarsi
|
|
-- * non si arriva da gestione passo del pellegrino
|
|
-- * se riesce a raggiungere la posizione con le corse a disposizione per come sono posizionate le morse attualmente
|
|
if ( dX1DeltaI - dX2DeltaF) + 10 * GEO.EPS_SMALL >= MyMinX1 - MaxX2 and
|
|
( abs( dX2DeltaF - dX2DeltaI) > 10 * GEO.EPS_SMALL or not EMC.X2DELTA) and
|
|
not EMC.PILGRIMSTEP and
|
|
( dX2DeltaF - dX2DeltaI > MinX2 - dX2PosI + MyMinX1 - dX1PosI) then
|
|
table.insert( vCmd, { 0, 'Direct-X2-X1'})
|
|
-- se l'altra morsa non era in presa, vado a pinzare il pezzo
|
|
if not EMC.X1DELTA then
|
|
dX1PosA = MyMinX1
|
|
dTPosA = MyMinX1 - dX1DeltaI
|
|
dX2PosA = dTPosA + dX2DeltaI
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI = dTPosA
|
|
dX2PosI = dX2PosA
|
|
table.insert( vCmd, { 11, 1})
|
|
end
|
|
|
|
-- se spostando morsa diretto esco dalle corse, calcolo di quanto devo muovere la trave (cioè l'altra morsa) come minimo
|
|
-- se non era ingaggiata, vado al suo minimo
|
|
if not EMC.X2DELTA then
|
|
dBeamMove = -( MaxX2 - dX2DeltaF - dTPosI)
|
|
-- se spostamento verso lo scarico
|
|
elseif ( dX2PosI + ( dX2DeltaF - dX2DeltaI)) < MinX2 then
|
|
dBeamMove = dX2PosI + ( dX2DeltaF - dX2DeltaI) - MinX2
|
|
-- se spostamento verso il carico
|
|
elseif ( dX2PosI + ( dX2DeltaF - dX2DeltaI)) > MaxX2 then
|
|
dBeamMove = dX2PosI + ( dX2DeltaF - dX2DeltaI) - MaxX2
|
|
-- se è FASTCLAMPING attivo, si suddivide il movimento
|
|
elseif BD.FASTCLAMPING then
|
|
-- se la trave si sposta dal carico verso lo scarico
|
|
if dTPosI - dTPosF > 0 then
|
|
dBeamMove = min( -( dTPosF - dTPosI), -( MyMinX1 - dX1PosI), -( dX2DeltaI - dX2DeltaF))
|
|
else
|
|
dBeamMove = max( -( dTPosF - dTPosI), -( MyMinX1 - dX1PosI))
|
|
end
|
|
dBeamMove = dBeamMove / 2
|
|
-- altrimenti la trave resta ferma e la pinza 1 va in presa (si limita lo scivolamento del pezzo)
|
|
else
|
|
;
|
|
end
|
|
-- se serve un grande spostamento e si sta pinzando poco. X1 trascinatore pinza poco e X2 si sposta per prima per recuperare
|
|
if not BD.FASTCLAMPING and abs( dBeamMove) > 2000 and dDeltaBeam < 0 and EMC.LENGTHBEAM - dX1DeltaI < max( 550, (MinJoin * 2)) then
|
|
table.insert( vCmd, { 12, 0})
|
|
dX2PosA = dX2PosI - dGainOnReclamping
|
|
-- sposto il carrello X2 di 1000mm
|
|
table.insert( vCmd, { 1, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, 1})
|
|
-- apro morsa X1 e recupero i 1000mm
|
|
table.insert( vCmd, { 11, 0})
|
|
dX2PosA = dX2PosI
|
|
dX1PosA = dX1PosI
|
|
dTPosA = dTPosI + dGainOnReclamping
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI = dTPosA
|
|
dX2PosI = dX2PosA
|
|
dX2DeltaI = dX2DeltaI - dGainOnReclamping
|
|
dX1DeltaI = dX1DeltaI - dGainOnReclamping
|
|
table.insert( vCmd, { 11, 1})
|
|
dBeamMove = dBeamMove + dGainOnReclamping
|
|
end
|
|
|
|
table.insert( vCmd, { 12, 0})
|
|
|
|
dTPosA = dTPosI - dBeamMove
|
|
dX1PosA = dTPosA + dX1DeltaI
|
|
dX2PosA = dTPosA + dX2DeltaF
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
|
|
-- la morsa allo scarico è adesso in posizione
|
|
dX2DeltaI = dX2DeltaF
|
|
dTPosI = dTPosA
|
|
|
|
-- blocco la morsa
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
|
|
-- imposto i nuovi parametri di aggancio
|
|
if EMC.X1DELTANEXT and EMC.X2DELTANEXT then
|
|
-- porto assi alla loro posizione finale
|
|
if abs( dX1DeltaF - dX1DeltaI) > 10 * GEO.EPS_SMALL then
|
|
table.insert( vCmd, { 11, 0})
|
|
dTPosA = dTPosF
|
|
dX1PosA = dTPosF + dX1DeltaF
|
|
dX2PosA = dTPosF + dX2DeltaF
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
-- la morsa al carico è adesso in posizione
|
|
dX1DeltaI = dX1DeltaF
|
|
end
|
|
table.insert( vCmd, { 21, dX1DeltaF, dX2DeltaF})
|
|
elseif EMC.X1DELTANEXT then
|
|
if abs( dX1DeltaF - dX1DeltaI) > 10 * GEO.EPS_SMALL then
|
|
table.insert( vCmd, { 11, 0})
|
|
dX1PosA = max( MyMinX1, dTPosI + dX1DeltaF)
|
|
dTPosA = dX1PosA - dX1DeltaF
|
|
dX2PosA = dTPosA + dX2DeltaF
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
-- la morsa al carico è adesso in posizione
|
|
dX1DeltaI = dX1DeltaF
|
|
end
|
|
table.insert( vCmd, { 12, 0})
|
|
-- sposto il carrello X2 in parcheggio
|
|
table.insert( vCmd, { 1, 'X2', ParkX2})
|
|
table.insert( vCmd, { 21, dX1DeltaF, 0})
|
|
else
|
|
table.insert( vCmd, { 11, 0})
|
|
table.insert( vCmd, { 1, 'X1', ParkX1})
|
|
table.insert( vCmd, { 21, 0, dX2DeltaF})
|
|
end
|
|
|
|
-- movimento terminato
|
|
dTPosI, dX1DeltaI, dX2DeltaI = dTPosF, dX1DeltaF, dX2DeltaF
|
|
EMC.X1DELTA = EMC.X1DELTANEXT
|
|
EMC.X2DELTA = EMC.X2DELTANEXT
|
|
|
|
-- SECONDO CASO -> SCAMBIO DIRETTO : X1 IN POSIZIONE FINALE
|
|
-- X1 può andare in posizione direttamente se :
|
|
-- * rispetta interasse minimo con X1
|
|
-- * deve effettivamente spostarsi
|
|
-- * non si arriva da gestione passo del pellegrino
|
|
-- * se riesce a raggiungere la posizione con le corse a disposizione per come sono posizionate le morse attualmente
|
|
elseif ( dX1DeltaF - dX2DeltaI) + 10 * GEO.EPS_SMALL >= MyMinX1 - MaxX2 and
|
|
( abs( dX1DeltaF - dX1DeltaI) > 10 * GEO.EPS_SMALL or not EMC.X1DELTA) and
|
|
not EMC.PILGRIMSTEP and
|
|
( dX1DeltaF - dX1DeltaI < MaxX1 - dX1PosI + MaxX2 - dX2PosI) then
|
|
table.insert( vCmd, { 0, 'Direct-X1-X2'})
|
|
-- se l'altra morsa non era in presa, vado a pinzare il pezzo
|
|
if not EMC.X2DELTA then
|
|
dX2PosA = MaxX2
|
|
dTPosA = MaxX2 - dX2DeltaI
|
|
dX1PosA = dTPosA + dX1DeltaI
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI = dTPosA
|
|
dX1PosI = dX1PosA
|
|
table.insert( vCmd, { 12, 1})
|
|
end
|
|
|
|
-- se spostando morsa diretto esco dalle corse, calcolo di quanto devo muovere la trave (cioè l'altra morsa) come minimo
|
|
-- se non era ingaggiata, vado al suo minimo
|
|
if not EMC.X1DELTA then
|
|
dBeamMove = - ( dX1DeltaF - MyMinX1 + dTPosI)
|
|
-- se spostamento verso lo scarico
|
|
elseif ( dX1PosI + ( dX1DeltaF - dX1DeltaI)) < MyMinX1 then
|
|
dBeamMove = -( dX1PosI + ( dX1DeltaF - dX1DeltaI) - MyMinX1)
|
|
-- se spostamento verso il carico
|
|
elseif ( dX1PosI + ( dX1DeltaF - dX1DeltaI)) > MaxX1 then
|
|
dBeamMove = -( dX1PosI + ( dX1DeltaF - dX1DeltaI) - MaxX1)
|
|
-- se è FASTCLAMPING attivo, si suddivide il movimento
|
|
elseif BD.FASTCLAMPING then
|
|
-- se la trave si sposta dal carico verso lo scarico
|
|
if dTPosI - dTPosF > 0 then
|
|
dBeamMove = max( ( dTPosF - dTPosI), ( MinX2 - dX2PosI), ( dX1DeltaI - dX1DeltaF))
|
|
else
|
|
dBeamMove = min( ( dTPosF - dTPosI), ( dX2PosI - MaxX2))
|
|
end
|
|
dBeamMove = dBeamMove / 2
|
|
-- altrimenti la trave resta ferma e la pinza 1 va in presa (si limita lo scivolamento del pezzo)
|
|
else
|
|
;
|
|
end
|
|
|
|
-- se serve un grande spostamento e si sta pinzando poco. X2 trascinatore pinza poco e X1 si sposta per prima per recuperare
|
|
if not BD.FASTCLAMPING and abs( dBeamMove) > 2000 and dDeltaBeam > 0 and dX2DeltaI < max( 550, (MinJoin * 2)) then
|
|
table.insert( vCmd, { 11, 0})
|
|
dX1PosA = dX1PosI + dGainOnReclamping
|
|
-- sposto il carrello X2 di 1000mm
|
|
table.insert( vCmd, { 1, 'X1', dX1PosA})
|
|
table.insert( vCmd, { 11, 1})
|
|
-- apro morsa X1 e recupero i 1000mm
|
|
table.insert( vCmd, { 12, 0})
|
|
dX2PosA = dX2PosI
|
|
dX1PosA = dX1PosI
|
|
dTPosA = dTPosI - dGainOnReclamping
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI = dTPosA
|
|
dX2PosI = dX2PosA
|
|
dX2DeltaI = dX2DeltaI + dGainOnReclamping
|
|
dX1DeltaI = dX1DeltaI + dGainOnReclamping
|
|
table.insert( vCmd, { 12, 1})
|
|
dBeamMove = dBeamMove - dGainOnReclamping
|
|
end
|
|
|
|
table.insert( vCmd, { 11, 0})
|
|
|
|
dTPosA = dTPosI + dBeamMove
|
|
dX1PosA = dTPosA + dX1DeltaF
|
|
dX2PosA = dTPosA + dX2DeltaI
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
|
|
-- la morsa al carico è adesso in posizione
|
|
dX1DeltaI = dX1DeltaF
|
|
dTPosI = dTPosA
|
|
|
|
-- blocco la morsa
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
|
|
-- imposto i nuovi parametri di aggancio
|
|
if EMC.X1DELTANEXT and EMC.X2DELTANEXT then
|
|
if abs( dX2DeltaF - dX2DeltaI) > 10 * GEO.EPS_SMALL then
|
|
table.insert( vCmd, { 12, 0})
|
|
dTPosA = dTPosF
|
|
dX1PosA = dTPosF + dX1DeltaF
|
|
dX2PosA = dTPosF + dX2DeltaF
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
-- la morsa al carico è adesso in posizione
|
|
dX2DeltaI = dX2DeltaF
|
|
end
|
|
table.insert( vCmd, { 21, dX1DeltaF, dX2DeltaF})
|
|
elseif EMC.X2DELTANEXT then
|
|
if abs( dX2DeltaF - dX2DeltaI) > 10 * GEO.EPS_SMALL then
|
|
table.insert( vCmd, { 12, 0})
|
|
dX2PosA = min( MaxX2, dTPosI + dX2DeltaF)
|
|
dTPosA = dX2PosA - dX2DeltaF
|
|
dX1PosA = dTPosA + dX1DeltaF
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
-- la morsa al carico è adesso in posizione
|
|
dX2DeltaI = dX2DeltaF
|
|
end
|
|
table.insert( vCmd, { 11, 0})
|
|
-- sposto il carrello X1 in parcheggio
|
|
table.insert( vCmd, { 1, 'X1', ParkX1})
|
|
table.insert( vCmd, { 21, 0, dX2DeltaF})
|
|
else
|
|
table.insert( vCmd, { 12, 0})
|
|
-- sposto il carrello X2 in parcheggio
|
|
table.insert( vCmd, { 1, 'X2', ParkX2})
|
|
table.insert( vCmd, { 21, dX1DeltaF, 0})
|
|
end
|
|
-- movimento terminato
|
|
dTPosI, dX1DeltaI, dX2DeltaI = dTPosF, dX1DeltaF, dX2DeltaF
|
|
EMC.X1DELTA = EMC.X1DELTANEXT
|
|
EMC.X2DELTA = EMC.X2DELTANEXT
|
|
|
|
-- TERZO CASO -> PASSO DEL PELLEGRINO
|
|
-- non è possibile fare scambio diretto.
|
|
-- le morse vengono compattate e allargate sfruttando tutta la corsa X, massimizzando spostamento trave
|
|
else
|
|
EMC.PILGRIMSTEP = false
|
|
local bUpdateValues = false
|
|
table.insert( vCmd, { 0, 'Pilgrim Cycle'})
|
|
-- compatto al centro
|
|
if not EMC.X1DELTA then
|
|
table.insert( vCmd, { 0, 'Compact X1'})
|
|
table.insert( vCmd, { 11, 0})
|
|
dTPosA = MaxX2 - dX2DeltaI
|
|
dX2PosA = MaxX2
|
|
dX1PosA = MyMinX1
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 11, 1})
|
|
dX1DeltaI = dX2DeltaI - MaxX2 + MyMinX1
|
|
EMC.X1DELTA = dX1DeltaI
|
|
bUpdateValues = true
|
|
end
|
|
if not EMC.X2DELTA then
|
|
table.insert( vCmd, { 0, 'Compact X2'})
|
|
table.insert( vCmd, { 12, 0})
|
|
dTPosA = MyMinX1 - dX1DeltaI
|
|
dX2PosA = MaxX2
|
|
dX1PosA = MyMinX1
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, 1})
|
|
dX2DeltaI = dX1DeltaI + MaxX2 - MyMinX1
|
|
EMC.X2DELTA = dX2DeltaI
|
|
bUpdateValues = true
|
|
end
|
|
|
|
-- se si sono compattate le morse, bisogna aggiornare le posizioni e i massimi recuperi
|
|
if bUpdateValues then
|
|
dTPosI = dTPosA
|
|
dX1PosI = dX1PosA
|
|
dX2PosI = dX2PosA
|
|
dMaxMovePilgrimStepDoubleClamp = MaxX1 - MinX1 - MinX2 + MaxX2
|
|
dMaxMovePilgrimStepSingleClampX1 = MaxX1 - MinX1
|
|
dMaxMovePilgrimStepSingleClampX2 = - MinX2 + MaxX2
|
|
end
|
|
|
|
-- aggiorno delta mancante
|
|
dDeltaBeam = dTPosI - dTPosF
|
|
|
|
-- a questo punto entrambe le pinze sono in presa sul pezzo.
|
|
-- trave si muove dal carico allo scarico
|
|
-- Il trascinatore si decide in base alla direzione di movimento trave
|
|
-- trascino con morsa allo scarico. Obiettivo mandare X1 in posizione per prima
|
|
if dDeltaBeam > 0 then
|
|
-- se serve un grande spostamento e si sta pinzando poco. X1 trascinatore pinza poco e X2 si sposta per prima per recuperare
|
|
if not BD.FASTCLAMPING and abs( dDeltaBeam) > 2000 and dX2DeltaI < max( 550, (MinJoin * 2)) then
|
|
table.insert( vCmd, { 11, 0})
|
|
dX1PosA = dX1PosI + dGainOnReclamping
|
|
-- sposto il carrello X2 di 1000mm
|
|
table.insert( vCmd, { 1, 'X1', dX1PosA})
|
|
table.insert( vCmd, { 11, 1})
|
|
-- apro morsa X1 e recupero i 1000mm
|
|
table.insert( vCmd, { 12, 0})
|
|
dX2PosA = dX2PosI
|
|
dX1PosA = dX1PosI
|
|
dTPosA = dTPosI - dGainOnReclamping
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI = dTPosA
|
|
dX2PosI = dX2PosA
|
|
dX2DeltaI = dX2DeltaI + dGainOnReclamping
|
|
dX1DeltaI = dX1DeltaI + dGainOnReclamping
|
|
table.insert( vCmd, { 12, 1})
|
|
end
|
|
|
|
-- apro morsa al carico
|
|
table.insert( vCmd, { 11, 0})
|
|
-- devo recuperare più delle corse disponibili di entrambi i carrelli
|
|
if abs( dX1DeltaI - dX1DeltaF) > dMaxMovePilgrimStepDoubleClamp then
|
|
dX1PosA = MaxX1
|
|
dX2PosA = MinX2
|
|
dTPosA = dTPosI - dX2PosI + MinX2
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 11, 1})
|
|
table.insert( vCmd, { 12, 0})
|
|
-- nuova posizione della morsa al carico dopo riposizionamento
|
|
dX1DeltaI = MaxX1 - dTPosA
|
|
dTPosI = dTPosA
|
|
EMC.X1DELTA = dX1DeltaI
|
|
EMC.X2DELTA = nil
|
|
EMC.PILGRIMSTEP = true
|
|
-- mi serve riposizonare di nuovo, quindi richiamo funzione in modo ricorsivo
|
|
vCmd = GetCarriagesRepositioningCmd( vCmd, dTPosI, dX1DeltaI, dX2DeltaI, dTPosF, dX1DeltaF, dX2DeltaF)
|
|
-- recupero una corsa massima e l'altra solo di quello che serve
|
|
elseif abs( dX1DeltaI - dX1DeltaF) > dMaxMovePilgrimStepSingleClampX2 then
|
|
-- suddivido il movimento su entrambe le morse
|
|
local dTotMove = ( dX1DeltaF - dX1DeltaI) / 2
|
|
-- morsa X1 arriva in posizione finale
|
|
dX2PosA = MaxX2 - dTotMove
|
|
dTPosA = dTPosI - dX2PosI + MaxX2 - dTotMove
|
|
dX1PosA = dX1DeltaF + dTPosA
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
table.insert( vCmd, { 12, 0})
|
|
dX1DeltaI = dX1DeltaF
|
|
dTPosI = dTPosA
|
|
EMC.X1DELTA = dX1DeltaF
|
|
EMC.X2DELTA = nil
|
|
-- mi serve riposizonare di nuovo, quindi richiamo funzione in modo ricorsivo
|
|
vCmd = GetCarriagesRepositioningCmd( vCmd, dTPosI, dX1DeltaI, dX2DeltaI, dTPosF, dX1DeltaF, dX2DeltaF)
|
|
-- non serve recuperare al massimo della corsa, suddivido movimento in due
|
|
else
|
|
-- suddivido il movimento su entrambe le morse
|
|
local dTotMove = ( dX1DeltaF - dX1DeltaI) / 2
|
|
|
|
if abs( dTotMove) > 10 * GEO.EPS_SMALL then
|
|
dX1PosA = dTPosI + dX1DeltaI + dTotMove
|
|
dX2PosA = dTPosI + dX2DeltaI - dTotMove
|
|
dTPosA = dTPosI - dTotMove
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
table.insert( vCmd, { 12, 0})
|
|
|
|
-- aggiorno nuova posizione della morsa al carico dopo riposizionamento
|
|
dX1DeltaI = dX1DeltaF ;
|
|
|
|
if not EMC.X2DELTANEXT then
|
|
dTPosA = dTPosF
|
|
dX1PosA = dTPosF + dX1DeltaF
|
|
dX2PosA = ParkX2
|
|
elseif EMC.X1DELTANEXT then
|
|
dTPosA = dTPosF
|
|
dX1PosA = dTPosF + dX1DeltaF
|
|
dX2PosA = dTPosF + dX2DeltaF
|
|
else
|
|
dX1PosA = MyMinX1
|
|
dTPosA = MyMinX1 - dX1DeltaF
|
|
dX2PosA = dTPosA + dX2DeltaF
|
|
end
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI, dX1DeltaI, dX2DeltaI = dTPosF, dX1DeltaF, dX2DeltaF
|
|
EMC.X1DELTA = EMC.X1DELTANEXT
|
|
EMC.X2DELTA = EMC.X2DELTANEXT
|
|
end
|
|
|
|
-- imposto i nuovi parametri di aggancio
|
|
if EMC.X1DELTANEXT and EMC.X2DELTANEXT then
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
table.insert( vCmd, { 21, dX1DeltaF, dX2DeltaF})
|
|
elseif EMC.X1DELTANEXT then
|
|
table.insert( vCmd, { 21, dX1DeltaF, 0})
|
|
else
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
table.insert( vCmd, { 11, 0})
|
|
-- sposto il carrello X1 in parcheggio
|
|
table.insert( vCmd, { 1, 'X1', ParkX1})
|
|
table.insert( vCmd, { 21, 0, dX2DeltaF})
|
|
end
|
|
end
|
|
-- trave si muove dallo scarico verso il carico. Obiettivo mandare X2 in posizione per prima
|
|
else
|
|
-- se serve un grande spostamento e si sta pinzando poco. X1 trascinatore pinza poco e X2 si sposta per prima per recuperare
|
|
if not BD.FASTCLAMPING and abs( dDeltaBeam) > 2000 and EMC.LENGTHBEAM - dX1DeltaI < max( 550, (MinJoin * 2)) then
|
|
table.insert( vCmd, { 12, 0})
|
|
dX2PosA = dX2PosI - dGainOnReclamping
|
|
-- sposto il carrello X2 di 1000mm
|
|
table.insert( vCmd, { 1, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, 1})
|
|
-- apro morsa X1 e recupero i 1000mm
|
|
table.insert( vCmd, { 11, 0})
|
|
dX2PosA = dX2PosI
|
|
dX1PosA = dX1PosI
|
|
dTPosA = dTPosI + dGainOnReclamping
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI = dTPosA
|
|
dX2PosI = dX2PosA
|
|
dX2DeltaI = dX2DeltaI - dGainOnReclamping
|
|
dX1DeltaI = dX1DeltaI - dGainOnReclamping
|
|
table.insert( vCmd, { 11, 1})
|
|
end
|
|
|
|
-- apro morsa allo scarico
|
|
table.insert( vCmd, { 12, 0})
|
|
-- devo recuperare più del doppio delle corse
|
|
local dMaxMoveFirst
|
|
if abs( dX2DeltaI - dX2DeltaF) > dMaxMovePilgrimStepDoubleClamp then
|
|
dX1PosA = MaxX1
|
|
dX2PosA = MinX2
|
|
dTPosA = dTPosI + ( MaxX1 - dX1PosI)
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, 1})
|
|
table.insert( vCmd, { 11, 0})
|
|
-- nuova posizione della morsa allo scarico dopo riposizionamento
|
|
dX2DeltaI = MinX2 - dTPosA
|
|
dTPosI = dTPosA
|
|
EMC.X1DELTA = nil
|
|
EMC.X2DELTA = dX2DeltaI
|
|
EMC.PILGRIMSTEP = true
|
|
-- mi serve riposizonare di nuovo, quindi richiamo funzione in modo ricorsivo
|
|
vCmd = GetCarriagesRepositioningCmd( vCmd, dTPosI, dX1DeltaI, dX2DeltaI, dTPosF, dX1DeltaF, dX2DeltaF)
|
|
-- recupero una corsa massima e l'altra solo di quello che serve
|
|
elseif abs( dX2DeltaI - dX2DeltaF) > dMaxMovePilgrimStepSingleClampX1 then
|
|
-- suddivido il movimento su entrambe le morse
|
|
local dTotMove = ( dX2DeltaI - dX2DeltaF) / 2
|
|
-- morsa X2 arriva in posizione finale
|
|
dX1PosA = MaxX1 + dTotMove
|
|
dTPosA = dTPosI + ( MaxX1 - dX1PosI) + dTotMove
|
|
dX2PosA = dX2DeltaF + dTPosA
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
table.insert( vCmd, { 11, 0})
|
|
dX2DeltaI = dX2DeltaF
|
|
dTPosI = dTPosA
|
|
EMC.X1DELTA = nil
|
|
EMC.X2DELTA = dX2DeltaF
|
|
-- mi serve riposizonare di nuovo, quindi richiamo funzione in modo ricorsivo
|
|
vCmd = GetCarriagesRepositioningCmd( vCmd, dTPosI, dX1DeltaI, dX2DeltaI, dTPosF, dX1DeltaF, dX2DeltaF)
|
|
-- non serve recuperare al massimo della corsa, suddivido movimento in due
|
|
else
|
|
-- suddivido il movimento su entrambe le morse
|
|
local dTotMove = ( dX2DeltaI - dX2DeltaF) / 2
|
|
|
|
if abs( dTotMove) > 10 * GEO.EPS_SMALL then
|
|
dX1PosA = dTPosI + dX1DeltaI + dTotMove
|
|
dX2PosA = dTPosI + dX2DeltaI - dTotMove
|
|
dTPosA = dTPosI + dTotMove
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
table.insert( vCmd, { 12, CalcCharStatus( 'X2', dX2DeltaF)})
|
|
table.insert( vCmd, { 11, 0})
|
|
|
|
-- aggiorno nuova posizione della morsa allo scarico dopo riposizionamento
|
|
dX2DeltaI = dX2DeltaF ;
|
|
|
|
if not EMC.X1DELTANEXT then
|
|
dTPosA = dTPosF
|
|
dX2PosA = dTPosF + dX2DeltaF
|
|
dX1PosA = ParkX1
|
|
elseif EMC.X2DELTANEXT then
|
|
dTPosA = dTPosF
|
|
dX1PosA = dTPosF + dX1DeltaF
|
|
dX2PosA = dTPosF + dX2DeltaF
|
|
else
|
|
dX2PosA = MaxX2
|
|
dTPosA = MaxX2 - dX2DeltaF
|
|
dX1PosA = dTPosA + dX1DeltaF
|
|
end
|
|
table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA})
|
|
dTPosI, dX1DeltaI, dX2DeltaI = dTPosF, dX1DeltaF, dX2DeltaF
|
|
EMC.X1DELTA = EMC.X1DELTANEXT
|
|
EMC.X2DELTA = EMC.X2DELTANEXT
|
|
|
|
end
|
|
|
|
-- imposto i nuovi parametri di aggancio
|
|
if EMC.X1DELTANEXT and EMC.X2DELTANEXT then
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
table.insert( vCmd, { 21, dX1DeltaF, dX2DeltaF})
|
|
elseif EMC.X1DELTANEXT then
|
|
table.insert( vCmd, { 11, CalcCharStatus( 'X1', dX1DeltaF)})
|
|
-- sposto il carrello X1 in parcheggio
|
|
table.insert( vCmd, { 12, 0})
|
|
table.insert( vCmd, { 1, 'X2', ParkX2})
|
|
table.insert( vCmd, { 21, dX1DeltaF, 0})
|
|
else
|
|
table.insert( vCmd, { 21, 0, dX2DeltaF})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return vCmd
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecOutputCmds( vCmd, bEnd)
|
|
|
|
local sRoot = EgtIf( not bEnd, 'AS', 'AE')
|
|
|
|
-- Registro il numero di comandi
|
|
if #vCmd > 0 then
|
|
EgtSetInfo( EMC.PATHID, sRoot..'#', #vCmd)
|
|
else
|
|
EgtRemoveInfo( EMC.PATHID, sRoot..'#')
|
|
end
|
|
-- Registro i comandi
|
|
for i = 1, #vCmd do
|
|
local Cmd = vCmd[i]
|
|
local sKey = sRoot..tostring( i)
|
|
-- commento
|
|
if Cmd[1] == 0 then
|
|
local sInfo = '0,'..Cmd[2]
|
|
if Cmd[3] then sInfo = sInfo..','..Cmd[3] end
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
-- movimento di 1 asse
|
|
elseif Cmd[1] == 1 then
|
|
local sInfo = '1,'..Cmd[2]..','..EgtNumToString( Cmd[3],3)
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
-- movimento di 2 assi
|
|
elseif Cmd[1] == 2 then
|
|
local sInfo = '2,'..Cmd[2]..','..EgtNumToString( Cmd[3],3)..','..Cmd[4]..','..EgtNumToString( Cmd[5],3)
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
-- movimento di 3 assi
|
|
elseif Cmd[1] == 3 then
|
|
local sInfo = '3,'..Cmd[2]..','..EgtNumToString( Cmd[3],3)..','..Cmd[4]..','..EgtNumToString( Cmd[5],3)..','..
|
|
Cmd[6]..','..EgtNumToString( Cmd[7],3)
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
-- apertura/chiusura morsa X1
|
|
elseif Cmd[1] == 11 then
|
|
local sInfo = '11,'..EgtNumToString( Cmd[2],0)
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
if Cmd[2] == 0 then EMC.X1DELTA = nil end
|
|
-- apertura/chiusura morsa X2
|
|
elseif Cmd[1] == 12 then
|
|
local sInfo = '12,'..EgtNumToString( Cmd[2],0)
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
if Cmd[2] == 0 then EMC.X2DELTA = nil end
|
|
-- impostazione nuovo stato dei carrelli
|
|
elseif Cmd[1] == 21 then
|
|
local sInfo = '21,'..EgtNumToString( Cmd[2],3)..','..EgtNumToString( Cmd[3],3)
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
if Cmd[2] > 0 and Cmd[3] > 0 then
|
|
EMC.X1DELTA = Cmd[2]
|
|
EMC.X2DELTA = Cmd[3]
|
|
elseif Cmd[2] > 0 then
|
|
EMC.X1DELTA = Cmd[2]
|
|
EMC.X2DELTA = nil
|
|
elseif Cmd[3] > 0 then
|
|
EMC.X1DELTA = nil
|
|
EMC.X2DELTA = Cmd[3]
|
|
end
|
|
-- aggancio grezzo a carrello
|
|
elseif Cmd[1] == 31 then
|
|
local sInfo = '31,'..EgtNumToString( Cmd[2],0)..','..Cmd[3]
|
|
EgtSetInfo( EMC.PATHID, sKey, sInfo)
|
|
end
|
|
end
|
|
|
|
-- gli ingombri della lavorazione sono sempre salvati
|
|
if EMC.DISTBACK then
|
|
EgtSetInfo( EMC.PATHID, 'DISTBACK', EMC.DISTBACK)
|
|
else
|
|
EgtRemoveInfo( EMC.PATHID, 'DISTBACK')
|
|
end
|
|
|
|
if EMC.DISTFRONT then
|
|
EgtSetInfo( EMC.PATHID, 'DISTFRONT', EMC.DISTFRONT)
|
|
else
|
|
EgtRemoveInfo( EMC.PATHID, 'DISTFRONT')
|
|
end
|
|
|
|
-- Salvo i nuovi delta dei carrelli
|
|
if EMC.X1DELTA then
|
|
EgtSetInfo( EMC.PATHID, 'X1DELTA', EMC.X1DELTA)
|
|
else
|
|
EgtRemoveInfo( EMC.PATHID, 'X1DELTA')
|
|
end
|
|
if EMC.X2DELTA then
|
|
EgtSetInfo( EMC.PATHID, 'X2DELTA', EMC.X2DELTA)
|
|
else
|
|
EgtRemoveInfo( EMC.PATHID, 'X2DELTA')
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecSetCarrPosFromCmds( vCmd)
|
|
-- recupero nuova posizione carrelli
|
|
for i = 1, #vCmd do
|
|
local Cmd = vCmd[i]
|
|
if Cmd[1] == 21 then
|
|
if Cmd[2] > 0 and Cmd[3] > 0 then
|
|
EMC.X1DELTA = Cmd[2]
|
|
EMC.X2DELTA = Cmd[3]
|
|
elseif Cmd[2] > 0 then
|
|
EMC.X1DELTA = Cmd[2]
|
|
EMC.X2DELTA = nil
|
|
elseif Cmd[3] > 0 then
|
|
EMC.X1DELTA = nil
|
|
EMC.X2DELTA = Cmd[3]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
function SpecTestOnlyRemarkInCmds( vCmd)
|
|
if not vCmd then return true end
|
|
-- verifico se nella lista dei comandi ci sono solo commenti
|
|
for i = 1, #vCmd do
|
|
if vCmd[i][1] ~= 0 then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|