-- Special Operations macchina Saomad-KAIROS by EgalWare s.r.l. 2023/12/01 -- Intestazioni require( 'EmtGenerator') EgtEnableDebug( false) -- Carico i dati globali local sBaseDir = EgtGetSourceDir() local BD = dofile( sBaseDir .. 'Beam\\BeamData.lua') ---------------------- OnSpecialMoveZup ----------------------------- --------------------------------------------------------------------- function OnSpecialMoveZup() --EgtOutLog( 'OnSpecialMoveZup : ' .. EMC.HEAD .. '.' .. tostring( EMC.EXIT)) -- Inizializzazioni EMC.ERR = 0 EMC.MODIF = false -- se sega a catena if EMC.HEAD == 'H3' then end end ---------- OnSpecialApplyDisposition & OnPostApplyMachining --------- ----------------------- Costanti ------------------------------------ local DELTA_TOL_V = 110 local DELTA_TOL_S = 160 local DELTA_TOL_L = 310 local DELTA_TOL_FIXED = 50 local DeltaTol = DELTA_TOL_S local DELTA_SIC = 1 local AGG_LOAD = 0 local MIN_JOIN_VV = 75 local MIN_JOIN_SS = 100 local MIN_JOIN_LS = 100 local MIN_JOIN_SL = 290 local MIN_JOIN_LL = 400 local MinJoin = MIN_JOIN_SS local MinOther = abs( MinX1) + abs( MaxX2) + MinJoin ----------------------- 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 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 UpdateMinJoinDeltaTol() local L_SMALL = 800 local H_V = 90 local H_S = 150 local H_L = 250 local W_V = 90 local W_S = 150 local W_L = 450 if EMC.SB <= W_V and EMC.HB <= H_V then MinJoin = MIN_JOIN_VV DeltaTol = DELTA_TOL_V elseif EMC.LB <= L_SMALL then MinJoin = MIN_JOIN_SS DeltaTol = DELTA_TOL_S else local dMinJoinS local dMinJoinL if EMC.SB <= W_S then dMinJoinS = MIN_JOIN_SS dMinJoinL = MIN_JOIN_LS elseif EMC.SB <= W_L then local Coeff = ( EMC.SB - W_S) / ( W_L - W_S) dMinJoinS = ( 1 - Coeff) * MIN_JOIN_SS + Coeff * MIN_JOIN_SL dMinJoinL = ( 1 - Coeff) * MIN_JOIN_LS + Coeff * MIN_JOIN_LL else dMinJoinS = MIN_JOIN_SL dMinJoinL = MIN_JOIN_LL end if EMC.HB <= H_S then MinJoin = dMinJoinS DeltaTol = DELTA_TOL_S elseif EMC.HB <= H_L then local Coeff = ( EMC.HB - H_S) / ( H_L - H_S) MinJoin = ( 1 - Coeff) * dMinJoinS + Coeff * dMinJoinL DeltaTol = ( 1 - Coeff) * DELTA_TOL_S + Coeff * DELTA_TOL_L else MinJoin = dMinJoinL DeltaTol = DELTA_TOL_L end if EMC.SB < W_V then DeltaTol = DELTA_TOL_V end end MinOther = abs( MinX1) + abs( MaxX2) + MinJoin 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 EnsureZmax( bZmaxOk, vCmd) if not bZmaxOk then table.insert( vCmd, { 1, 'Z', EgtGetAxisHomePos( 'Z')}) end return true 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 dPosY = EgtGetInfo( EMC.DISPID, 'YPOS', 'd') EMC.TPOS = dPosT EMC.YDELTA = dPosY - dPosT EMC.VDELTA = nil EMC.CNT = 1 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.YDELTA = EgtGetInfo( nLastPathId, 'YDELTA', 'd') EMC.VDELTA = EgtGetInfo( nLastPathId, 'VDELTA', 'd') EMC.CNT = EgtGetInfo( nLastPathId, 'CNT', 'i') 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.LB = 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.YDELTA = EgtGetInfo( nLastPathId, 'YDELTA', 'd') EMC.VDELTA = EgtGetInfo( nLastPathId, 'VDELTA', 'd') EMC.CNT = EgtGetInfo( nLastPathId, 'CNT', 'i') -- 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.LB = 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.LB = b3Raw:getDimX() + 10 * GEO.EPS_SMALL EMC.SB = b3Raw:getDimY() EMC.HB = b3Raw:getDimZ() EMC.ZMIN = b3Raw:getMin():getZ() -- Aggiorno limiti di presa e tolleranza UpdateMinJoinDeltaTol() -- Assegno sovramateriale di testa e ingombro tagli di testa e di coda EMC.HOVM = 0 EMC.HCING = 0 EMC.TCING = 0 -- Devo scaricare il grezzo rimasto (deve essere unico) -- Posizione trave local dPosT -- Se fase 1 o dopo rotazione eseguo carico con carrello Y local vCmd = {} if EMC.PHASE == 1 or IsEnd2Phase( EMC.PHASE) then dPosT = LoadT if IsEnd2Phase( EMC.PHASE) then dPosT = dPosT + TurnerOffs end vCmd = SpecCalcLoad( dPosT, 0, min( EMC.LB - 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 dPosY = EgtGetInfo( EMC.DISPID, 'YPOS', 'd') -- se carrello agganciato if dPosY then -- confermo i nuovi parametri di aggancio table.insert( vCmd, { 21, dPosY - 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) EMC.CNT = EgtGetInfo( nLastPathId, 'CNT', 'i') -- altrimenti è grezzo scaricato al carico e devo ricaricarlo else vCmd = SpecCalcLoad( dPosT, 0, min( EMC.LB - MinOther - AGG_LOAD, MaxX1 - dPosT)) end -- altrimenti fase successiva pari else local dPosV = EgtGetInfo( EMC.DISPID, 'VPOS', 'd') EMC.VDELTA = dPosV end -- Se fase inizio o rimanenza, eseguo scambio per avere solo pinza V local vCmd2 = {} if IsStartOrRestPhase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE) then EMC.TPOS = dPosT SpecSetCarrPosFromCmds( vCmd) local dDistFront = EgtIf( EMC.LB < abs( MinX2 - UnloadT), MinJoin, EMC.LB - abs( MinX2 - UnloadT) + MinJoin + DeltaTol) vCmd2 = SpecCalcCarriages( dDistFront, 0) 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() 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.YDELTA = nil EMC.VDELTA = nil EMC.HCING_IGNORE = true elseif IsStartOrRestPhase( EMC.PHASE) then -- carico le posizioni local dPosT = EgtGetInfo( nPrevOpeId, 'TPOS', 'd') local dPosY = EgtGetInfo( nPrevOpeId, 'YPOS', 'd') -- se carrello agganciato if dPosY then EMC.TPOS = dPosT EMC.YDELTA = dPosY - dPosT EMC.VDELTA = nil -- altrimenti è grezzo scaricato al carico e devo ricaricarlo else EMC.TPOS = nil EMC.YDELTA = nil EMC.VDELTA = 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.YDELTA = EgtGetInfo( nLastPathId, 'YDELTA', 'd') EMC.VDELTA = EgtGetInfo( nLastPathId, 'VDELTA', 'd') end EMC.CNT = nil -- 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.YDELTA = EgtGetInfo( nLastPathId, 'YDELTA', 'd') EMC.VDELTA = EgtGetInfo( nLastPathId, 'VDELTA', 'd') EMC.CNT = EgtGetInfo( nLastPathId, 'CNT', 'i') 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 OriYDelta = EMC.YDELTA local OriVDelta = EMC.VDELTA local OriCnt = EMC.CNT -- 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.YDELTA = OriYDelta EMC.VDELTA = OriVDelta EMC.CNT = OriCnt -- 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) -- Assegno flag di pezzo in separazione local bFixedDelta = ( bPreSplit or bSplitting or bPreCut or bCutting) -- Se separazione o taglio del grezzo finale, verifico se precedente era una preparazione local bFixedPos = false if bPreSplit or bSplitting or bPreCut or bCutting then local nPrevOpeId = EgtGetPrevActiveOperation( EMC.MCHID) bFixedPos = EgtExistsInfo( nPrevOpeId or GDB_ID.NULL, 'IS_PRE') end -- 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.LB = EgtIf( bSplit, b3Raw:getDimX(), b3Tot:getDimX()) + 10 * GEO.EPS_SMALL EMC.SB = b3Tot:getDimY() EMC.HB = b3Tot:getDimZ() EMC.LR = b3Raw:getDimX() + 10 * GEO.EPS_SMALL EMC.YMIN = b3Raw:getMin():getY() EMC.ZMIN = b3Raw:getMin():getZ() -- Aggiorno limiti di presa e tolleranza UpdateMinJoinDeltaTol() -- Recupero 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 EMC.XMAX = b3Raw:getMax():getX() - EMC.HOVM -- Calcolo dell'ingombro della lavorazione local dDistFront, dDistBack = SpecialCalcMachiningEncumbrance( EMC.MCHID, bPreCut) if not dDistFront or not dDistBack then return end if bPreSplit or bSplitting then local dDistF = SpecialCalcPhaseEncumbrance( 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 EgtOutLog( 'DistBack='..EgtNumToString( dDistBack)..' OtherBack='..EgtNumToString( dBackOther), 3) dDistBack = min( dDistBack, dBackOther) elseif bPreCut or bCutting then local dDistF = SpecialCalcPhaseEncumbrance( EMC.PHASE + 1) dDistFront = min( dDistFront, dDistF) dDistBack = 0.0 end -- Verifico lunghezza pezzo if not bSplit and not VerifyPartLength() then return end -- 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 = SpecCalcLoad( dPosT, dDistFront, max( dDistBack, MinJoin)) local vCmd2 = SpecCalcCarriages( dDistFront, dDistBack, bFixedDelta, bFixedPos) if vCmd2 and #vCmd2 > 1 then table.insert( vCmd, { 0, 'CARR_MOVE'}) end EgtJoinTables( vCmd, vCmd2) SpecOutputCmds( vCmd) -- Se altrimenti carri entrambi diponibili, eseguo calcoli per carrelli elseif not IsEndPhase( EMC.PHASE) then local vCmd = SpecCalcCarriages( dDistFront, dDistBack, bFixedDelta, bFixedPos) -- Se non ci sono spostamenti, confermo i parametri di aggancio if SpecTestOnlyRemarkInCmds( vCmd) then table.insert( vCmd, { 21, EgtIf( EMC.YDELTA, EMC.YDELTA, 0), EgtIf( EMC.VDELTA, EMC.VDELTA, 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') -- verifico se separazione con caduta if not EMC.VDELTA 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.YDELTA or not EMC.VDELTA then EMC.ERR = 19 EMC.MSG = ' Error SPLIT : Y or V not clamped' return false end -- eseguo la separazione ( standard o di pezzo ruotato) if not IsMid2Phase( EMC.PHASE + 1) then vCmd = SpecCalcSplit( b3Raw:getDimX()) else vCmd = SpecCalcSplitRot( b3Raw:getDimX()) end end -- Se taglio finale di grezzo a perdere if bCutting then -- salvo distanza carrello V da inizio grezzo rimasto nella disposizione della prossima fase local NextDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) if NextDispId then EgtSetInfo( NextDispId, 'VPOS', EMC.VDELTA) end end -- Se previsto scarico, lo eseguo if bUnload then EMC.LB = 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 SpecialCalcMachiningEncumbrance( 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 SpecialCalcPhaseEncumbrance( nPhase) -- Deve essere la fase finale di lavorazione di un pezzo (già staccato dal resto della trave) local dDistFront = EMC.LB local dDistBack = EMC.LB -- 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 = SpecialCalcMachiningEncumbrance( 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 --------------------------------------------------------------------- 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.SB, EMC.ZMIN) local ptHeadMax = ptMax + vtTool * dTLen - Vector3d( EMC.XMAX, EMC.YMIN + EMC.SB, EMC.ZMIN) -- Ingombro a sinistra local dDistBack = EMC.LB + 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 = 450 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.HB) 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 = 450 else dHeadBack = 650 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 = EgtIf( EMC.CNT == 1, 180, 130) elseif ( vtTool:getX() > -0.1 and vtArm:getX() > -0.95) then dHeadBack = 180 elseif ( vtTool:getX() < -0.8) then dHeadBack = 675 elseif ( vtTool:getX() < -0.75) then dHeadBack = 650 elseif ( vtTool:getX() < -0.5) then dHeadBack = 450 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( EgtIf( EMC.CNT == 1, 180, 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 = 510 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 = 500 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 Y+/- 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.SB - 80)) then dHeadBack = EgtIf( EMC.CNT == 1, 180, 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 = 450 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.HB) 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 = 650 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.8) then dHeadFront = 675 elseif ( vtTool:getX() > 0.75) then dHeadFront = 650 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 = 510 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 = 500 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 Y+/- 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.SB - 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 return ( dDistFront - dHeadFront), ( dDistBack - dHeadBack) end --------------------------------------------------------------------- function VerifyPartLength() -- Verifico lunghezza pezzo if EMC.LB < 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 SpecCalcLoad( dPosT, dDistFront, dDistBack) --[L] local dMinDistBack= max( dDistBack, MinJoin + EgtIf( IsMid2Phase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE), EMC.TCING, 0)) local dNewYDelta = max( EMC.LB - dMinDistBack, MinOther + AGG_LOAD + EMC.HCING + EMC.HOVM) local dNewVDelta = nil local dNewY = dPosT + TurnerOffs + dNewYDelta local vCmd = {} EgtOutLog( ' *[L]', 1) -- [L-1] if dNewY - MaxX1 > 0 then dNewYDelta = min( EMC.LB - MinJoin + AGG_LOAD, MaxX1 - dPosT - TurnerOffs) EgtOutLog( ' *[L1]', 1) end --[L-2] if EMC.LB - dNewYDelta < MinJoin then dNewYDelta = min( EMC.LB - MinJoin + AGG_LOAD, MaxX1 - dPosT - TurnerOffs) EgtOutLog( ' *[L2]', 1) end -- Commento table.insert( vCmd, { 0, 'Loading'}) -- risalita testa a Zmax local bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- Apro entrambe le morse table.insert( vCmd, { 11, 0}) table.insert( vCmd, { 12, 0}) -- Sposto il carrello Y per il carico table.insert( vCmd, { 2, 'X1', dPosT + dNewYDelta, 'X2', ParkX2}) -- Chiudo morsa Y table.insert( vCmd, { 11, EgtIf( EMC.LB - dNewYDelta < LenToPress, 1, 2)}) -- confermo i nuovi parametri di aggancio table.insert( vCmd, { 21, dNewYDelta, 0}) -- Inizializzo contatore globale EMC.CNT = 1 SpecOutputCNT() -- Assegno stato corrente EMC.TPOS = dPosT EMC.YDELTA = dNewYDelta EMC.VDELTA = nil -- Restituisco i comandi return vCmd end -- SpecAdjustLoad [L] --------------------------------------------------------------------- function SpecCalcCarriages( dDistFront, dDistBack, bFixedDelta, bFixedPos) local MinFrontJoin = MinJoin + EMC.HCING + EMC.HOVM local MinBackJoin = MinJoin + EgtIf( IsMid2Phase( EMC.PHASE) or IsEnd2Phase( EMC.PHASE), EMC.TCING, 0) local MyMinOther = MinOther + EgtIf( EMC.CNT == 1, AGG_LOAD, 0) local dDistFrontEff = min( dDistFront, EMC.LB - MyMinOther - EMC.TCING) if bFixedDelta and IsMid2Phase( EMC.PHASE + 1) then dDistFrontEff = min( dDistFrontEff, EMC.LR - MinOther - EMC.TCING) end local dDistBackEff = min( dDistBack, EMC.LB - MyMinOther - EMC.HCING - EMC.HOVM) EgtOutLog( ' Dist/Min : Back=' .. EgtNumToString( dDistBackEff, 1) .. '/' .. EgtNumToString( MinBackJoin, 1) .. ' Front=' .. EgtNumToString( dDistFrontEff, 1) .. '/' .. EgtNumToString( MinFrontJoin, 1) .. ' Fixed : Delta=' .. EgtIf( bFixedDelta, 'T', 'F') .. ' Pos=' .. EgtIf( bFixedPos, 'T', 'F'), 3) -- [A] se posso mettere solo carrello Y if dDistFrontEff < MinFrontJoin and dDistBackEff > MinBackJoin - GEO.EPS_SMALL then local dPosT = EMC.TPOS local dYDelta = EMC.YDELTA local dVDelta = EMC.VDELTA local dNewPosT = nil local dNewYDelta = EMC.LB - dDistBackEff local dNewVDelta = nil return SpecAdjustCarriages( dPosT, dYDelta, dVDelta, dNewPosT, dNewYDelta, dNewVDelta, bFixedDelta, bFixedPos) -- [B] se altrimenti posso mettere entrambi i carrelli Y e V elseif dDistBackEff > MinBackJoin - GEO.EPS_SMALL and dDistFrontEff > MinFrontJoin - GEO.EPS_SMALL then local dPosT = EMC.TPOS local dYDelta = EMC.YDELTA local dVDelta = EMC.VDELTA local dNewPosT = nil local dNewYDelta = EMC.LB - dDistBackEff local dNewVDelta = dDistFrontEff return SpecAdjustCarriages( dPosT, dYDelta, dVDelta, dNewPosT, dNewYDelta, dNewVDelta, bFixedDelta, bFixedPos) -- [C] se altrimenti posso mettere solo carrello V elseif dDistBackEff < MinBackJoin and dDistFrontEff > MinFrontJoin - GEO.EPS_SMALL then local dPosT = EMC.TPOS local dYDelta = EMC.YDELTA local dVDelta = EMC.VDELTA local dNewPosT = nil local dNewYDelta = nil local dNewVDelta = dDistFrontEff return SpecAdjustCarriages( dPosT, dYDelta, dVDelta, dNewPosT, dNewYDelta, dNewVDelta, bFixedDelta, bFixedPos) -- 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 {} end end --------------------------------------------------------------------- function SpecCalcSplit( dLenRaw) local vCmd = {} EgtOutLog( ' *[S]', 1) table.insert( vCmd, { 0, EgtIf( EMC.VDELTA, 'Split', 'Fall')}) -- determino i grezzi da agganciare al carrello Y (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 Y al carico con il resto della trave local dLDelta = EMC.YDELTA - dLenRaw table.insert( vCmd, { 1, 'X1', LoadT + dLDelta}) table.insert( vCmd, { 21, 0, EMC.VDELTA or 0}) -- imposto subito Y non più attaccato al trave in lavoro EMC.YDELTA = nil -- salvo posizione carrello Y in disposizione del pezzo dopo split local PostDispId = EgtGetPhaseDisposition( EMC.PHASE + 1) if PostDispId then EgtSetInfo( PostDispId, 'YPOS', LoadT + dLDelta) end -- salvo posizione grezzo rimasto e posizione carrello Y nella disposizione iniziale del pezzo succ (prossima fase dispari) local NextDispId = EgtGetPhaseDisposition( nNextOddPhase) if NextDispId then EgtSetInfo( NextDispId, 'TPOS', LoadT) EgtSetInfo( NextDispId, 'YPOS', LoadT + 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 Y (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 Y al carico con il resto della trave local dLDelta = EMC.YDELTA - dLenRaw table.insert( vCmd, { 1, 'X1', LoadT + TurnerOffs + dLDelta}) table.insert( vCmd, { 21, 0, EMC.VDELTA}) -- imposto subito Y non più attaccato alla trave in lavoro EMC.YDELTA = nil -- apro il carrello Y table.insert( vCmd, { 11, 0}) -- sgancio i grezzi dal carrello Y 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 Y chiusa , devo effettuare uno scambio if EMC.YDELTA then -- determino posizione testa trave local nLastEntId = EgtGetLastInGroup( EMC.PATHID) local vAxes = EmtGetAxesPos( nLastEntId) if #vAxes > 0 then EMC.TPOS = vAxes[1] end -- imposto quote aggancio per avere solo pinza V local dDistFront = EMC.LB - MinOther - EMC.TCING - 10 * GEO.EPS_SMALL local dDistBack = 0 -- effettuo scambio vCmdPre = SpecCalcCarriages( dDistFront, dDistBack) 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.LB - EMC.HOVM < MaxUnloadLen + 1) -- Commento table.insert( vCmd, { 0, 'Unloading', EgtIf( bStdUl, 'Unloading', 'Manual Unloading')}) -- risalita testa a Zmax local bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- Se pinza Y chiusa, la apro if EMC.YDELTA 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 = UnloadT - EMC.LB local dFinV = dFinT + EMC.VDELTA table.insert( vCmd, { 2, 'T', dFinT, 'X2', dFinV}) 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 V chiusa , devo effettuare uno scambio if EMC.VDELTA then -- imposto quote aggancio per avere solo pinza Y local dDistFront = 0 local dDistBack = EMC.LB - MinOther - EMC.HOVM + 10 * GEO.EPS_SMALL -- effettuo scambio vCmdPre = SpecCalcCarriages( dDistFront, dDistBack) -- recupero nuova posizione carrelli SpecSetCarrPosFromCmds( vCmdPre) EgtOutLog( ' *[PR1]', 1) end -- porto il pezzo alla zona di rotazione con il carro Y local vCmd = {} -- Commento table.insert( vCmd, { 0, 'Pre-Rotation'}) -- risalita testa a Zmax local bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- Se pinza V chiusa, la apro if EMC.VDELTA 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.YDELTA, 'T', RotT}) -- apro la morsa table.insert( vCmd, { 11, 0}) -- riporto il carrello in home table.insert( vCmd, { 1, 'X1', ParkX1}) -- eventuale unione tabelle if #vCmdPre > 0 then vCmd = EgtJoinTables( vCmdPre, vCmd) end return vCmd end --------------------------------------------------------------------- function SpecAdjustCarriages( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta, bFixedPos) -- [A] richiesto solo carrello Y if dYDeltaF and ( not dVDeltaF) then -- [A1] rimango sul carrello Y if dYDeltaI and ( not dVDeltaI) then return SpecAdjustCarrA1( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF) -- [A2] torno da entrambi elseif dYDeltaI and dVDeltaI then return SpecAdjustCarrA2( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF) -- [A3] torno da carrello V elseif dVDeltaI and (not dYDeltaI) then return SpecAdjustCarrA3( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF) else EgtOutLog( ' Error CLAMP NULL-> Y impossibile') error( 'Error CLAMP NULL-> Y impossibile') end -- (B) richiesti entrambi i carrelli elseif dYDeltaF and dVDeltaF then -- [B1] passo da carrello Y a entrambi if dYDeltaI and ( not dVDeltaI) then return SpecAdjustCarrB1( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) -- [B2] continuo con entrambi i carrelli elseif dYDeltaI and dVDeltaI then return SpecAdjustCarrB2( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) -- [B3] passo da carrello V a entrambi elseif dVDeltaI and (not dYDeltaI) then return SpecAdjustCarrB3( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) else EgtOutLog( ' Error CLAMP NULL-> Y+V impossibile') error( 'Error CLAMP NULL-> Y+V impossibile') end -- [C] richiesto solo carrello V elseif ( not dYDeltaF) and dVDeltaF then -- [C1] provengo da solo carrello Y if dYDeltaI and ( not dVDeltaI) then return SpecAdjustCarrC1( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) -- [C2] provengo da carrelli Y e V elseif dYDeltaI and dVDeltaI then return SpecAdjustCarrC2( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) -- [C3] rimango sul carrello V elseif ( not dYDeltaI) and dVDeltaI then return SpecAdjustCarrC3( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta, bFixedPos) else EgtOutLog( ' Error CLAMP NULL-> V impossibile') error( 'Error CLAMP NULL-> V impossibile') end end end --------------------------------------------------------------------- local function CalcCharStatus( sType, dDelta) -- se per carrello Y if sType == 'X1' then return EgtIf( EMC.LB - dDelta < LenToPress, 1, 2) -- altrimenti per carrello V else return EgtIf( dDelta < LenToPress, 1, 2) end end --------------------------------------------------------------------- local function GetDeltaTol( dLenPresa, TCING, HCING, HOVM, Carr, bFixedDelta) local dDeltaTolEff = DELTA_SIC if Carr == 'X1' then local dLenPreEff = dLenPresa - TCING if dLenPreEff < MinJoin + DeltaTol then dDeltaTolEff = max( DELTA_SIC, dLenPreEff - MinJoin + 10 * GEO.EPS_SMALL) else dDeltaTolEff = DeltaTol end elseif Carr == 'X2' then local dLenPreEff = dLenPresa - HCING - HOVM if dLenPreEff < MinJoin + DeltaTol then dDeltaTolEff = max( DELTA_SIC, dLenPreEff - MinJoin + 10 * GEO.EPS_SMALL) else dDeltaTolEff = DeltaTol end end return EgtIf( bFixedDelta, min( dDeltaTolEff, DELTA_TOL_FIXED), dDeltaTolEff) end --------------------------------------------------------------------- local function GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistN, sSide) local dRecTotn = min( dDistN, dCorsaYfc+ dCorsaVfc) -- recupero possibile al netto di dCorsa..TrA) local dCorsaYd, dCorsaYTd, dCorsaVd, dCorsaVTd if sSide == 'Fr' then if dRecTotn / 2 <= dCorsaYfc then if dRecTotn / 2 <= dCorsaVfc then dCorsaYTd = dRecTotn / 2 dCorsaVd = dRecTotn / 2 else dCorsaVd = dCorsaVfc dCorsaYTd = min( dCorsaYfc, dRecTotn - dCorsaVd) end else dCorsaYTd = dCorsaYfc dCorsaVd = min( dCorsaVfc, dRecTotn - dCorsaYTd) end dCorsaY = dCorsaYTd dCorsaV = dCorsaVd else if dRecTotn / 2 <= dCorsaVfc then if dRecTotn / 2 <= dCorsaYfc then dCorsaVTd = dRecTotn / 2 dCorsaYd = dRecTotn / 2 else dCorsaYd = dCorsaYfc dCorsaVTd = min( dCorsaVfc, dRecTotn - dCorsaYd) end else dCorsaVTd = dCorsaVfc dCorsaYd = min( dCorsaYfc, dRecTotn - dCorsaVTd) end dCorsaY = dCorsaYd dCorsaV = dCorsaVTd end return dCorsaY, dCorsaV end --------------------------------------------------------------------- local function PosxExtraYV( dX1PosA, dX2PosA, dTPosA, dMinX1, dMaxX2, sYV) -- svolge la predisposizione iniziale di trave e carrelli in caso di situazione iniziale con un solo carrello chiuso -- con un solo carrello chiuso per l'aggancio del carrello aperto local dX1Pos, dX2Pos, dTPos -- per aggancio del carrello X2 if sYV == 'X2' then dTPos = min( dTPosA, dX2PosA - MinJoin - EgtIf( EMC.HCING_IGNORE, 0, EMC.HCING) - EMC.HOVM) dX1Pos = dX1PosA + ( dTPos - dTPosA) if dX1Pos < dMinX1 then dX2Pos = dX2PosA + ( dMinX1 - dX1Pos) if dX2Pos > dMaxX2 + GEO.EPS_SMALL then EmitComment( vCmd, ' Error CLAMP X2') error( 'Error CLAMP X2') return elseif dX2Pos > dMaxX2 - GEO.EPS_SMALL then dX2Pos = dMaxX2 end dX1Pos = dMinX1 dTPos = dTPosA + ( dX1Pos - dX1PosA) else --dX1Pos = dMinX1 --dX1Pos = dX1Pos! --dTPos = dTPosA + ( dX1Pos - dX1PosA) --dTPos = dTPos! dX2Pos = dX2PosA end end -- per aggancio del carrello X1 if sYV == 'X1' then dTPos = max( dTPosA, dX1PosA + MinJoin + EMC.TCING - EMC.LB) dX2Pos = dX2PosA + ( dTPos - dTPosA) if dX2Pos > dMaxX2 then dX1Pos = dX1PosA - ( dX2Pos - dMaxX2) if dX1Pos < dMinX1 - GEO.EPS_SMALL then EmitComment( vCmd, ' Error CLAMP X1') error( 'Error CLAMP X1') return elseif dX1Pos < dMinX1 + GEO.EPS_SMALL then dX1Pos = dMinX1 end dX2Pos = dMaxX2 dTPos = dTPosA + ( dX2Pos - dX2PosA) else -- ++++++++++++++++++++++++++++++++ --dX2Pos = dMaxX2 --dX2Pos = dX2Pos! --dTPos = dTPosA + ( dX2Pos - dX2PosA) --dTpos = dTPos!! dX1Pos = dX1PosA end end return dX1Pos, dX2Pos, dTPos end --------------------------------------------------------------------- local function PosXs2Enl (dYa, dVa, dTa, dExtraC, dCorsaTra, dCorsaYd, dCorsaVd, sYV) -- svolge la fase di allontanamento dei carrelli per il recupero di 'ExtraX2'/'ExtraX1' -- richiesto alle posizioni [--.xs2] delle funzioni SpecAdjustCarr.. if sYV == 'X2' then -- caso di ExtraX2 (ed eventuale ulteriore allontanamento di X1) local dCorsaYTrA = dCorsaTra local dExtraX2n = dExtraC - dCorsaYTrA -- eseguo allontanamento di Y e (V+T) if dExtraX2n / 2 <= dCorsaYd then if dExtraX2n / 2 <= dCorsaVd then dYa = dYa + dExtraX2n / 2 dVa = dVa - dExtraX2n / 2 dTa = dTa - dExtraX2n / 2 else dVa = dVa - dCorsaVd dTa = dTa - dCorsaVd dYa = dYa + min( dExtraX2n - dCorsaVd, dCorsaYd) end else dYa = dYa + dCorsaYd dVa = dVa - min( dExtraX2n - dCorsaYd, dCorsaVd) dTa = dTa - min( dExtraX2n - dCorsaYd, dCorsaVd) end end if sYV == 'X1' then -- caso di ExtraX1 (ed eventuale ulteriore allontanamento di X2) local dCorsaVTrA = dCorsaTra local dExtraX1n = -dExtraC - dCorsaVTrA -- eseguo allontanamento di (Y+T) e V if dExtraX1n / 2 <= dCorsaVd then if dExtraX1n / 2 <= dCorsaYd then dVa = dVa - dExtraX1n / 2 dYa = dYa + dExtraX1n / 2 dTa = dTa + dExtraX1n / 2 else dYa = dYa + dCorsaYd dTa = dTa + dCorsaYd dVa = dVa - min( dExtraX1n - dCorsaYd, dCorsaVd) end else dVa = dVa - dCorsaVd dYa = dYa + min( dExtraX1n - dCorsaVd, dCorsaYd) dTa = dTa + min( dExtraX1n - dCorsaVd, dCorsaYd) end end return dYa, dVa, dTa end --------------------------------------------------------------------- -- *** [A1] da carrello X1 a X1 : X1 -> X1 *** --------------------------------------------------------------------- function SpecAdjustCarrA1( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF) EgtOutLog( ' *[A1] = X1 -> X1', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X1 -> X1'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) -- recupero le posizioni correnti dei carrelli local dX1PosA = dTPosI + dYDeltaI local dX2PosA = ParkX2 local dTPosA = dTPosI local dYDeltaA = dYDeltaI local dVDeltaA = dX2PosA - dTPosA local dNewYDelta -- = dYDeltaF local dCorsaYfc = MaxX1 - dX1PosA local dCorsaYd = min( dCorsaYfc, EMC.LB - dYDeltaI - MinJoin) -- tolleranza local dYDeltaTol = GetDeltaTol( EMC.LB - dYDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, 'X1') local bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) if bYDeltaS then dNewYDelta = dYDeltaF + dYDeltaTol / 4 else dNewYDelta = dYDeltaA end EgtOutLog( ' YDeltaI=' .. EgtNumToString( dYDeltaI) .. ' TPosI=' .. EgtNumToString( dTPosI), 1) EgtOutLog( ' YDeltaF=' .. EgtNumToString( dYDeltaF) .. ' NewYDelta=' .. EgtNumToString( dNewYDelta), 1) -- flag per risalita resta a Zmax local bZmaxOk = false -- **[A1Ys]** |pos. di Y cambia in modo significativo| if bYDeltaS then -- eventuale risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- definisco 'ExtraX1' con (Y+T) e V accentrati q.b. per la presa con V local dX1Pos, dX2Pos, dTPos = PosxExtraYV( dX1PosA, dX2PosA, dTPosA, MyMinX1, MaxX2, 'X2') local dNewY = dTPos + dNewYDelta local dExtraX1 = dNewY - MyMinX1 -- effettuo spostamenti di (Y+T) e V per predisporre all'aggancio di T con V dX1PosA = dX1Pos dX2PosA = dX2Pos dTPosA = dTPos table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dVDeltaA = dX2PosA - dTPosA -- **[A1Ys-x]** posizione di |Y non raggiungibile| (oltre MyMinX1) if dExtraX1 < 0 then -- **[A1Ys-xs]** posizione di Y non raggiungibile, |con ExtraX1 'significativo'| if -dExtraX1 > dYDeltaTol /2 then --EmitComment( vCmd, '[A1Ys-xs]') -- calcolo le **corse disponibili dei carrelli a partire da Y e V c.s.** per allontanare q.p. (Y+T) e V local dCorsaYfc = MaxX1 - dX1Pos local dCorsaVfc = dX2Pos - MinX2 local dDistFrN = (dX2Pos-dTPos) - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' local dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto **le corse di 'recupero'** dai due carrelli possibili riaccentrando Y e (V+T) local dCorsaVTr = dCorsaVd + (MaxX2 - dX2Pos) local dCorsaYr = dCorsaYTd -- **[A1Ys-xsw]** posizione finale dNewV non raggiungibile, con |dExtraX1 > CorsaVr + CorsaYr| if -dExtraX1 > ( dCorsaVTr + dCorsaYr) and bYDeltaS then EmitComment( vCmd, '[A1Ys-xsw]' .. 'CASO NON GESTITO') return end local dCorsaVTrA = MaxX2 - dX2Pos -- !! att.ne: non dX2PosA !! -- **[A1Ys-xs1]** se posso recuperare ExtraX1 semplicem' accentrando Y e (V+T) -- (dalle posizione impostate sopra per l'aggancio di V) if dCorsaVTrA >= -dExtraX1 then EmitComment( vCmd, '[A1Ys-xs1]') -- chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: accentro** Y e (V+T) dX1PosA = MyMinX1 -- (pos. finale) dX2PosA = dX2PosA + (-dExtraX1) dTPosA = dTPosA + (-dExtraX1) table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dYDeltaA = dX1PosA - dTPosA else -- **[A1Ys-xs2]** -- ci sarebbe un doppio movimento di Y ? => caso impossibile ? EmitComment( vCmd, '[A1Ys-xs2]') -- **1:** posiziono (ulteriormente!) (Y+T) e V dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX1, dCorsaVTrA, dCorsaYTd, dCorsaVd, 'X1') table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) dVDeltaA = dX2PosA - dTPosA -- chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **2: accentro** Y e (V+T) dX1PosA = MyMinX1 -- (pos. finale) dX2PosA = MaxX2 dTPosA = dX2PosA - dVDeltaA --dVDeltaA = dX2PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [A1Ys-xs1/-xs2] -- **[A1Ys-xn]** |dExtraX1 ancora < 0 ma non 'significativo')| else --if -dExtraX1 < DeltaToll/2 EmitComment( vCmd, '[A1Ys-xn]') -- chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1:** accentro Y dExtraX1 = 0 dX1PosA = MyMinX1 -- (pos. finale) table.insert( vCmd, { 1, 'X1', dX1PosA}) -- dYDeltaA = dX1PosA - dTPosA end --[A1Ys-xs/xn] -- **[A1Ys-r]** |posizione di Y raggiungibile| (ExtraX1 >=0) -- (si esclude la possibilità di extra corsa oltre maxX1) else EmitComment( vCmd, '[A1Ys-r]') -- chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1:** posiziono Y alla posizione richiesta dX1PosA = dNewY table.insert( vCmd, { 1, 'X1', dX1PosA}) end -- [A1Ys] -- calcolo il nuovo parametro di aggancio dYDeltaA = dX1PosA - dTPosA -- chiudo Y e apro V table.insert( vCmd, { 11, CalcCharStatus( 'X1', dYDeltaA)}) table.insert( vCmd, { 12, 0}) -- sposto il carrello V in parcheggio table.insert( vCmd, { 1, 'X2', ParkX2}) -- imposto il nuovo parametro di aggancio table.insert( vCmd, { 21, dYDeltaA, 0}) -- reset contatore EMC.CNT = nil else -- **[A1Yns]** |spostamento| finale richiesto (ev' residuo) di |Y non 'significativo'| EmitComment( vCmd, '[A1Yns]') end --[A1Ys/ns] EgtOutLog(' YDeltaA =' .. EgtNumToString( dYDeltaA), 1) SpecOutputCNT() return vCmd end --SpecAdjustCarrA1 --------------------------------------------------------------------- -- *** [A2] da entrambi a carrello X1 : X1+X2 -> X1 *** --------------------------------------------------------------------- function SpecAdjustCarrA2( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF) EgtOutLog( ' *[A2] = X1+X2 -> X1 ', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X1+X2 -> X1'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) local dCorsaY = MaxX1 - MyMinX1 local dCorsaV = MaxX2 - MinX2 -- recupero le posizioni correnti dei carrelli local dX1PosA = dTPosI + dYDeltaI local dX2PosA = dTPosI + dVDeltaI local dTPosA = dTPosI local dYDeltaA = dYDeltaI local dVDeltaA = dVDeltaI local dNewYDelta -- = dYDeltaF -- tolleranze local dYDeltaTol = GetDeltaTol( EMC.LB - dYDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, 'X1') local bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) if bYDeltaS then dNewYDelta = dYDeltaF + dYDeltaTol / 4 else dNewYDelta = dYDeltaA end -- definisco 'ExtraX1' local dNewY = dTPosA + dNewYDelta local dExtraX1 = dNewY - MyMinX1 -- < 0 = nuova pos. di Y 'non raggiungibile' (= oltre MyMinX1) -- definisco 'ExtraX1 significativo' local bYxs = -dExtraX1 > dYDeltaTol / 2 EgtOutLog( ' YDeltaI=' .. EgtNumToString( dYDeltaI) .. ' TPosI=' .. EgtNumToString( dTPosI) .. ' VDeltaI=' .. EgtNumToString( dVDeltaI), 1) EgtOutLog( ' YDeltaF=' .. EgtNumToString( dYDeltaF) .. ' NewYDelta=' .. EgtNumToString( dNewYDelta), 1) -- flag per risalita resta a Zmax local bZmaxOk = false -- risalita testa a Zmax (da effettuare comunque, per il parcheggio di V) bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- calcoli preliminari in caso di spostamento richiesto per Y significativo local dCorsaYfc, dCorsaVfc, dDistFrN, dCorsaYTd, dCorsaVd, dCorsaVTr, dCorsaYr, bXsw if bYDeltaS then if bYxs then -- calcolo le **corse disponibili** dei carrelli **a partire dalle posizioni attuali** (=iniziali) -- per allontanare q.p. (Y+T) e V dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto **le corse di 'recupero'** dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd + (MaxX2 - dX2PosA) dCorsaYr = dCorsaYTd bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaYr + dCorsaVTr end end -- **[A2Ys-xsw]** posizione NewY non raggiungibile (oltre MyMinX1), con ||dExtraX1 | > CorsaYr + CorsaVTr| while bXsw do EmitComment( vCmd, '[A2Ys-xsw]') -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- chiudo eventualmente il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1:** allontano q.p. (Y+T) e V dX1PosA = dX1PosA + dCorsaYTd dTPosA = dTPosA + dCorsaYTd dX2PosA = dX2PosA - dCorsaVd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **2:** accentro Y e (V+T) dX1PosA = MyMinX1 dX2PosA = dX2PosA + dCorsaVTr dTPosA = dTPosA + dCorsaVTr table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto Delta attuali dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) -- aggiorno l'extra corsa residua per Y dExtraX1 = dExtraX1 + dCorsaYr + dCorsaVTr bYxs = -dExtraX1 > dYDeltaTol/2 -- **aggiorno la valutazione delle corse disponibili** -- a partire da Y e V c.s. per allontanare q.p. (Y+T) e V dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd dCorsaYr = dCorsaYTd -- aggiorno verifica per ripetizione del ciclo bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end -- [A2Ys-xw] -- **[A2Ys]** se lo |spostamento| richiesto (ev' residuo) per |Y| è |'significativo'| if bYDeltaS then -- **[A2Ys-x]** se la |posizione per Y non è 'raggiungibile'| if dExtraX1 < 0 then -- **[A2Ys-xs]** se |ExtraX1 'significativo'| if bYxs then local dCorsaVTrA = MaxX2 - dX2PosA -- **[A2Ys-xs1]** se posso recuperare ExtraX1 solo accentrando (V+T) e Y if dCorsaVTrA >= -dExtraX1 then EmitComment( vCmd, '[A2Ys-xs1]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1:** accentro (V+T) q.b. e Y dX2PosA = dX2PosA + (-dExtraX1) dTPosA = dTPosA + (-dExtraX1) dX1PosA = MyMinX1 -- (pos. finale) --dYDeltaA = dX1PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) else -- **[A2Ys-xs2]** EmitComment( vCmd, '[A2Ys-xs2]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1:** allontano (Y+T) e V dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX1, dCorsaVTrA, dCorsaYTd, dCorsaVd, 'X1') table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) dVDeltaA = dX2PosA - dTPosA -- chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **2:** accentro Y e (V+T) q.b. per recupero di dExtraX1 dX1PosA = MyMinX1 dX2PosA = MaxX2 dTPosA = dX2PosA - dVDeltaA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end --[A2Ys-xs1/-xs2] -- [A2Ys-xn] |ExtraX1 ancora <= 0, ma 'non significativo'| else --if dExtraX1 <= 0 then EmitComment( vCmd, '[A2Ys-xn]') dExtraX1 = 0 -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- 1: accentro Y dX1PosA = MyMinX1 -- (pos. finale) table.insert( vCmd, { 1, 'X1', dX1PosA}) end -- [A2Ys-xs/xn] --[A2Ys-r] dExtraX2 > 0 ( |pos. Y'raggiungibile|) else EmitComment( vCmd, '[A2Ys-r]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- posizione Y dX1PosA = dTPosA + dNewYDelta -- (pos. finale) table.insert( vCmd, { 1, 'X1', dX1PosA}) end -- [A2Ys-x/r] else -- [A2Yns] |spostamento Y| (ev' residuo) |non significativo| EmitComment( vCmd, '[A2Yns]') end -- [A2Ys/ns] -- calcolo i nuovi parametri di aggancio dYDeltaA = dX1PosA - dTPosA -- chiudo ev' Y e apro V table.insert( vCmd, { 11, CalcCharStatus( 'X1', dYDeltaA)}) table.insert( vCmd, { 12, 0}) -- sposto il carrello V in parcheggio table.insert( vCmd, { 1, 'X2', ParkX2}) -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, dYDeltaA, 0}) EgtOutLog( ' YDeltaA =' .. EgtNumToString( dYDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end --SpecAdjustCarrA2 --------------------------------------------------------------------- -- *** [A3] da carrello X2 a X1 : X2 -> X1 *** --------------------------------------------------------------------- function SpecAdjustCarrA3( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF) EgtOutLog( ' *[A3] = X2 -> X1', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X2 -> X1'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) -- recupero le posizioni correnti local dX1PosA = ParkX1 local dTPosA = dTPosI local dX2PosA = dTPosI + dVDeltaI local dYDeltaA = dX1PosA - dTPosA local dVDeltaA = dVDeltaI local dNewYDelta -- = dVDeltaF -- tolleranza local dYDeltaTol = GetDeltaTol( EMC.LB - dYDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, 'X1') local bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) -- reimposto i delta finali in caso di spostamenti richiesti significativi, tenuto conto delle tolleranze if bYDeltaS then dNewYDelta = dYDeltaF + dYDeltaTol / 4 else dNewYDelta = dYDeltaA end -- EgtOutLog(' VDeltaI=' .. EgtNumToString( dVDeltaA) .. ' YDeltaI(Park)='.. EgtNumToString( dYDeltaA).. ' TPosI=' .. EgtNumToString( dTPosI) , 1) EgtOutLog(' YDeltaF=' .. EgtNumToString( dYDeltaF) .. ' NewYDelta=' .. EgtNumToString( dNewYDelta) , 1) local bZmaxOk = false -- risalita testa a Zmax (da effettuare comunque, dato lo scambio di carrelli) bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- calcoli preliminari in caso di spostamento richiesto per Y significativo local dX1Pos, dX2Pos, dTPos local dNewY, dExtraX1, bYxs local dCorsaYfc, dCorsaVfc, dDistFrN, dCorsaYTd, dCorsaVd, dCorsaVTr, dCorsaYr, bXsw if bYDeltaS then -- definisco 'ExtraX1' con Y e (V+T) accentrati q.b. per la presa con Y dX1Pos, dX2Pos, dTPos = PosxExtraYV( dX1PosA, dX2PosA, dTPosA, MyMinX1, MaxX2, 'X1') dNewY = dTPos + dNewYDelta dExtraX1 = dNewY - MyMinX1 --( <0 <=> pos. 'non raggiungibile') bYxs = -dExtraX1 > dYDeltaTol/2 if bYxs then -- calcolo le **corse disponibili dei carrelli a partire da Y e V c.s.** per allontanare q.p. (Y+T) e V dCorsaYfc = MaxX1 - dX1Pos dCorsaVfc = dX2Pos - MinX2 --local dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dDistFrN = (dX2Pos-dTPos) - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto **le corse di 'recupero'** dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd + (MaxX2 - dX2Pos) dCorsaYr = dCorsaYTd bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end -- inizializzo dX1PosA = dX1Pos dX2PosA = dX2Pos dTPosA = dTPos end -- **[A3Ys-xsw]** posizione finale dNewY non raggiungibile, con |dExtraX1 > CorsaVr + CorsaYr| while bXsw do EmitComment( vCmd, '[A3Ys-xsw]') -- |1:| posiziono (V+T) e Y come calcolato sopra table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo ev' il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- |2:| allontano (Y+T) e V quanto possibile dX1PosA = dX1PosA + dCorsaYTd dTPosA = dTPosA + dCorsaYTd dX2PosA = dX2PosA - dCorsaVd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |3:| accentro (V+T) e Y dX2PosA = dX2PosA + dCorsaVTr dTPosA = dTPosA + dCorsaVTr dX1PosA = MyMinX1 table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto i Delta ottenuti dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) -- aggiorno ExtraX1 dExtraX1 = dExtraX1 + dCorsaYr + dCorsaVTr -- **aggiorno la valutazione delle corse disponibili** -- a partire da Y e V c.s. per allontanare q.p. (Y+T) e V dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd dCorsaYr = dCorsaYTd -- aggiorno verifica per ripetizione del ciclo bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end --[A3Ys-xw] -- **[A3Ys]** |spostamento| richiesto (ev' residuo) |di Y| |'significativo'| if bYDeltaS then EmitComment( vCmd, '[A3Ys]') -- **[A3Ys-x]** posizione di |Y non raggiungibile| if dExtraX1 < 0 then -- **[A3Ys-xs]** |pos. NewY non raggiungibile, con ExtraX1 'significativo'| -- ( -dExtraX1 <= (CorsaYr+CorsaVr) da ciclo precedente ) if bYxs then local dCorsaVTrA = MaxX2 - dX2PosA -- **[A3Ys-xs1]** se posso recuperare ExtraX1 semplicem' accentrando Y e (V+T) -- ulteriormente rispetto a YPos e Vpos definiti c.s. if dCorsaVTrA >= -dExtraX1 then EmitComment( vCmd, '[A3Ys-xs1]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: accentro** Y e (V+T) dX1PosA = MyMinX1 -- (pos. finale) dX2PosA = dX2PosA - dExtraX1 dTPosA = dTPosA - dExtraX1 dYDeltaA = dX1PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) else -- **[A3Ys-xs2]** EmitComment( vCmd, '[A3Ys-xs2]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: accentro** ev' Y e (V+T) alle posizioni impostate table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dYDeltaA = dX1PosA - dTPosA -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2: allontano** (Y+T) e V dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX1, dCorsaVTrA, dCorsaYTd, dCorsaVd, 'X1') table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) dVDeltaA = dX2PosA - dTPosA -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **3: accentro** Y e (V+T) dX1PosA = MyMinX1 -- (pos. finale) dX2PosA = MaxX2 dTPosA = dX2PosA - dVDeltaA --dYDeltaA = dX1PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [A3Ys-xs1/-xs2] -- **[A3Ys-xn]** |dExtraX1 ancora < 0 ma non 'significativo')| else --if -dExtraX1 < DeltaToll/2 EmitComment( vCmd, '[A3Ys-xn]') -- ev' chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1:** accentro Y e porto (V+T) alla posizione impostata dExtraX1 = 0 dX1PosA = MyMinX1 -- (pos. finale) table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end --[A3Ys-xs/xn] -- **[A3Ys-r]** |posizione di Y raggiungibile (ExtraX1 >=0)| else EmitComment( vCmd, '[A3Ys-r]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- posizione Y in posizione finale ed ev' (V+T) come impostato sopra dX1PosA = dTPosA + dNewYDelta table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [A3Ys] else -- **[A3Yns]** |spostamento| finale richiesto (ev' residuo) di |Y non 'significativo'| EmitComment( vCmd, '[A3Yns]') end --[A3Ys/ns] -- calcolo il nuovo parametro di aggancio dYDeltaA = dX1PosA - dTPosA -- chiudo ev' Y e apro V table.insert( vCmd, { 11, CalcCharStatus( 'X1', dYDeltaA)}) table.insert( vCmd, { 12, 0}) -- sposto il carrello V in parcheggio table.insert( vCmd, { 1, 'X2', ParkX2}) -- imposto il nuovo parametro di aggancio table.insert( vCmd, { 21, dYDeltaA, 0}) EgtOutLog( ' YDeltaA =' .. EgtNumToString( dYDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end --SpecAdjustCarrA3 --------------------------------------------------------------------- local function AdjustPositionsForB( dNewYDelta, dNewVDelta, TCING, HCING, HOVM, bFixedDelta) local REF_DIST = 1400 local dYDelta = 0 local dVDelta = 0 -- incremento se possibile la distanza tra le due posizioni if not bFixedDelta and ( dNewYDelta - dNewVDelta) < REF_DIST then local dEffAddDist = ( REF_DIST - ( dNewYDelta - dNewVDelta)) / 2 dYDelta = max( min( dEffAddDist, EMC.LB - dNewYDelta - MinJoin - TCING), 0) dVDelta = max( min( dEffAddDist, dNewVDelta - MinJoin - HOVM - HCING), 0) end return dYDelta, dVDelta end --------------------------------------------------------------------- -- *** [B1] da carrello X1 a entrambi : X1 -> X1+X2 *** --------------------------------------------------------------------- function SpecAdjustCarrB1( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) EgtOutLog( ' *[B1] = X1 -> X1+X2', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X1 -> X1+X2'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) local dCorsaY = MaxX1 - MyMinX1 local dCorsaV = MaxX2 - MinX2 -- recupero le posizioni correnti local dX1PosA = dTPosI + dYDeltaI local dX2PosA = ParkX2 local dTPosA = dTPosI local dYDeltaA = dYDeltaI local dVDeltaA = dX2PosA - dTPosA local dNewYDelta local dNewVDelta -- incremento la distanza tra le due posizioni ( se abilitato e possibile) local dYDeltaAgg, dVDeltaAgg = AdjustPositionsForB( dYDeltaF, dVDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, bFixedDelta) -- tolleranze local dYDeltaTol = dYDeltaAgg + GetDeltaTol( EMC.LB - dYDeltaF - dYDeltaAgg, EMC.TCING, EMC.HCING, EMC.HOVM, 'X1', bFixedDelta) local dVDeltaTol = dVDeltaAgg + GetDeltaTol( dVDeltaF - dVDeltaAgg, EMC.TCING, EMC.HCING, EMC.HOVM, 'X2', bFixedDelta) -- definisco criteri per movimenti 'significativi' in base alle 'nuove' tolleranze local bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) local bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- reimposto i delta finali in caso di spostamenti richiesti significativi, tenuto conto delle tolleranze if bYDeltaS then dNewYDelta = dYDeltaF + dYDeltaTol / 2 else dNewYDelta = dYDeltaA end if bVDeltaS then dNewVDelta = dVDeltaF - dVDeltaTol / 2 else dNewVDelta = dVDeltaA end EgtOutLog(' YDeltaI=' .. EgtNumToString( dYDeltaA) .. ' VDeltaI(Park)='.. EgtNumToString( dVDeltaA) .. ' TPosI='.. EgtNumToString( dTPosI), 1) EgtOutLog(' YDeltaF=' .. EgtNumToString( dYDeltaF) .. ' VDeltaF=' .. EgtNumToString( dVDeltaF), 1) EgtOutLog(' NewYDelta=' .. EgtNumToString( dNewYDelta) .. ' NewVDelta=' .. EgtNumToString( dNewVDelta), 1) -- risalita testa a Zmax local bZmaxOk = false -- calcoli preliminari in caso di spostamento richiesto per V significativo local dX1Pos, dX2Pos, dTPos local dNewV, dExtraX2, bVxs local dCorsaYfc, dCorsaVfc, dDistBkN, dCorsaYd, dCorsaVTd, dCorsaYTr, dCorsaVr, bXsw if bVDeltaS then -- definisco 'ExtraX2' con (Y+T) e V accentrati q.b. per la presa di V dX1Pos, dX2Pos, dTPos = PosxExtraYV( dX1PosA, dX2PosA, dTPosA, MyMinX1, MaxX2, 'X2') dNewV = dTPos + dNewVDelta dExtraX2 = dNewV - MaxX2 -- se > 0 pos. V non direttamente 'raggiungibile' bVxs = dExtraX2 > dVDeltaTol/2 -- ExtraX2 'significativo' if bVxs then -- calcolo le **corse disponibili** dei carrelli a partire da Y e V c.s.| -- per allontanare q.p. Y e (V+T) dCorsaYfc = MaxX1 - dX1Pos dCorsaVfc = dX2Pos - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- valuto le **corse di 'recupero'** dai due carrelli possibili riaccentrando (Y+T) e V dCorsaYTr = dCorsaYd + (dX1Pos - MyMinX1) dCorsaVr = dCorsaVTd bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaVr + dCorsaYTr end -- inizializzo dX1PosA = dX1Pos dX2PosA = dX2Pos dTPosA = dTPos end -- **[B1Vs-xsw]** posizione finale dNewV non raggiungibile, con |dExtraX2 > CorsaVr + CorsaYr| while bXsw do EmitComment( vCmd, '[B1Vs-xsw]') -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- |1:| imposto (Y+T) e V come calcolato sopra table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |2:| allontano Y e (V+T) quanto possibile dX1PosA = dX1PosA + dCorsaYd dX2PosA = dX2PosA - dCorsaVTd dTPosA = dTPosA - dCorsaVTd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- |3:| accentro (Y+T) e V dX1PosA = dX1PosA - dCorsaYTr dTPosA = dTPosA - dCorsaYTr dX2PosA = MaxX2 table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto i Delta ottenuti dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- aggiorno l'extra corsa residuo per V dExtraX2 = dExtraX2 - dCorsaYTr - dCorsaVr -- **aggiorno la valutazione delle corse disponibili** -- a partire da Y e V c.s. per allontanare q.p. Y e (V+T) dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- aggiorno i prossimi recuperi disponibili dCorsaYTr = dCorsaYd dCorsaVr = dCorsaVTd -- aggiorno verifica per ripetizione del ciclo bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaVr + dCorsaYTr end --[B1Vs-xw] -- **[B1Vs]** se lo |spostamento| finale richiesto (ev' residuo) di |V| è |'significativo'| if bVDeltaS then -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- **[B1Vs-x]** posizione di |V non raggiungibile| if dExtraX2 > 0 then -- **[B1Vs-xs]** |ExtraX2 'signfificativo'| -- (ExtraX2 <= (CorsaYr+CorsaVr) da ciclo precedente ) if bVxs then local dCorsaYTrA = dX1PosA - MyMinX1 local dCorsaVra = MaxX2 - dX2PosA -- **[B1Vs-xs1]** se posso recuperare ExtraX2 semplicem' accentrando V e (Y+T) -- ulteriormente rispetto a YPos e Vpos definiti c.s. if dCorsaYTrA >= dExtraX2 then EmitComment( vCmd, '[B1Vs-xs1]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1: accentro** (Y+T) e V dX1PosA = dX1PosA - dExtraX2 dTPosA = dTPosA - dExtraX2 dX2PosA = MaxX2 -- (pos. finale) dVDeltaA = dX2PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) else -- **[B1Vs-xs2]** EmitComment( vCmd, '[B1Vs-xs2]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1: accentro** ev' (Y+T) e V alle posizioni impostate table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dVDeltaA = dX2PosA - dTPosA -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **2: allontano** (V+T) e Y -- tenendo conto di dover 'recuperare' ExtraX2.... local dX1Pos1, dX2Pos1, dTPos1 = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX2, dCorsaYTrA, dCorsaYd, dCorsaVTd, 'X2') local dYDispl1 = dX1Pos1 - dX1PosA local dVDispl1 = dX2Pos1 - dX2PosA --local dTDispl1 = dTPos1 - dTPosA local dYDeltaDiff = dNewYDelta - (dX1Pos1 - dTPos1) -- ...e anche di posizionare possibilmente Y alla posizione finale if dYDeltaDiff > 0 then dCorsaYfc = MaxX1 - dX1Pos1 dCorsaVfc = dX2Pos1 - MinX2 dDistBkN = EMC.LB - (dX1Pos1-dTPos1) - MinJoin - EMC.TCING -- DistBack1 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1Pos1, dX2Pos1, dTPos1, dYDeltaDiff, 0, dCorsaYd, dCorsaVTd, 'X2') else dX1PosA = dX1Pos1; dX2PosA = dX2Pos1; dTPosA = dTPos1 end table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **3: accentro** (Y+T) e V dX1PosA = dX1PosA - dYDispl1 - dCorsaYTrA -- POS. FINALE dTPosA = dTPosA - dYDispl1 - dCorsaYTrA dX2PosA = dX2PosA - dVDispl1 + dCorsaVra -- POS. FINALE table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B1Vs-xs1/-xs2] -- **[B1Vs-xn]** |dExtraX2 ancora > 0 ma non 'significativo')| else --if dExtraX2 < DeltaToll/2 EmitComment( vCmd, '[B1Vs-xn]') -- ev' chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- 1: accentro (Y+T) alla posizione impostate e V al max dExtraX2 = 0 dX2PosA = MaxX2 -- (pos. finale) table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B1s-xs/xn] -- **[B1Vs-r]** |dExtraX2 < 0 (pos. V raggiungibile)| else EmitComment( vCmd, '[B1Vs-r]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- posiziono ev' (Y+T) come impostato sopra e V in posizione finale dX2PosA = dTPosA + dNewVDelta table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B1Vs] dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA else -- **[B1Vns]** |spostamento| finale richiesto (ev' residuo) di |V non 'significativo'| EmitComment( vCmd, '[B1Vns]') if SpecTestOnlyRemarkInCmds( vCmd) then -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- emetto posizione di V table.insert( vCmd, { 1, 'X2', dX2PosA}) end end -- [B1-s/ns] -- aggiorno la verifica di movimento 'significativo' per Y bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) -- **[B1Ys]** Se vi è uno |spostamento residuo di Y significativo'| if bYDeltaS then EmitComment( vCmd, '[B1Ys]') -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) local dNewY = dTPosA + dNewYDelta local dExtraX1 = dNewY - MyMinX1 -- **[B1Ys-r]** se pos. NewY è raggiungibile direttamente if dExtraX1 >= 0 then --dNewY > MyMinX1 then EmitComment( vCmd, '[B1Ys-r]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- sposto il carrello Y dX1PosA = dTPosA + dNewYDelta table.insert( vCmd, { 1, 'X1', dX1PosA}) -- **[B1Ys-xn]** se pos. NewY non è raggiungibile direttamente, ma ExtraX1 non è 'significativo' elseif -dExtraX1 <= dYDeltaTol / 2 then EmitComment( vCmd, '[B1Ys-xn]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- accentro Y dX1PosA = MyMinX1 table.insert( vCmd, { 1, 'X1', dX1PosA}) -- [B1sY-nr.xs] ma ExtraX1 'significativo' else -- **[B1Ys-xs]** EmitComment( vCmd, '[B1Ys-xs]') EgtOutLog( ' CLAMP : caso [B1Ys-xs] non gestito') error( ' CLAMP : caso [B1Ys-xs] non gestito') end --[B1Ys-r/-nr] else -- [B1Yns] spostamento residuo di Y non significativo EmitComment( vCmd, '[B1Yns]') end -- [B1Ys/ns] -- calcolo i nuovi parametri di aggancio dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- se non emessi movimenti, imposto posizione V if not bZmaxOk then -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) table.insert( vCmd, { 1, 'X2', dX2PosA}) end -- imposto stato carrelli, per eventuale uso pressori (sempre eseguita risalita Z) table.insert( vCmd, { 11, CalcCharStatus( 'X1', dYDeltaA)}) table.insert( vCmd, { 12, CalcCharStatus( 'X2', dVDeltaA)}) -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, dYDeltaA, dVDeltaA}) EgtOutLog( ' YDeltaA =' .. EgtNumToString( dYDeltaA) .. ' VDeltaA =' .. EgtNumToString( dVDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end -- SpecAdjustCarrB1 --------------------------------------------------------------------- -- *** [B2] da entrambi a entrambi i carrelli : X1+X2 -> X1+X2 *** --------------------------------------------------------------------- function SpecAdjustCarrB2( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) EgtOutLog( ' *[B2] = X1+X2 -> X1+X2', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X1+X2 -> X1+X2'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) -- recupero le posizioni correnti local dX1PosA = dTPosI + dYDeltaI local dX2PosA = dTPosI + dVDeltaI local dTPosA = dTPosI local dYDeltaA = dYDeltaI local dVDeltaA = dVDeltaI local dNewYDelta local dNewVDelta -- incremento la distanza tra le due posizioni ( se abilitato e possibile) local dYDeltaAgg, dVDeltaAgg = AdjustPositionsForB( dYDeltaF, dVDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, bFixedDelta) -- tolleranze local dYDeltaTol = dYDeltaAgg + GetDeltaTol( EMC.LB - dYDeltaF - dYDeltaAgg, EMC.TCING, EMC.HCING, EMC.HOVM, 'X1', bFixedDelta) local dVDeltaTol = dVDeltaAgg + GetDeltaTol( dVDeltaF - dVDeltaAgg, EMC.TCING, EMC.HCING, EMC.HOVM, 'X2', bFixedDelta) -- definisco criteri per movimenti 'significativi' in base alle 'nuove' tolleranze local bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) local bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- reimposto i delta finali in caso di spostamenti richiesti significativi, tenuto conto delle tolleranze if bYDeltaS then dNewYDelta = dYDeltaF + dYDeltaTol / 2 else dNewYDelta = dYDeltaA end if bVDeltaS then dNewVDelta = dVDeltaF - dVDeltaTol / 2 else dNewVDelta = dVDeltaA end -- definisco 'ExtraX1' e ExtraX2' local dNewY = dTPosA + dNewYDelta local dNewV = dTPosA + dNewVDelta local dExtraX1 = dNewY - MyMinX1 -- < 0 => nuova pos. di Y 'non raggiungibile' local dExtraX2 = dNewV - MaxX2 -- > 0 => nuova pos. di V 'non raggiungibile' local bYxs = -dExtraX1 > dYDeltaTol/2 local bVxs = dExtraX2 > dVDeltaTol/2 EgtOutLog( ' YDeltaI=' .. EgtNumToString( dYDeltaI) .. ' VDeltaI=' .. EgtNumToString( dVDeltaI) .. ' TPosI='.. EgtNumToString( dTPosI), 1) EgtOutLog( ' YDeltaF=' .. EgtNumToString( dYDeltaF) .. ' VDeltaF=' .. EgtNumToString( dVDeltaF), 1) EgtOutLog( ' NewYDelta=' .. EgtNumToString( dNewYDelta) .. ' NewVDelta=' .. EgtNumToString( dNewVDelta), 1) -- flag risalita a Zmax local bZmaxOk = false -- **[B2V]** |accentramento di V| if dVDeltaF > dVDeltaI then EmitComment( vCmd, '[B2V]') -- calcoli preliminari in caso di spostamento richiesto per V significativo local dCorsaYfc, dCorsaVfc, dDistBkN, dCorsaYd, dCorsaVTd, dCorsaYTr, dCorsaVr, bXsw if bVDeltaS then -- eventuale risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) if bVxs then -- calcolo le corse disponibili dei carrelli **dalle posizioni iniziali** -- per allontanare Y e (V+T) dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- calcolo le corse di 'recupero' accentrando (Y+T) e V dopo l'allontanamento dCorsaYTr = dCorsaYd + (dX1PosA - MyMinX1) dCorsaVr = dCorsaVTd -- ((MaxX2-dNewV) non fa parte del recupero in quanto già disponibile!) bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaYTr + dCorsaVr end end -- **[B2V-xsw]** posizione NewV non raggiungibile, con |dExtraX2 > CorsaVr + CorsaYTr| -- e spostamento richiesto di V significativo; while bXsw do EmitComment( vCmd, '[B2V-xsw]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1**: allontano Y e V(+T) quanto possibile dX1PosA = dX1PosA + dCorsaYd dX2PosA = dX2PosA - dCorsaVTd dTPosA = dTPosA - dCorsaVTd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2:** accentro (Y+T) e V dX1PosA = dX1PosA - dCorsaYTr -- = MyMinX1 dTPosA = dTPosA - dCorsaYTr dX2PosA = MaxX2 table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto Delta ottenuti dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- aggiorno ExtraX2 residuo dExtraX2 = dExtraX2 - dCorsaYTr - dCorsaVr -- **aggiorno i recuperi disponibili** riallontanando Y e (V+T) e riaccentrando (Y+T) e V dCorsaYfc = dCorsaY -- MaxX1 - dNewY dCorsaVfc = dCorsaV -- dNewV - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') dCorsaYTr = dCorsaYd dCorsaVr = dCorsaVTd -- aggiorno verifica per ripetizione del ciclo bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaYTr + dCorsaVr end -- [B2V-xsw] --[B2Vs] |accentramento| (ev' residuo) |di V 'significativo'| if bVDeltaS then --[B2Vs-x] accentramento di V 'significativo' |con pos. NewV 'non raggiungibile'|(= oltre MaxX2) if dExtraX2 > 0 then -- (ExtraX2 <= (CorsaYTr+CorsaVr) da ciclo precedente) --[B2Vs-xs] accentramento di V con |ExtraX2 'significativo'| if bVxs then local dCorsaYTrA = dX1PosA - MyMinX1 local dCorsaVra = MaxX2 - dX2PosA -- **[B2Vs-xs1]** se posso recuperare ExtraX2 solo accentrando V e (Y+T) if dCorsaYTrA >= dExtraX2 then EmitComment( vCmd, '[B2Vs-xs1]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1:** accentro (Y+T) q.b. e V dX1PosA = dX1PosA - dExtraX2 dTPosA = dTPosA - dExtraX2 dX2PosA = MaxX2 -- (pos. finale) dExtraX2 = 0 table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) else -- **[B2Vs-xs2]** EmitComment( vCmd, '[B2Vs-xs2]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: allontano** (V+T) e Y -- tenendo conto di dover 'recuperare' ExtraX2... local dX1Pos1, dX2Pos1, dTPos1 = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX2, dCorsaYTrA, dCorsaYd, dCorsaVTd, 'X2') local dYDispl1 = dX1Pos1 - dX1PosA local dVDispl1 = dX2Pos1 - dX2PosA --local dTDispl1 = dTPos1 - dTPosA local dYDeltaDiff = dNewYDelta - (dX1Pos1 - dTPos1) -- ...e anche possibilmente di posizionare Y alla posizione finale if dYDeltaDiff > 0 then dCorsaYfc = MaxX1 - dX1Pos1 dCorsaVfc = dX2Pos1 - MinX2 dDistBkN = EMC.LB - (dX1Pos1-dTPos1) - MinJoin - EMC.TCING -- DistBack1 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') --dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1Pos1, dX2Pos1, dTPos1, dYDeltaDiff, 0, dCorsaYd-dYDispl1, dCorsaVTd+dVDispl1, 'X2') dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1Pos1, dX2Pos1, dTPos1, dYDeltaDiff, 0, dCorsaYd, dCorsaVTd, 'X2') else dX1PosA = dX1Pos1; dX2PosA = dX2Pos1; dTPosA = dTPos1 end table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2: accentro** (Y+T) e V dX1PosA = dX1PosA - dYDispl1 - dCorsaYTrA -- POS. FINALE dTPosA = dTPosA - dYDispl1 - dCorsaYTrA dX2PosA = dX2PosA - dVDispl1 + dCorsaVra -- POS. FINALE table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B2Vs-xs1/xs2] -- **[B2Vs-xn]** |dExtraX2 non 'significativo'| else EmitComment( vCmd, '[B2Vs-xn]') dExtraX2 = 0 -- ev' chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- 1: posiziono V assumendo maxX2 come pos. finale dX2PosA = MaxX2 -- (pos finale) table.insert( vCmd, { 1, 'X2', dX2PosA}) end -- [B2Vs-xs/xn] -- **[B2Vs-r]** accentramento di |V| 'significativo' con pos.|'raggiungibile'| (= non oltre MaxX2) else EmitComment( vCmd, '[B2Vs-r]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- 1: posiziono V -- (pos finale) dX2PosA = dTPosA + dNewVDelta dExtraX2 = 0 table.insert( vCmd, { 1, 'X2', dX2PosA}) end --[B2Vs] -- **[B2Vns]** accentramento di V non 'significativo'| else EmitComment( vCmd, '[B2Vns]') dExtraX2 = 0 end --[B2Vs/ns] end --[B2V] ( accentramento di V) -- --------------------------------------------------------------------------- -- **[B2Y]** |accentramento di Y| if dYDeltaF < dYDeltaI then EmitComment( vCmd, '[B2Y]') -- calcoli preliminari in caso di spostamento richiesto per Y significativo local dCorsaYfc, dCorsaVfc, dDistFrN, dCorsaYTd, dCorsaVd, dCorsaVTr, dCorsaYr if bYDeltaS then -- eventuale risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) if bYxs then -- calcolo le **corse disponibili** dei carrelli dalle posizioni iniziali -- per allontanare (Y+T) e V dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd + (MaxX2 - dX2PosA) dCorsaYr = dCorsaYTd bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end end -- **[B2Ys-xsw]** |-dExtraX1 > dCorsaYr + dCorsaVTr| while bXsw do EmitComment( vCmd, '[B2Y-xsw]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- |1:| allontano (Y+T) e V quanto possibile dX1PosA = dX1PosA + dCorsaYTd dTPosA = dTPosA + dCorsaYTd dX2PosA = dX2PosA - dCorsaVd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |2:| accentro Y e (V+T) dX1PosA = MyMinX1 -- = dX1PosA - dCorsaYr dX2PosA = dX2PosA + dCorsaVTr -- = MaxX2 dTPosA = dTPosA + dCorsaVTr table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto Delta 'attuali' dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- aggiorno ExtraX1 residuo dExtraX1 = dExtraX1 + dCorsaYr + dCorsaVTr -- aggiorno i recuperi disponibili riallontanando (Y+T) V e riaccentrando succ' Y e (V+T) dCorsaYfc = dCorsaY -- MaxX1 - dNewY dCorsaVfc = dCorsaV -- dNewV - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd dCorsaYr = dCorsaYTd -- aggiorno verifica per ripetizione del ciclo bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end -- [B2Ys-xsw] -- **[B2Ys]** |accentramento di Y 'significativo'| if bYDeltaS then -- **[B2Ys-x]** accentramento di Y 'significativo' |con pos. NewY 'non raggiungibile'|(= oltre MyMinX1) if dExtraX1 < 0 then -- (-ExtraX1 <= (dCorsaYr + dCorsaVTr ) a ciclo precedente -- **[B2Ys-xs]** accentramento di Y con |'ExtraX1 'significativo'| if bYxs then local dCorsaVTrA = MaxX2 - dX2PosA local dCorsaYra = dX1PosA - MyMinX1 -- **[B2Ys-xs1]** se posso recuperare ExtraX1 solo accentrando Y e (V+T) if dCorsaVTrA >= -dExtraX1 then EmitComment( vCmd, '[B2Ys-xs1]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- accentro Y e (V+T) q.b. dX1PosA = MyMinX1 -- (pos. finale) dX2PosA = dX2PosA - dExtraX1 -- = +(-dExtraX1) dTPosA = dTPosA - dExtraX1 -- = +(-dExtraX1) dExtraX1 = 0 table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) else -- **[B2Ys-xs2]** EmitComment( vCmd, '[B2Ys-xs2]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1: allontano** (Y+T) e V -- tenendo conto di dover 'recuperare' ExtraX1... dX1Pos1, dX2Pos1, dTPos1 = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX1, dCorsaVTrA, dCorsaYTd, dCorsaVd, 'X1') local dYDispl1 = dX1Pos1 - dX1PosA local dVDispl1 = dX2Pos1 - dX2PosA local dVDeltaDiff = dNewVDelta - (dX2Pos1 - dTPos1) -- ...e anche possibilmente di posizionare V alla posizione finale if dVDeltaDiff < 0 then dCorsaYfc = MaxX1 - dX1Pos1 dCorsaVfc = dX2Pos1 - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront1 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1Pos1, dX2Pos1, dTPos1, dVDeltaDiff, 0, dCorsaYTd, dCorsaVd, 'X1') else dX1PosA = dX1Pos1; dX2PosA = dX2Pos1; dTPosA = dTPos1 end table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) --dVDeltaA = dX2PosA - dTPosA -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |2:| accentro Y e (V+T) dX1PosA = dX1PosA - dYDispl1 - dCorsaYra -- POS. FINALE dX2PosA = dX2PosA - dVDispl1 + dCorsaVTrA -- POS. FINALE dTPosA = dTPosA - dVDispl1 + dCorsaVTrA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B2Ys-xs1/xs2] -- **[B2Ys-xn]** |dExtraX1 non 'significativo'| else EmitComment( vCmd, '[B2Ys-xn]') dExtraX1 = 0 -- ev' chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- 1: posiziono Y assumendo MyMinX1 come pos. finale dX1PosA = MyMinX1 -- (pos finale) table.insert( vCmd, { 1, 'X1', dX1PosA}) end -- [B2Ys-xs/xn] --[B2Ys-r] accentramento di |Y| 'significativo' con pos.|'raggiungibile'| (non oltre MyMinX1) else EmitComment( vCmd, '[B2Ys-r]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |1:| posiziono Y -- (pos finale) dX1PosA = dTPosA + dNewYDelta dExtraX2 = 0 table.insert( vCmd, { 1, 'X1', dX1PosA}) end --[B2Ys] -- [B2Yns] accentramento di V non 'significativo'| else EmitComment( vCmd, '[B2Yns]') dExtraX2 = 0 end --[B2Ys/ns] end --[B2Y] ( accentramento di V) -- ricalcolo gli 'spostamenti significativi' dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- ------------------------------------------------------------------------------------------ -- **[B2C]** |Spostamenti| di Y e/o V (ev' |residui| da cicli precedenti) -- ++ possono essere solo allontanamenti ? +++++++++++++++++++++ EmitComment( vCmd, '[B2C]') -- **[B2Cs]** se c'è uno |spostamento (ev' residuo) significativo| if bYDeltaS or bVDeltaS then -- **[B2CYs]** se lo |spostamento (ev' residuo) di Y è 'significativo'| if bYDeltaS then EmitComment( vCmd, '[B2CYs]') -- eventuale risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) local dNewY = dTPosA + dNewYDelta local dExtraX1 = dNewY - MyMinX1 -- **[B2CYs-r]** se posizione di |Y raggiungibile| if dExtraX1 >= 0 and dNewY <= MaxX1 then EmitComment( vCmd, '[B2CYs-r]') -- chiudo eventualmente V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- sposto il carrello Y dX1PosA = dNewY table.insert( vCmd, { 1, 'X1', dX1PosA}) -- **[B2CYs-nr]** else EmitComment( vCmd, '[B2CYs-nr]') EgtOutLog( ' CLAMP : posizione Y non raggiungibile' .. '- caso [B2Ys-nr] non gestito') error( 'CLAMP : posizione Y non raggiungibile') end end -- [B2CYs] -- **[B2CVs]** se lo |spostamento (ev' residuo) di V è 'significativo'| if bVDeltaS then EmitComment( vCmd, '[B2CVs]') -- eventuale risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) local dNewV = dTPosA + dNewVDelta local dExtraX2 = dNewV - MaxX2 -- **[B2CVs-r]** se posizione NewV raggiungibile if dExtraX2 <= 0 and dNewV >= MinX2 then EmitComment( vCmd, '[B2CVs-r]') -- chiudo eventualmente Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- sposto il carrello V dX2PosA = dNewV table.insert( vCmd, { 1, 'X2', dX2PosA}) -- **[B2CVs-nr]** else -- se ExtraX2 > 0 anche se non significativo EmitComment( vCmd, '[B2CVs-nr]') EgtOutLog( ' CLAMP : posizione V non raggiungibile' .. '- caso [B2cVs-nr] non gestito') error( 'CLAMP : posizione V non raggiungibile') end end --[B2CsV] -- **[B2Cn]** |nessuno spostamento (ev' residuo significativo)| else EmitComment( vCmd, '[B2Cn]') end -- [B2C] -- calcolo i nuovi parametri di aggancio dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- imposto stato carrelli, per eventuale uso pressori table.insert( vCmd, { 11, CalcCharStatus( 'X1', dYDeltaA)}) table.insert( vCmd, { 12, CalcCharStatus( 'X2', dVDeltaA)}) -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, dYDeltaA, dVDeltaA}) EgtOutLog( ' YDeltaA =' .. EgtNumToString( dYDeltaA) .. ' VDeltaA =' .. EgtNumToString( dVDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end --SpecAdjustCarrB2 --------------------------------------------------------------------------------------------------------- -- *** [B3] da carrello X2 a entrambi i carrelli : X2 -> X1+X2 *** --------------------------------------------------------------------------------------------------------- function SpecAdjustCarrB3( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) EgtOutLog( ' *[B3] = X2 -> X1+X2', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X2 -> X1+X2'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) local dCorsaY = MaxX1 - MyMinX1 local dCorsaV = MaxX2 - MinX2 -- recupero le posizioni correnti local dX2PosA = dTPosI + dVDeltaI local dX1PosA = ParkX1 local dTPosA = dTPosI local dVDeltaA = dVDeltaI local dYDeltaA = dX1PosA - dTPosA local dNewYDelta local dNewVDelta -- incremento la distanza tra le due posizioni ( se abilitato e possibile) local dYDeltaAgg, dVDeltaAgg = AdjustPositionsForB( dYDeltaF, dVDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, bFixedDelta) -- tolleranze local dYDeltaTol = dYDeltaAgg + GetDeltaTol( EMC.LB - dYDeltaF - dYDeltaAgg, EMC.TCING, EMC.HCING, EMC.HOVM, 'X1', bFixedDelta) local dVDeltaTol = dVDeltaAgg + GetDeltaTol( dVDeltaF - dVDeltaAgg, EMC.TCING, EMC.HCING, EMC.HOVM, 'X2', bFixedDelta) -- definisco criteri per movimenti 'significativi' in base alle 'nuove' tolleranze local bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) local bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- reimposto i delta finali in caso di spostamenti richiesti significativi, tenuto conto delle tolleranze if bYDeltaS then dNewYDelta = dYDeltaF + dYDeltaTol / 2 else dNewYDelta = dYDeltaA end if bVDeltaS then dNewVDelta = dVDeltaF - dVDeltaTol / 2 else dNewVDelta = dVDeltaA end EgtOutLog( ' YDeltaI(Park)='.. EgtNumToString( dYDeltaA)..' VDeltaI=' .. EgtNumToString( dVDeltaA) .. ' TPosI='.. EgtNumToString( dTPosI), 1) EgtOutLog( ' YDeltaF=' .. EgtNumToString( dYDeltaF) .. ' VDeltaF=' .. EgtNumToString( dVDeltaF), 1) EgtOutLog( ' NewYDelta=' .. EgtNumToString( dNewYDelta) .. ' NewVDelta=' .. EgtNumToString( dNewVDelta), 1) -- risalita testa a Zmax local bZmaxOk = false -- calcoli preliminari in caso di spostamento richiesto per Y significativo local dX1Pos, dX2Pos, dTPos local dNewY, dExtraX1, bYxs local dCorsaYfc, dCorsaVfc, dDistFrN, dCorsaYTd, dCorsaVd, dCorsaVTr, dCorsaYr, bXsw if bYDeltaS then -- definisco 'ExtraX1' con (V+T) e Y accentrati q.b. per la presa di Y dX1Pos, dX2Pos, dTPos = PosxExtraYV( dX1PosA, dX2PosA, dTPosA, MyMinX1, MaxX2, 'X1') dNewY = dTPos + dNewYDelta dExtraX1 = dNewY - MyMinX1 -- se < 0 pos. Y non direttamente 'raggiungibile' bYxs = -dExtraX1 > dYDeltaTol/2 -- ExtraX1 'significativo' if bYxs then -- calcolo le **corse disponibili dei carrelli a partire da Y e V c.s.** per allontanare q.p. (Y+T) e V dCorsaYfc = MaxX1 - dX1Pos dCorsaVfc = dX2Pos - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto **le corse di 'recupero'** dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd + (MaxX2 - dX2Pos) dCorsaYr = dCorsaYTd bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end -- inizializzo dX1PosA = dX1Pos dX2PosA = dX2Pos dTPosA = dTPos end -- **[B3Ys-xsw]** posizione finale dNewV non raggiungibile, con |dExtraX1 > CorsaVr + CorsaYr| while bXsw do EmitComment( vCmd, '[B3Ys-xsw]') -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- |1:| posiziono (V+T) e Y come calcolato sopra table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- |2:| allontano (Y+T) e V quanto possibile dX1PosA = dX1PosA + dCorsaYTd dTPosA = dTPosA + dCorsaYTd dX2PosA = dX2PosA - dCorsaVd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |3:| accentro (V+T) e Y dX2PosA = dX2PosA + dCorsaVTr dTPosA = dTPosA + dCorsaVTr dX1PosA = MyMinX1 table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto i Delta ottenuti dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bYDeltaS = ( dYDeltaF < dYDeltaA - dYDeltaTol or dYDeltaF > dYDeltaA + DELTA_SIC) bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- aggiorno ExtraX1 dExtraX1 = dExtraX1 + dCorsaYr + dCorsaVTr -- **aggiorno la valutazione delle corse disponibili** -- a partire da Y e V c.s. per allontanare q.p. (Y+T) e V dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando Y e (V+T) dCorsaVTr = dCorsaVd dCorsaYr = dCorsaYTd -- aggiorno verifica per ripetizione del ciclo bXsw = bYDeltaS and bYxs and -dExtraX1 > dCorsaVTr + dCorsaYr end --[B3Ys-xsw] -- **[B3Ys]** |spostamento| finale richiesto (ev' residuo) di |Y| |'significativo'| if bYDeltaS then EmitComment( vCmd, '[B3Ys]') -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- **[B3Ys-x]** posizione di |Y non raggiungibile| -- ( -dExtraX1 <= (CorsaYr+CorsaVr) da ciclo precedente ) if dExtraX1 < 0 then --EmitComment( vCmd, '[B3Ys-x]') -- **[B3Ys-xs]** |ExtraX1 'significativo'| if bYxs then --EmitComment( vCmd, '[B3Ys-xs]') local dCorsaVTrA = MaxX2 - dX2PosA local dCorsaYra = dX1PosA - MyMinX1 -- **[B3Ys-xs1]** se posso recuperare ExtraX1 semplicem' accentrando Y e (V+T) -- ulteriormente rispetto a YPos e Vpos definiti c.s. if dCorsaVTrA >= -dExtraX1 then EmitComment( vCmd, '[B3Ys-xs1]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: accentro** Y e (V+T) dX1PosA = MyMinX1 -- (pos. finale) dX2PosA = dX2PosA - dExtraX1 dTPosA = dTPosA - dExtraX1 dYDeltaA = dX1PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) else -- **[B3Ys-xs2]** EmitComment( vCmd, '[B3Ys-xs2]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: accentro** ev' Y e (V+T) alle posizioni impostate table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dYDeltaA = dX1PosA - dTPosA -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2: allontano** (Y+T) e V -- tenendo conto di dover 'recuperare' ExtraX1... dX1Pos1, dX2Pos1, dTPos1 = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX1, dCorsaVTrA, dCorsaYTd, dCorsaVd, 'X1') local dYDispl1 = dX1Pos1 - dX1PosA local dVDispl1 = dX2Pos1 - dX2PosA local dVDeltaDiff = dNewVDelta - (dX2Pos1 - dTPos1) -- ...e anche di posizionare possibilmente V alla posizione finale if dVDeltaDiff < 0 then CorsaYfc = MaxX1 - dX1Pos1 dCorsaVfc = dX2Pos1 - MinX2 dDistFrN = dVDeltaA - MinJoin - EMC.HCING - EMC.HOVM -- DistFront1 'netta' dCorsaYTd, dCorsaVd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistFrN, 'Fr') dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1Pos1, dX2Pos1, dTPos1, dVDeltaDiff, 0, dCorsaYTd, dCorsaVd, 'X1') else dX1PosA = dX1Pos1; dX2PosA = dX2Pos1; dTPosA = dTPos1 end table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) -- chiudo il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **3: accentro** Y e (V+T) dX1PosA = dX1PosA - dYDispl1 - dCorsaYra -- POS. FINALE dX2PosA = dX2PosA - dVDispl1 + dCorsaVTrA -- POS. FINALE dTPosA = dTPosA - dVDispl1 + dCorsaVTrA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B3Ys-xs1/-xs2] -- **[B3Ys-xn]** |dExtraX1 ancora < 0 ma non 'significativo')| else --if -dExtraX1 < DeltaToll/2 EmitComment( vCmd, '[B3Ys-xn]') -- ev' chiudo V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- 1: accentro Y e porto (V+T) alla posizione impostata dExtraX1 = 0 dX1PosA = MyMinX1 -- (pos. finale) table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end --[B3Ys-xs/xn] -- **[B3Ys-r]** |dExtraX1 > 0 (pos. Y raggiungibile)| else EmitComment( vCmd, '[B3Ys-r]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- posizione ev' (V+T) come impostato sopra e Y in posizione finale dX1PosA = dTPosA + dNewYDelta table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [B3Ys] -- dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA else -- [B3Yns] |spostamento| finale richiesto (ev' residuo) di |Y non 'significativo'| EmitComment( vCmd, '[B3Yns]') end --[B3Ys/ns] -- aggiorno la verifica di movimento 'significativo' per V bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- **[B3Vs]** Se vi è uno |spostamento residuo di V significativo'| if bVDeltaS then EmitComment( vCmd, '[B3Vs]') -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) local dNewV = dTPosA + dNewVDelta local dExtraX2 = dNewV - MaxX2 -- **[B3Vs-x]** se pos. |NewV non è raggiungibile direttamente| (oltre MaxX2) if dExtraX2 > 0 then --dNewV <= MaxX2 then -- **[B3Vs-xs]** |ExtraX2 'significativo'| if dExtraX2 > dVDeltaTol /2 then EmitComment( vCmd, '[B3Vs-xs]') EgtOutLog( ' CLAMP : caso [B3Vs-xs] non gestito') error( ' CLAMP : caso [B3Vs-xs] non gestito') -- **[B3Vs-xn]** |ExtraX2 non 'significativo'| else EmitComment( vCmd, '[B3Vs-xn]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- accentro V q.p. dX2PosA = MaxX2 table.insert( vCmd, { 1, 'X2', dX2PosA}) end -- [B3Vs-xs/xn] else -- **[B3Vs-r]** pos. |NewV raggiungibile direttamente| (non oltre MaxX2) EmitComment( vCmd, '[B3Vs-r]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- sposto il carrello V dX2PosA = dNewV table.insert( vCmd, { 1, 'X2', dX2PosA}) end --[B3Vs-x/-r] else -- [B3Vns] spostamento residuo di V non significativo EmitComment( vCmd, '[B3Vns]') end -- [B3Vs/ns] -- calcolo i nuovi parametri di aggancio dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- se non emessi movimenti, imposto posizione Y if not bZmaxOk then -- risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) table.insert( vCmd, { 1, 'X1', dX1PosA}) end -- imposto stato carrelli, per eventuale uso pressori (sempre effettuato movimento) table.insert( vCmd, { 11, CalcCharStatus( 'X1', dYDeltaA)}) table.insert( vCmd, { 12, CalcCharStatus( 'X2', dVDeltaA)}) -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, dYDeltaA, dVDeltaA}) EgtOutLog( ' YDeltaA =' .. EgtNumToString( dYDeltaA) .. ' VDeltaA =' .. EgtNumToString( dVDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end -- SpecAdjustCarrB3 --------------------------------------------------------------------- -- *** [C1] da carrello X1 a X2 : X1 -> X2 *** --------------------------------------------------------------------- function SpecAdjustCarrC1( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) EgtOutLog( ' *[C1] = X1 -> X2 ', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X1 -> X2'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) -- recupero le posizioni correnti --local dCorsaY = MaxX1 - MyMinX1 --local dCorsaV = MaxX2 - MinX2 local dX1PosA = dTPosI + dYDeltaI local dX2PosA = ParkX2 local dTPosA = dTPosI local dYDeltaA = dYDeltaI local dVDeltaA = dX2PosA - dTPosA local dNewVDelta -- = dVDeltaF -- tolleranza local dVDeltaTol = GetDeltaTol( dVDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, 'X2', bFixedDelta) local bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- reimposto i delta finali in caso di spostamenti richiesti significativi, tenuto conto delle tolleranze if bVDeltaS then dNewVDelta = dVDeltaF - dVDeltaTol / 4 else dNewVDelta = dVDeltaA end EgtOutLog(' YDeltaI=' .. EgtNumToString( dYDeltaA) .. ' VDeltaI(Park)='.. EgtNumToString( dVDeltaA).. ' TPosI=' .. EgtNumToString( dTPosI) , 1) EgtOutLog(' VDeltaF=' .. EgtNumToString( dVDeltaF) .. ' NewVDelta=' .. EgtNumToString( dNewVDelta) , 1) -- risalita testa a Zmax (da effettuare comunque, dato lo scambio di carrelli) local bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- calcoli preliminari in caso di spostamento richiesto per V significativo local dX1Pos, dX2Pos, dTPos local dNewV, dExtraX2, bVxs local dCorsaYfc, dCorsaVfc, dDistFrN, dCorsaYTd, dCorsaVd, dCorsaVTr, dCorsaYr, bXsw if bVDeltaS then -- definisco 'ExtraX2' con (Y+T) e V accentrati q.b. per la presa di V dX1Pos, dX2Pos, dTPos = PosxExtraYV( dX1PosA, dX2PosA, dTPosA, MyMinX1, MaxX2, 'X2') dNewV = dTPos + dNewVDelta dExtraX2 = dNewV - MaxX2 bVxs = dExtraX2 > dVDeltaTol/2 -- ExtraX2 'significativo' if bVxs then -- calcolo le **corse disponibili dei carrelli a partire da Y e V c.s.** per allontanare q.p. Y e (V+T) dCorsaYfc = MaxX1 - dX1Pos dCorsaVfc = dX2Pos - MinX2 --local dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dDistBkN = EMC.LB - (dX1Pos-dTPos) - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando (Y+T) e V dCorsaYTr = dCorsaYd + (dX1Pos -MyMinX1) dCorsaVr = dCorsaVTd bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaVr + dCorsaYTr end -- inizializzo dX1PosA = dX1Pos dX2PosA = dX2Pos dTPosA = dTPos end -- **[C1Vs-xsw]** posizione finale di V non raggiungibile, con |dExtraX2 > CorsaVr + CorsaYr| -- con spostamento richiesto significativo e ExtraX2 significativo while bXsw do EmitComment( vCmd, '[C1Vs-xsw]') -- **1:** posiziono (Y+T) e V come calcolato sopra table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **2:** allontano Y e (V+T) quanto possibile dX1PosA = dX1PosA + dCorsaYd dX2PosA = dX2PosA - dCorsaVTd dTPosA = dTPosA - dCorsaVTd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **3:** accentro (Y+T) e V dX1PosA = dX1PosA - dCorsaYTr -- = MyMinX1 dTPosA = dTPosA - dCorsaYTr dX2PosA = MaxX2 table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto i Delta ottenuti dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- **aggiorno ExtraX2** dExtraX2 = dExtraX2 - dCorsaYTr - dCorsaVr -- **aggiorno la valutazione di ulteriori corse disponibili** -- a partire da Y e V c.s. per allontanare q.p. Y e (V+T) dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- aggiorno i prossimi recuperi disponibili dCorsaYTr = dCorsaYd dCorsaVr = dCorsaVTd -- aggiorno verifica per ripetizione del ciclo bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaVr + dCorsaYTr end --[C1Vs-xw] -- **[C1Vs]** |spostamento| richiesto (ev' residuo) |di V| |'significativo'| if bVDeltaS then -- **[C1Vs-x]** posizione di |V non raggiungibile| if dExtraX2 > 0 then -- (dExtraX2 <= (CorsaYr+CorsaVr) da ciclo precedente) -- **[C1Vs-xs]** posizione di V non raggiungibile, |con ExtraX2 'significativo'| if bVxs then local dCorsaYTrA = dX1PosA - MyMinX1 -- **[C1Vs-xs1]** se posso recuperare dExtraX2 solo accentrando V e (Y+T) if dCorsaYTrA >= dExtraX2 then EmitComment( vCmd, '[C1Vs-xs1]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1:** accentro (Y+T) q.b. e V dX1PosA = dX1PosA - dExtraX2 dTPosA = dTPosA - dExtraX2 dX2PosA = MaxX2 -- (pos. finale) dVDeltaA = dX2PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) -- **[C1Vs-xs2]** dCorsaYTrA < dExtraX2 else EmitComment( vCmd, '[C1Vs-xs2]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1: accentro** ev' (Y+T) e V alle posizioni impostate table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) dVDeltaA = dX2PosA - dTPosA -- chiudo (ev') il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **2:allontano** (V+T) q.b./q.p. e Y per preparare il recupero di ExtraX2 dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX2, dCorsaYTrA, dCorsaYd, dCorsaVTd, 'X2') table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) dYDeltaA = dX1PosA - dTPosA -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **3: accentro**(Y+T) e V (pos. finale) dX1PosA = MyMinX1 dTPosA = dX1PosA - dYDeltaA dX2PosA = MaxX2 dVDeltaA = dX2PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) end -- [C1Vs-xs1/xs2] -- **[C1Vs-xn]** |ExtraX2 ancora > 0 , ma non 'significativo'| (<= DeltaTol/2) else EmitComment( vCmd, '[C1Vs-xn]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- 1: porto ev' (Y+T) alla posizione impostata sopra e accentro V dExtraX2 = 0 dX2PosA = MaxX2 -- pos. finale table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo V (?) table.insert( vCmd, { 12, 1}) end -- [C1Vs-xs/xn] -- **[C1Vs-r]** posizione di V 'raggiungibile' (ExtraX2 <= 0) else EmitComment( vCmd, '[C1Vs-r]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- posizione ev' (Y+T) come impostato sopra e V in posizione finale dX2PosA = dTPosA + dNewVDelta table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [C1V-s] -- **[C1Vns]** |spostamento| richIesto per V |non 'significativo'| else EmitComment( vCmd, '[C1Vns]') end -- calcolo i nuovi parametri di aggancio dVDeltaA = dX2PosA - dTPosA -- chiudo ev' V e apro Y table.insert( vCmd, { 12, CalcCharStatus( 'X2', dVDeltaA)}) table.insert( vCmd, { 11, 0}) -- sposto il carrello Y in parcheggio table.insert( vCmd, { 1, 'X1', ParkX1}) -- imposto i nuovi parametri di aggancio table.insert( vCmd, { 21, 0, dVDeltaA}) EgtOutLog( ' VDeltaA =' .. EgtNumToString( dVDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end --SpecAdjustCarrC1 --------------------------------------------------------------------- -- *** [C2] da entrambi i carrelli a X2 : X1+X2 -> X2 *** --------------------------------------------------------------------- function SpecAdjustCarrC2( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta) EgtOutLog( ' *[C2] = X1+X2 -> X2', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X1+X2 -> X2'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) local dCorsaY = MaxX1 - MyMinX1 local dCorsaV = MaxX2 - MinX2 -- recupero le posizioni correnti dei carrelli local dX1PosA = dTPosI + dYDeltaI local dX2PosA = dTPosI + dVDeltaI local dTPosA = dTPosI local dYDeltaA = dYDeltaI local dVDeltaA = dVDeltaI local dNewVDelta -- = dVDeltaF -- tolleranze local dVDeltaTol = GetDeltaTol( dVDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, 'X2', bFixedDelta) -- definisco spostamento 'significativo' in base alle tolleranze local bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- reimposto ev' il delta finale if bVDeltaS then dNewVDelta = dVDeltaF - dVDeltaTol / 4 else dNewVDelta = dVDeltaA end -- definisco 'ExtraX2' local dNewV = dTPosI + dNewVDelta local dExtraX2 = dNewV - MaxX2 -- > 0 se nuova pos. di X2 'non raggiungibile' (= oltre MaxX2) local bVxs = dExtraX2 > dVDeltaTol/2 -- 'ExtraX2 significativo' EgtOutLog( ' YDeltaI=' .. EgtNumToString( dYDeltaI) .. ' VDeltaI=' .. EgtNumToString( dVDeltaI) .. ' VDeltaF=' .. EgtNumToString( dVDeltaF) ,1) EgtOutLog( ' NewVDelta=' .. EgtNumToString( dNewVDelta), 1) -- risalita testa a Zmax (da effettuare comunque, per il parcheggio di Y) local bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- calcoli preliminari in caso di spostamento richiesto per YV significativo local dCorsaYfc, dCorsaVfc, dDistBkN, dCorsaYd, dCorsaVd, dCorsaVTd, dCorsaYTr, dCorsaVr, bXsw if bVDeltaS then if bVxs then -- calcolo le corse disponibili dei carrelli dalle posizioni attuali (=iniziali) -- per allontanare Y e (V+T) q.p. dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- valuto le corse di 'recupero' dai due carrelli possibili riaccentrando (Y+T) e V dCorsaYTr = dCorsaYd + (dX1PosA - MyMinX1) dCorsaVr = dCorsaVTd bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaYTr + dCorsaVr end end -- **[C2Vs-xsw]** posizione finale di V non raggiungibile, |con dExtraX2 > CorsaYTr + CorsaVr| while bXsw do EmitComment( vCmd, '[C2Vs-xsw]') -- chiudo eventualmente il carrello V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- |1:| allontano Y e (V+T) quanto possibile dX1PosA = dX1PosA + dCorsaYd dX2PosA = dX2PosA - dCorsaVTd dTPosA = dTPosA - dCorsaVTd table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- |3:| accentro (Y+T) e V dX1PosA = dX1PosA - dCorsaYTr dTPosA = dTPosA - dCorsaYTr dX2PosA = MaxX2 table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) -- valuto i Delta ottenuti dYDeltaA = dX1PosA - dTPosA dVDeltaA = dX2PosA - dTPosA -- aggiorno la verifica di spostamento significativo bVDeltaS = ( dVDeltaF > dVDeltaA + dVDeltaTol or dVDeltaF < dVDeltaA - DELTA_SIC) -- **aggiorno ExtraX2** dExtraX2 = dExtraX2 - dCorsaYTr - dCorsaVr -- **aggiorno la valutazione di ulteriori corse disponibili** dCorsaYfc = MaxX1 - dX1PosA dCorsaVfc = dX2PosA - MinX2 dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- aggiorno i prossimi recuperi disponibili dCorsaYTr = dCorsaYd + (dX1PosA - MyMinX1) dCorsaVr = dCorsaVTd -- aggiorno verifica per ripetizione del ciclo bXsw = bVDeltaS and bVxs and dExtraX2 > dCorsaYTr + dCorsaVr end -- [C2V-xsw] -- **[C2Vs]** se lo |spostamento richiesto per V è significativo| if bVDeltaS then -- **[C2Vs-x]** posizione di |V non raggiungibile| (oltre MaxX2) if dExtraX2 > 0 then -- **[C2Vs-xs]** |ExtraX2 'significativo'| if bVxs then local dCorsaYTrA = dX1PosA - MyMinX1 -- **[C2Vs-xs1]** se posso recuperare ExtraX2 semplicem' accentrando V e (Y+T) if dCorsaYTrA >= dExtraX2 then EmitComment( vCmd, '[C2Vs-xs1]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1: accentro** (Y+T) e V dX1PosA = dX1PosA - dExtraX2 dTPosA = dTPosA - dExtraX2 dX2PosA = MaxX2 -- (pos. finale) dVDeltaA = dX2PosA - dTPosA table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) else -- **[C2Vs-xs2]** EmitComment( vCmd, '[C2Vs-xs2]') -- chiudo ev' V e apro Y table.insert( vCmd, { 12, 1}) table.insert( vCmd, { 11, 0}) -- **1: allontano** (V+T) e Y dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX2, dCorsaYTrA, dCorsaYd, dCorsaVTd, 'X2') table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) dYDeltaA = dX1PosA - dTPosA -- chiudo il carrello Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2: accentro** (Y+T) e V dX1PosA = MyMinX1 dTPosA = dX1PosA - dYDeltaA dX2PosA = MaxX2 -- (pos. finale) table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [C2Vs-xs1/-xs2] -- **[C2Vs-xn]** |dExtraX2 ancora > 0 ma non 'significativo')| else --if dExtraX2 < DeltaToll/2 EmitComment( vCmd, '[B1Vs-xn]') -- ev' chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1:** accentro V dExtraX2 = 0 dX2PosA = MaxX2 -- (pos. finale) table.insert( vCmd, { 1, 'X2', dX2PosA}) end -- [C2s-xs/xn] -- **[C2Vs-r]** |dExtraX2 < 0 (pos. V raggiungibile)| else EmitComment( vCmd, '[C2Vs-r]') -- chiudo ev' Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- porto V in posizione finale dX2PosA = dTPosA + dNewVDelta table.insert( vCmd, { 1, 'X2', dX2PosA}) end --[C2Vs] -- **[C2Vns]** = |spostamento di V non significativo| else EmitComment( vCmd, '[C2Vns]') end --[C2Vs/n] -- calcolo il nuovo parametro di aggancio dVDeltaA = dX2PosA - dTPosA -- chiudo eventualmente il carrello V e apro Y table.insert( vCmd, { 12, CalcCharStatus( 'X2', dVDeltaA)}) table.insert( vCmd, { 11, 0}) -- sposto il carrello Y in parcheggio table.insert( vCmd, { 1, 'X1', ParkX1}) -- imposto il nuovo parametro di aggancio table.insert( vCmd, { 21, 0, dVDeltaA}) EgtOutLog( ' VDeltaA =' .. EgtNumToString( dVDeltaA), 1) -- reset contatore EMC.CNT = nil SpecOutputCNT() return vCmd end --SpecAdjustCarrC2 --------------------------------------------------------------------- -- *** [C3] da carrello X2 a X2 : X2 -> X2 *** --------------------------------------------------------------------- function SpecAdjustCarrC3( dTPosI, dYDeltaI, dVDeltaI, dTPosF, dYDeltaF, dVDeltaF, bFixedDelta, bFixedPos) EgtOutLog( ' *[C3] = X2 -> X2', 1) -- elenco comandi local vCmd = {} -- Commento table.insert( vCmd, { 0, 'X2 -> X2'}) -- se primo scambio local MyMinX1 = EgtIf( EMC.CNT == 1, MinX1 + AGG_LOAD, MinX1) -- recupero le posizioni correnti dei carrelli local dX2PosA = dTPosI + dVDeltaI local dX1PosA = ParkX1 local dTPosA = dTPosI local dVDeltaA = dVDeltaI local dYDeltaA = dX1PosA - dTPosA local dNewVDelta -- tolleranza local dVDeltaTol = GetDeltaTol( dVDeltaF, EMC.TCING, EMC.HCING, EMC.HOVM, 'X2', bFixedDelta) local bVDeltaS = (( dVDeltaF > dVDeltaA + dVDeltaTol and not bFixedPos) or dVDeltaF < dVDeltaA - DELTA_SIC) if bVDeltaS then dNewVDelta = dVDeltaF - dVDeltaTol / 4 else dNewVDelta = dVDeltaA end EgtOutLog( ' VDeltaI=' .. EgtNumToString( dVDeltaI) .. ' TPosI=' .. EgtNumToString( dTPosI), 1) EgtOutLog( ' VDeltaF=' .. EgtNumToString( dVDeltaF) .. ' NewVDelta=' .. EgtNumToString( dNewVDelta), 1) -- flag per risalita testa a Zmax local bZmaxOk = false -- **[C3Vs]** |pos. di V cambia in modo significativo| if bVDeltaS then EmitComment( vCmd, '[C3Vs]') -- eventuale risalita testa a Zmax bZmaxOk = EnsureZmax( bZmaxOk, vCmd) -- definisco 'ExtraX2' con (V+T) e Y accentrati q.b. per la presa con Y local dX1Pos, dX2Pos, dTPos = PosxExtraYV( dX1PosA, dX2PosA, dTPosA, MyMinX1, MaxX2, 'X1') local dNewV = dTPos + dNewVDelta local dExtraX2 = dNewV - MaxX2 -- effettuo spostamenti per predisporre all'aggancio di T con Y dX1PosA = dX1Pos dX2PosA = dX2Pos dTPosA = dTPos table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dYDeltaA = dX1PosA - dTPosA -- **[C3Vs-x]** posizione di |V non raggiungibile| (oltre MaxX2) if dExtraX2 > 0 then -- **[C3Vs-xs]** posizione di V non raggiungibile, |con ExtraX2 'significativo'| if dExtraX2 > dVDeltaTol /2 then -- calcolo le **corse disponibili dei carrelli a partire da Y e V c.s.** per allontanare q.p. (V+T) e Y local dCorsaYfc = MaxX1 - dX1Pos local dCorsaVfc = dX2Pos - MinX2 local dDistBkN = EMC.LB - dYDeltaA - MinJoin - EMC.TCING -- DistBack 'netta' local dCorsaYd, dCorsaVTd = GetCorseDisp( dCorsaYfc, dCorsaVfc, dDistBkN, 'Bk') -- valuto **le corse di 'recupero'** dai due carrelli possibili riaccentrando (Y+T) e V local dCorsaYTr = dCorsaYd + (dX1Pos - MyMinX1) local dCorsaVr = dCorsaVTd -- **[C3Vs-xsw]** posizione finale dNewV non raggiungibile, con |dExtraX2 > CorsaVr + CorsaYr| if dExtraX2 > ( dCorsaYTr + dCorsaVr) and bVDeltaS then EmitComment( vCmd, '[C3Vs-xsw]' .. 'CASO NON GESTITO') return end local dCorsaYTrA = dX1Pos - MyMinX1 -- !! att.ne: non dX1PosA !! -- **[C3Vs-xs1]** se posso recuperare ExtraX2 semplicem' accentrando (Y+T) e V -- (dalle posizione impostate sopra per l'aggancio di Y) if dCorsaYTrA >= dExtraX2 then EmitComment( vCmd, '[C3Vs-xs1]') -- chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1: accentro** (Y+T) e V dX1PosA = dX1PosA - dExtraX2 dTPosA = dTPosA - dExtraX2 dX2PosA = MaxX2 -- (pos. finale) table.insert( vCmd, { 3, 'X1', dX1PosA , 'T', dTPosA, 'X2', dX2PosA}) dVDeltaA = dX2PosA - dTPosA else -- **[C3Vs-xs2]** -- ci sarebbe un doppio movimento di V ? => caso impossibile ? EmitComment( vCmd, '[C3Vs-xs2]') -- **1:** posiziono (ulteriormente!) Y e (V+T) dX1PosA, dX2PosA, dTPosA = PosXs2Enl( dX1PosA, dX2PosA, dTPosA, dExtraX2, dCorsaYTrA, dCorsaYd, dCorsaVTd, 'X2') table.remove( vCmd) table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA }) dYDeltaA = dX1PosA - dTPosA -- chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2: accentro** (Y+T) e V dX1PosA = MyMinX1 dX2PosA = MaxX2 -- (pos. finale) dTPosA = dX1PosA - dYDeltaA table.insert( vCmd, { 3, 'X1', dX1PosA, 'T', dTPosA, 'X2', dX2PosA}) end -- [C3Vs-xs1/-xs2] -- **[C3Vs-xn]** |dExtraX2 > 0 ma 'non significativo')| else --if dExtraX2 < DeltaToll/2 EmitComment( vCmd, '[C3Vs-xn]') -- chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **1:** accentro V dExtraX2 = 0 dX2PosA = MaxX2 -- (pos. finale) table.insert( vCmd, { 1, 'X2', dX2PosA}) end --[C3Vs-xs/xn] -- **[C3Vs-r]** |posizione di Y raggiungibile| (ExtraX1 >=0) -- (si esclude la possibilità di extra corsa oltre maxX1) else EmitComment( vCmd, '[C3Vs-r]') -- chiudo Y e apro V table.insert( vCmd, { 11, 1}) table.insert( vCmd, { 12, 0}) -- **2:** posiziono V alla posizione richiesta dX2PosA = dNewV table.insert( vCmd, { 1, 'X2', dX2PosA}) end -- [C3Vs] -- calcolo il nuovo parametro di aggancio dVDeltaA = dX2PosA - dTPosA -- chiudo ev' V e apro Y table.insert( vCmd, { 12, CalcCharStatus( 'X2', dVDeltaA)}) table.insert( vCmd, { 11, 0}) -- sposto il carrello Y in parcheggio table.insert( vCmd, { 1, 'X1', ParkX1}) -- imposto il nuovo parametro di aggancio table.insert( vCmd, { 21, 0, dVDeltaA}) -- reset contatore EMC.CNT = nil else -- **[C3Vns]** |spostamento| finale richiesto (ev' residuo) di |V non 'significativo'| EmitComment( vCmd, '[C3Vns]') end --[C3Vs/ns] EgtOutLog( ' VDeltaA =' .. EgtNumToString( dVDeltaA), 1) SpecOutputCNT() return vCmd end --SpecAdjustCarrC3 --------------------------------------------------------------------- function SpecOutputCNT() if EMC.CNT == 1 then EgtSetInfo( EMC.PATHID, 'CNT', 1) else EgtRemoveInfo( EMC.PATHID, 'CNT') end 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 Y elseif Cmd[1] == 11 then local sInfo = '11,'..EgtNumToString( Cmd[2],0) EgtSetInfo( EMC.PATHID, sKey, sInfo) if Cmd[2] == 0 then EMC.YDELTA = nil end -- apertura/chiusura morsa V elseif Cmd[1] == 12 then local sInfo = '12,'..EgtNumToString( Cmd[2],0) EgtSetInfo( EMC.PATHID, sKey, sInfo) if Cmd[2] == 0 then EMC.VDELTA = 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.YDELTA = Cmd[2] EMC.VDELTA = Cmd[3] elseif Cmd[2] > 0 then EMC.YDELTA = Cmd[2] EMC.VDELTA = nil elseif Cmd[3] > 0 then EMC.YDELTA = nil EMC.VDELTA = 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 -- Salvo i nuovi delta dei carrelli if EMC.YDELTA then EgtSetInfo( EMC.PATHID, 'YDELTA', EMC.YDELTA) else EgtRemoveInfo( EMC.PATHID, 'YDELTA') end if EMC.VDELTA then EgtSetInfo( EMC.PATHID, 'VDELTA', EMC.VDELTA) else EgtRemoveInfo( EMC.PATHID, 'VDELTA') 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.YDELTA = Cmd[2] EMC.VDELTA = Cmd[3] elseif Cmd[2] > 0 then EMC.YDELTA = Cmd[2] EMC.VDELTA = nil elseif Cmd[3] > 0 then EMC.YDELTA = nil EMC.VDELTA = 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