From 4b835a27be187f595b5083ef3b1e3b67ccad7a33 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 5 Sep 2024 08:29:20 +0200 Subject: [PATCH 1/2] EgtMachKernel 2.6i1 : - introduzione secondo simulatore sperimentale per macchine multiprocesso. --- EgtMachKernel.rc | Bin 11774 -> 11774 bytes EgtMachKernel.vcxproj | 5 +- EgtMachKernel.vcxproj.filters | 13 +- MachMgr.h | 2 +- MachMgrClEntities.cpp | 1 + MachMgrGeneration.cpp | 4 +- MachMgrSimulation.cpp | 10 +- Machine.cpp | 2 +- Machine.h | 6 +- MachineLua.cpp | 21 +- MachineLuaCL.cpp | 1 + Operation.h | 1 + Simulator.h | 189 +- SimulatorMP.cpp | 2491 +++++++++++++++ SimulatorMP.h | 202 ++ Simulator.cpp => SimulatorSP.cpp | 4912 +++++++++++++++--------------- SimulatorSP.h | 186 ++ 17 files changed, 5411 insertions(+), 2635 deletions(-) create mode 100644 SimulatorMP.cpp create mode 100644 SimulatorMP.h rename Simulator.cpp => SimulatorSP.cpp (94%) create mode 100644 SimulatorSP.h diff --git a/EgtMachKernel.rc b/EgtMachKernel.rc index 59ba50d8eadfb3c08aedd8bb67b4a5b2b13331d3..a583864a206ff5f65856d7ae00cbc3991336992b 100644 GIT binary patch delta 105 zcmewt{V#gMH#SDg&F|%|GEF|inZ=yRU^w}qr0(W4t{xV!xHB_COb9B5q1JpF diff --git a/EgtMachKernel.vcxproj b/EgtMachKernel.vcxproj index 884ac02..921d8b3 100644 --- a/EgtMachKernel.vcxproj +++ b/EgtMachKernel.vcxproj @@ -283,7 +283,8 @@ copy $(TargetPath) \EgtProg\Dll64 - + + Create Create @@ -459,6 +460,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + diff --git a/EgtMachKernel.vcxproj.filters b/EgtMachKernel.vcxproj.filters index 87a3c0a..8c0d39e 100644 --- a/EgtMachKernel.vcxproj.filters +++ b/EgtMachKernel.vcxproj.filters @@ -150,7 +150,7 @@ Source Files\MachMgr - + Source Files\Output @@ -246,6 +246,9 @@ Source Files\Operations + + Source Files\Output + @@ -341,7 +344,7 @@ Header Files\Include - + Header Files @@ -752,6 +755,12 @@ Header Files\Include + + Header Files + + + Header Files + diff --git a/MachMgr.h b/MachMgr.h index 7822799..a0de374 100644 --- a/MachMgr.h +++ b/MachMgr.h @@ -550,5 +550,5 @@ class MachMgr : public IMachMgr int m_nCurrDispId ; // identificativo della disposizione corrente int m_nCurrMachiningId ; // identificativo della lavorazione corrente AXBLOCKVECTOR m_vAxisBlock ; // elenco assi da bloccare - Simulator* m_pSimul ; // puntatore al simulatore attivo + ISimulator* m_pSimul ; // puntatore al simulatore attivo } ; diff --git a/MachMgrClEntities.cpp b/MachMgrClEntities.cpp index 85d991e..58896ee 100644 --- a/MachMgrClEntities.cpp +++ b/MachMgrClEntities.cpp @@ -16,6 +16,7 @@ #include "DllMain.h" #include "MachMgr.h" #include "MachConst.h" +#include "CamData.h" using namespace std ; diff --git a/MachMgrGeneration.cpp b/MachMgrGeneration.cpp index e6ce8cd..2357967 100644 --- a/MachMgrGeneration.cpp +++ b/MachMgrGeneration.cpp @@ -26,8 +26,8 @@ using namespace std ; bool MachMgr::Generate( const string& sCncFile, const string& sInfo) { - // se necessaria stima speciale - if ( GetCurrMachine() != nullptr && GetCurrMachine()->GetSpecialEstimate()) { + // se macchina multiprocesso è necessaria stima speciale + if ( GetCurrMachine() != nullptr && GetCurrMachine()->GetMultiProcess()) { // inizializzazione stimatore Estimator estPP ; if ( ! estPP.Init( this)) { diff --git a/MachMgrSimulation.cpp b/MachMgrSimulation.cpp index 74bd84a..d4679d2 100644 --- a/MachMgrSimulation.cpp +++ b/MachMgrSimulation.cpp @@ -16,7 +16,8 @@ #include "DllMain.h" #include "MachMgr.h" #include "MachConst.h" -#include "Simulator.h" +#include "SimulatorSP.h" +#include "SimulatorMP.h" using namespace std ; @@ -27,7 +28,12 @@ MachMgr::SimInit( void) // alloco o rialloco il simulatore if ( m_pSimul != nullptr) delete m_pSimul ; - m_pSimul = new( nothrow) Simulator ; + if ( GetCurrMachine() == nullptr) + return false ; + //if ( GetCurrMachine()->GetMultiProcess()) + // m_pSimul = CreateSimulatorMP() ; + //else + m_pSimul = CreateSimulatorSP() ; if ( m_pSimul == nullptr) return false ; // lo inizializzo diff --git a/Machine.cpp b/Machine.cpp index 5e23e82..c07c7dd 100644 --- a/Machine.cpp +++ b/Machine.cpp @@ -41,7 +41,7 @@ Machine::Machine( void) m_dExitMaxAdjust = EPS_SMALL ; m_dExitMaxRotAdj = 10 * EPS_ANG_SMALL ; m_dAngDeltaMinForHome = INFINITO ; - m_bSpecialEstimate = false ; + m_bMultiProcess = false ; m_nCalcTabId = GDB_ID_NULL ; m_nCalcHeadId = GDB_ID_NULL ; m_nCalcExitId = GDB_ID_NULL ; diff --git a/Machine.h b/Machine.h index 361888b..32bd835 100644 --- a/Machine.h +++ b/Machine.h @@ -71,8 +71,8 @@ class Machine int GetHeadSelectType(const std::string& sHead) const ; double GetAngDeltaMinForHome( void) const { return m_dAngDeltaMinForHome ; } - bool GetSpecialEstimate( void) const - { return m_bSpecialEstimate ; } + bool GetMultiProcess( void) const + { return m_bMultiProcess ; } bool LoadTool( const std::string& sHead, int nExit, const std::string& sTool) ; bool GetLoadedTool( const std::string& sHead, int nExit, std::string& sTool) const ; bool UnloadTool( const std::string& sHead, int nExit) ; @@ -293,7 +293,7 @@ class Machine double m_dExitMaxAdjust ; // massimo aggiustamento uscita da geometria a descrizione cinematica double m_dExitMaxRotAdj ; // massima rotazione di aggiustamento uscita da geometria a descrizione cinematica double m_dAngDeltaMinForHome ; // minima differenza angolare da valore precedente per scegliere di stare vicino a home - bool m_bSpecialEstimate ; // flag di esecuzione stima speciale prima della generazione + bool m_bMultiProcess ; // flag di macchina multi-processo con stima speciale prima di generazione e simulazione ad hoc INTVECTOR m_vLinkedRawParts ; // elenco dei grezzi agganciati a gruppi della macchina INTVECTOR m_vLinkedFixtures ; // elenco dei bloccaggi agganciati a gruppi della macchina INTVECTOR m_vLinkedParts ; // elenco dei pezzi agganciati a gruppi della macchina diff --git a/MachineLua.cpp b/MachineLua.cpp index 0974e03..5495554 100644 --- a/MachineLua.cpp +++ b/MachineLua.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- // EgalTech 2015-2024 //---------------------------------------------------------------------------- -// File : MachineLua.cpp Data : 05.08.24 Versione : 2.6h1 +// File : MachineLua.cpp Data : 01.09.24 Versione : 2.6i1 // Contenuto : Implementazione gestione macchina : funzioni Lua. // // @@ -9,6 +9,7 @@ // Modifiche : 06.05.15 DS Creazione modulo. // 26.04.20 DS Aggiunta gestione TcPos. // 05.08.24 DS Aggiunta gestione SpecialEstimate. +// 01.09.24 DS SpecialEstimate è diventato MultiProcess. // //---------------------------------------------------------------------------- @@ -35,7 +36,7 @@ static const string FLD_AXISMAXROTADJ = "AxisMaxRotAdj" ; static const string FLD_EXITMAXADJUST = "ExitMaxAdjust" ; static const string FLD_EXITMAXROTADJ = "ExitMaxRotAdj" ; static const string FLD_ANGDELTAMINFORHOME = "AngDeltaMinForHome" ; -static const string FLD_SPECIALESTIMATE = "SpecialEstimate" ; +static const string FLD_MULTIPROCESS = "MultiProcess" ; static const string FLD_NAME = "Name" ; static const string FLD_PARENT = "Parent" ; static const string FLD_GEO = "Geo" ; @@ -344,9 +345,9 @@ Machine::LuaEmtGeneral( lua_State* L) // lettura eventuale campo 'AngDeltaForHome' dalla tabella (default INFINITO) double dAngDeltaMinForHome = INFINITO ; LuaGetTabFieldParam( L, 1, FLD_ANGDELTAMINFORHOME, dAngDeltaMinForHome) ; - // lettura eventuale campo 'SpecialEstimate' dalla tabella (default false) - bool bSpecialEstimate = false ; - LuaGetTabFieldParam( L, 1, FLD_SPECIALESTIMATE, bSpecialEstimate) ; + // lettura eventuale campo 'MultiProcess' dalla tabella (default false) + bool bMultiProcess = false ; + LuaGetTabFieldParam( L, 1, FLD_MULTIPROCESS, bMultiProcess) ; LuaClearStack( L) ; // info @@ -396,8 +397,8 @@ Machine::LuaEmtGeneral( lua_State* L) // imposto minima differenza angolare da posizione precedente per stare vivino a posizione home m_pMchLua->m_dAngDeltaMinForHome = dAngDeltaMinForHome ; - // imposto flag per stima speciale - m_pMchLua->m_bSpecialEstimate = bSpecialEstimate ; + // imposto flag per macchina multiprocesso + m_pMchLua->m_bMultiProcess = bMultiProcess ; return 0 ; } @@ -1553,7 +1554,9 @@ Machine::LuaEmtMoveAxes( lua_State* L) // assegno risultato if ( nRes == SIM_AXMV_RES_STOP) return luaL_error( L, "STOP") ; - else + else { LuaSetParam( L, ( nRes == SIM_AXMV_RES_OK)) ; - return 1 ; + LuaSetParam( L, m_pMchLua->GetMultiProcess()) ; + } + return 2 ; } diff --git a/MachineLuaCL.cpp b/MachineLuaCL.cpp index f81ee6c..fca5e18 100644 --- a/MachineLuaCL.cpp +++ b/MachineLuaCL.cpp @@ -15,6 +15,7 @@ #include "stdafx.h" #include "MachMgr.h" #include "DllMain.h" +#include "CamData.h" #include "/EgtDev/Include/EXeExecutor.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkCurveLine.h" diff --git a/Operation.h b/Operation.h index abe69a4..da97f8a 100644 --- a/Operation.h +++ b/Operation.h @@ -17,6 +17,7 @@ #include "MachMgr.h" #include "MachConst.h" #include "MachineStruConst.h" +#include "CamData.h" #include "/EgtDev/Include/EGkPoint3d.h" #include "/EgtDev/Include/EGkUserObj.h" #include "/EgtDev/Include/EGkSelection.h" diff --git a/Simulator.h b/Simulator.h index aeb8fac..854d00e 100644 --- a/Simulator.h +++ b/Simulator.h @@ -1,25 +1,24 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2023 +// EgalTech 2015-2024 //---------------------------------------------------------------------------- -// File : Simulator.h Data : 16.01.23 Versione : 2.5a2 -// Contenuto : Dichiarazione della classe Simulator. +// File : Simulator.h Data : 01.09.24 Versione : 2.6i1 +// Contenuto : Dichiarazione della classe interfaccia ISimulator. // // // -// Modifiche : 19.10.15 DS Creazione modulo. +// Modifiche : 01.09.24 DS Creazione modulo. // // //---------------------------------------------------------------------------- #pragma once -#include "CamData.h" +#include "/EgtDev/Include/EGkVector3d.h" #include "/EgtDev/Include/EMkSimuGenConst.h" +#include "/EgtDev/Include/EgtNumCollection.h" +#include class MachMgr ; -class IGeomDB ; -class Machine ; -class PerformanceCounter ; //------------------------ Struttura per movimento esterno assi -------------- struct SimAxMv @@ -38,160 +37,26 @@ enum SimAxMvRes { SIM_AXMV_RES_STOP = -1, SIM_AXMV_RES_OK = 1} ; //---------------------------------------------------------------------------- -class Simulator +class __declspec( novtable) ISimulator { public : - Simulator( void) ; - ~Simulator( void) ; - bool Init( MachMgr* pMchMgr) ; - bool Start( bool bFirst) ; - bool Move( int& nStatus) ; - bool GoHome( void) ; - bool SetStep( double dStep) ; - bool SetUiStatus( int nUiStatus) ; - bool GetAxisInfoPos( int nI, std::string& sName, std::string& sToken, bool& bLinear, double& dVal) const ; - bool GetToolInfo( std::string& sName, double& dSpeed) const ; - bool GetOperationInfo( std::string& sName, int& nType) const ; - bool GetMoveInfo( int& nGmove, double& dFeed) const ; - bool AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) ; - bool ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) ; - bool OnCollision( int nCdInd, int nObjInd, int& nErr) ; - bool SetToolForVmill( const std::string& sTool, const std::string& sHead, int nExit, int nFlag, double dPar1, double dPar2, - const INTVECTOR& vVmill, bool bFirst) ; - bool EnableToolsForVmill( bool bEnable) ; - int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) ; - - private : - bool UpdateTool( bool bFirst, int& nErr) ; - bool UpdateAxes( void) ; - bool UpdateAxesPos( void) ; - bool ResetInterpolation( void) ; - bool ResetAxes( void) ; - bool ResetAuxAxes( void) ; - - private : - bool VerifySetup( void) ; - bool FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) ; - bool ManageOperationEnd( int& nStatus) ; - bool FindAndManagePathStart( int& nStatus) ; - bool ManagePathEnd( int& nStatus) ; - bool ManagePathStartAux( int& nStatus) ; - bool ManagePathEndAux( int& nStatus) ; - bool ManageMove( int& nStatus) ; - bool ManageSingleMove( int& nStatus, double& dMove) ; - int CalcStatusOnError( int nErr) ; - bool GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA) ; - bool ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, - const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, - const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) ; - bool NeedCollisionCheck( void) const - { return ( ! m_CollObj.empty() && ! m_CdId.empty()) ; } - bool Stopped( void) - { return ( m_nUiStatus == MCH_UISIM_STOP) ; } - bool SetCollisionMark( int nCdInd, int nObjInd) ; - bool ResetCollisionMark( void) ; - bool OnInit( void) ; - bool OnExit( void) ; - bool OnProgramStart( bool bFirst) ; - bool OnProgramEnd( void) ; - bool OnDispositionStarting( int nOpId, int nOpInd, int nPhase, - const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; - bool OnDispositionStart( int nOpId, int nOpInd, int nPhase, - const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; - bool OnDispositionEnd( void) ; - bool OnToolSelect( const std::string& sTool, const std::string& sHead, int nExit, const std::string& sTcPos, bool bFirst, int& nErr) ; - bool OnToolDeselect( const std::string& sNextTool, const std::string& sNextHead, int nNextExit, const std::string& sNextTcPos, int& nErr) ; - bool OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, - const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) ; - bool OnMachiningEnd( void) ; - bool OnPathStartAux( int nInd, const std::string& sAS, int& nErr) ; - bool OnPathEndAux( int nInd, const std::string& sAE, int& nErr) ; - bool OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, - const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, - const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) ; - bool OnPathEnd( int nAE) ; - bool OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) ; - bool OnMoveEnd( int& nErr) ; - bool OnResetMachine( void) ; - - private : - struct CollObj { - int nInd ; - bool bToolOn ; - int nFrameId ; - int nType ; - Vector3d vtMove ; - double dPar1 ; - double dPar2 ; - double dPar3 ; - CollObj( void) : nInd( 0), bToolOn( false), nFrameId( -1), nType( 0), vtMove(), dPar1( 0), dPar2( 0), dPar3( 0) {} - CollObj( int nI, bool bTOn, int nF, int nT, const Vector3d& vtM, double dP1, double dP2, double dP3) - : nInd( nI), bToolOn( bTOn), nFrameId( nF), nType( nT), vtMove( vtM), dPar1( dP1), dPar2( dP2), dPar3( dP3) {} - } ; - typedef std::vector COBVECTOR ; - struct VmTool - { - std::string sName ; - std::string sHead ; - int nExit ; - double dTdOffs ; - double dAdOffs ; - VmTool( void) : nExit( 0), dTdOffs( 0), dAdOffs( 0) {} - VmTool( std::string sN, std::string sH, int nE, double dT, double dA) - : sName( sN), sHead( sH), nExit( nE), dTdOffs( dT), dAdOffs( dA) {} - } ; - typedef std::vector VMTVECTOR ; - enum { SIS_CREATED = 0, - SIS_INITIALIZED = 1, - SIS_READYTOSTART = 2, - SIS_READYTORUN = 3} ; - - private : - MachMgr* m_pMchMgr ; // puntatore al gestore di tutte le lavorazioni - IGeomDB* m_pGeomDB ; // puntatore al DB geometrico - Machine* m_pMachine ; // puntatore alla macchina - PerformanceCounter* m_pPerfCnt ; // timer per calcolo FPS - int m_nStatus ; // stato interno del simulatore (creato, inizializzato, pronto al movimento) - double m_dStep ; // lunghezza di riferimento per la velocità di simulazione - int m_nUiStatus ; // stato simulazione a livello utente - int m_nOpId ; // identificativo della operazione (lavoraz.) corrente - int m_nOpInd ; // contatore della operazione (lavoraz.) corrente - int m_nCLPathId ; // identificativo del percorso di lavoro corrente - int m_nCLPathInd ; // contatore del percorso di lavoro corrente nell'operazione - int m_nEntId ; // identificativo dell'entità corrente - int m_nEntInd ; // contatore dell'entità corrente nel percorso di lavoro - double m_dCoeff ; // coefficiente di esecuzione del movimento corrente (0...1) - int m_nAuxSTot ; // numero totale movimenti ausiliari di inizio percorso - int m_nAuxSInd ; // indice del movimento ausiliario di inizio percorso corrente - int m_nAuxETot ; // numero totale movimenti ausiliari di fine percorso - int m_nAuxEInd ; // indice del movimento ausiliario di fine percorso corrente - std::string m_sTool ; // nome dell'utensile corrente - std::string m_sHead ; // nome della testa corrente - int m_nExit ; // indice dell'uscita corrente - double m_dTDiam ; // diametro dell'utensile corrente - bool m_bCutOnTip ; // flag capacità di lavorare di testa dell'utensile corrente - bool m_bEnableVm ; // flag abilitazione Virtual Milling - INTVECTOR m_VmId ; // vettore identificativi Zmap per Virtual Milling - INTVECTOR m_CdId ; // vettore identificativi Zmap per Collision Detection - VMTVECTOR m_VmTool ; // vettore utensili attivi per virtual milling - COBVECTOR m_CollObj ; // vettore oggetti da testare per collisione con grezzo - double m_dSafeDist ; // distanza di sicurezza per verifica collisioni - INTVECTOR m_nCollMarkId ; // elenco oggetti marcati per visualizzare meglio la collisione rilevata - int m_nAxesMask ; // maschera a bit di abilitazione movimento assi (solo se rapido) - bool m_bEnabAxes ; // flag abilitazione movimento assi attivi - bool m_bShowAxes ; // flag visualizzazione assi attivi - STRVECTOR m_AxesName ; // nomi degli assi macchina attivi - STRVECTOR m_AxesToken ; // token degli assi macchina attivi - BOOLVECTOR m_AxesInvert ; // flag di asse con verso invertito degli assi macchina attivi - DBLVECTOR m_AxesOffset ; // valore di offset delgli assi macchina ttivi - BOOLVECTOR m_AxesLinear ; // flag di lineare degli assi macchina attivi - DBLVECTOR m_AxesVal ; // valori degli assi macchina all'inizio del movimento corrente - STRVECTOR m_AuxAxesName ; // nomi degli assi macchina ausiliari abilitati - STRVECTOR m_AuxAxesToken ; // token degli assi macchina ausiliari abilitati - BOOLVECTOR m_AuxAxesInvert ; // flag di asse con verso invertito degli assi macchina ausiliari abilitati - DBLVECTOR m_AuxAxesOffset ; // valore di offset degli assi macchina ausiliari abilitati - BOOLVECTOR m_AuxAxesLinear ; // flag di lineare degli assi macchina ausiliari abilitati - DBLVECTOR m_AuxAxesVal ; // valori degli assi macchina ausiliari all'inizio del movimento corrente - DBLVECTOR m_AuxAxesEnd ; // valori degli assi macchina ausiliari alla fine del movimento corrente - INTVECTOR m_AuxAxesLink ; // indice + 1 asse principale di aggancio (negativo valore opposto, 0 nessuno) + virtual ~ISimulator( void) {} + virtual bool Init( MachMgr* pMchMgr) = 0 ; + virtual bool Start( bool bFirst) = 0 ; + virtual bool Move( int& nStatus) = 0 ; + virtual bool GoHome( void) = 0 ; + virtual bool SetStep( double dStep) = 0 ; + virtual bool SetUiStatus( int nUiStatus) = 0 ; + virtual bool GetAxisInfoPos( int nI, std::string& sName, std::string& sToken, bool& bLinear, double& dVal) const = 0 ; + virtual bool GetToolInfo( std::string& sName, double& dSpeed) const = 0 ; + virtual bool GetOperationInfo( std::string& sName, int& nType) const = 0 ; + virtual bool GetMoveInfo( int& nGmove, double& dFeed) const = 0 ; + virtual bool AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, + const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) = 0 ; + virtual bool ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) = 0 ; + virtual bool OnCollision( int nCdInd, int nObjInd, int& nErr) = 0 ; + virtual bool SetToolForVmill( const std::string& sTool, const std::string& sHead, int nExit, int nFlag, + double dPar1, double dPar2, const INTVECTOR& vVmill, bool bFirst) = 0 ; + virtual bool EnableToolsForVmill( bool bEnable) = 0 ; + virtual int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) = 0 ; } ; diff --git a/SimulatorMP.cpp b/SimulatorMP.cpp new file mode 100644 index 0000000..5899225 --- /dev/null +++ b/SimulatorMP.cpp @@ -0,0 +1,2491 @@ +//---------------------------------------------------------------------------- +// EgalTech 2024-2024 +//---------------------------------------------------------------------------- +// File : SimulatorMP.cpp Data : 01.09.24 Versione : 2.6i1 +// Contenuto : Implementazione della classe SimulatorMP. +// Simulatore multi-processo. +// +// +// Modifiche : 01.09.24 DS Creazione modulo. +// +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "SimulatorMP.h" +#include "MachMgr.h" +#include "Disposition.h" +#include "Machining.h" +#include "MachiningConst.h" +#include "OutputConst.h" +#include "DllMain.h" +#include "/EgtDev/Include/EGkCDeBoxClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeCylClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeSpheClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeConeFrustumClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeClosedSurfTmClosedSurfTm.h" +#include "/EgtDev/Include/EGkVolZmap.h" +#include "/EgtDev/Include/EGkGeoVector3d.h" +#include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EGkSurfLocal.h" +#include "/EgtDev/Include/EXeCmdLogOff.h" +#include "/EgtDev/Include/EXeConst.h" +#include "/EgtDev/Include/EMkToolConst.h" +#include "/EgtDev/Include/EMkOperationConst.h" +#include "/EgtDev/Include/EgtPerfCounter.h" +#include "/EgtDev/Include/EgtNumUtils.h" + +using namespace std ; + +//------------------------------ Errors -------------------------------------- +// 1001 = "Error with setup : xxx" + +//---------------------------------------------------------------------------- +static const double MIN_STEP = 1.0 ; +static const double MAX_STEP = 500.0 ; +static const double MID_STEP = 50.0 ; +static const double COLL_STEP = 10. ; +static const double SQ_COEFF_ROT_MOVE = 100. ; +static const double COEFF_LIM = 0.999 ; +static const double SAFEDIST_STD = 5.0 ; +static const int ERR_OUTSTROKE = 1 ; +static const int ERR_COLLISION = 11 ; +static const int ERR_TOOL_SEL = 21 ; + +//---------------------------------------------------------------------------- +ISimulator* +CreateSimulatorMP( void) +{ + return static_cast ( new( nothrow) SimulatorMP) ; +} + +//---------------------------------------------------------------------------- +SimulatorMP::SimulatorMP( void) +{ + m_pMchMgr = nullptr ; + m_pGeomDB = nullptr ; + m_pMachine = nullptr ; + m_pPerfCnt = nullptr ; + m_nStatus = SIS_CREATED ; + m_dStep = MID_STEP ; + m_nUiStatus = MCH_UISIM_NULL ; + m_nOpId = GDB_ID_NULL ; + m_nOpInd = 0 ; + m_nCLPathId = GDB_ID_NULL ; + m_nCLPathInd = 0 ; + m_nEntId = GDB_ID_NULL ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + m_nExit = 0 ; + m_dTDiam = 0 ; + m_bCutOnTip = false ; + m_bEnableVm = false ; + m_dSafeDist = SAFEDIST_STD ; + m_nAxesMask = 0 ; + m_bEnabAxes = true ; + m_bShowAxes = true ; + m_AxesName.reserve( 8) ; + m_AxesToken.reserve( 8) ; + m_AxesLinear.reserve( 8) ; + m_AxesVal.reserve( 8) ; + m_nCmdInd = 0 ; + m_dCmdCoeff = 0 ; +} + +//---------------------------------------------------------------------------- +SimulatorMP::~SimulatorMP( void) +{ + // porto la macchina in posizione home + GoHome() ; + // gestione evento uscita dal simulatore + OnExit() ; + // rimuovo tavola variabili globali + m_pMachine->LuaResetGlobVar( GLOB_VAR) ; + // rimuovo performance counter + if ( m_pPerfCnt != nullptr) { + delete m_pPerfCnt ; + m_pPerfCnt = nullptr ; + } +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::Init( MachMgr* pMchMgr) +{ + // verifico ambiente + if ( pMchMgr == nullptr || pMchMgr->GetContextId() == 0 || + pMchMgr->GetGeomDB() == nullptr || pMchMgr->GetCurrMachine() == nullptr) + return false ; + m_pMchMgr = pMchMgr ; + m_pGeomDB = m_pMchMgr->GetGeomDB() ; + m_pMachine = m_pMchMgr->GetCurrMachine() ; + m_pPerfCnt = new PerformanceCounter ; + m_nStatus = SIS_INITIALIZED ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::Start( bool bFirst) +{ + // Verifico ci sia una macchinata corrente + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr || m_pMachine == nullptr || + m_pMchMgr->GetCurrMachGroup() == GDB_ID_NULL) + return false ; + m_pMchMgr->ResetLastError() ; + m_pMchMgr->ResetWarnings() ; + + bool bOk = true ; + + // Se appena entrati in simulazione + if ( m_nStatus == SIS_INITIALIZED) { + // Forzo aggiornamento attrezzaggio della macchinata + if ( ! m_pMchMgr->UpdateCurrSetup()) + bOk = false ; + // Verifico attrezzaggio + if ( ! VerifySetup()) + bOk = false ; + } + + // Reset utensile, interpolazione e assi correnti + m_sTool.clear() ; + m_sHead.clear() ; + m_nExit = 0 ; + m_dTDiam = 0 ; + m_bCutOnTip = false ; + ResetInterpolation() ; + ResetAxes() ; + ResetAuxAxes() ; + + // porto la macchina in home + if ( ! GoHome()) + bOk = false ; + + // Verifico la disposizione iniziale della macchinata + m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; + m_nOpInd = 1 ; + if ( m_pMchMgr->GetOperationType( m_nOpId) != OPER_DISP) + bOk = false ; + + // Definisco tabella variabili globali + if ( ! m_pMachine->LuaCreateGlobTable( GLOB_VAR)) + bOk = false ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INCHES, ! ExeUiUnitsAreMM()) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_VER, GetEMkVer()) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MACHNAME, m_pMachine->GetMachineName()) ; + + // Se appena entrati in simulazione + if ( m_nStatus == SIS_INITIALIZED) { + if ( ! OnInit()) + bOk = false ; + m_nStatus = SIS_READYTOSTART ; + } + + // Richiamo funzione per evento avvio simulazione + if ( ! OnProgramStart( bFirst)) + bOk = false ; + + // Arrivo alla preparazione per la prima lavorazione + int nStatus ; + if ( ! FindAndManageOperationStart( true, bFirst, nStatus) && nStatus != MCH_SIM_STOP) + bOk = false ; + // se sono ancora su disposizione + if ( m_pMchMgr->GetOperationType( m_nOpId) == OPER_DISP) { + // ricerca e gestione inizio percorso di lavoro + if ( ! FindAndManagePathStart( nStatus)) + return false ; + // eventuali comandi ausiliari di inizio percorso + while ( m_nAuxSInd < m_nAuxSTot) { + if ( ! ManagePathStartAux( nStatus)) + return false ; + } + // aggiornamento assi per eventuali teste caricate + UpdateAxes() ; + } + + if ( ! ExecAllCmdData( nStatus)) + return false ; + + // Reset timer + if ( m_pPerfCnt != nullptr) + m_pPerfCnt->Start() ; + + // Imposto lo stato interno + m_nStatus = ( bOk ? SIS_READYTORUN : SIS_READYTOSTART) ; + + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::VerifySetup( void) +{ + // se attrezzaggio non definito, nulla da verificare + if ( ! m_pMchMgr->GetCurrSetupMgr().Exists()) + return true ; + + // lancio la verifica + STRVECTOR vsErr ; + if ( m_pMchMgr->VerifyCurrSetup( vsErr)) + return true ; + + // gestisco errore + string sErr = "Error with setup :" ; + for ( const auto& sTmp : vsErr) + sErr += " " + sTmp ; + m_pMchMgr->SetLastError( 1001, sErr) ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ResetInterpolation( void) +{ + m_nOpId = GDB_ID_NULL ; + m_nOpInd = 0 ; + m_nCLPathId = GDB_ID_NULL ; + m_nCLPathInd = 0 ; + m_nEntId = GDB_ID_NULL ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + m_VmId.clear() ; + m_CdId.clear() ; + m_VmTool.clear() ; + m_CollObj.clear() ; + m_dSafeDist = SAFEDIST_STD ; + m_nAxesMask = 0 ; + m_bEnabAxes = true ; + m_bShowAxes = true ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::Move( int& nStatus) +{ + // Verifiche + if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr || m_nStatus != SIS_READYTORUN) { + nStatus = MCH_SIM_ERR ; + return false ; + } + + // Recupero tempo impiegato (calcolo + visualizzazione precedenti) + if ( m_pPerfCnt != nullptr && ExeGetDebugLevel() >= 5) { + double dElapsed = m_pPerfCnt->Stop() ; + string sOut = "Elapsed=" + ToString( dElapsed, 1) ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + m_pPerfCnt->Start() ; + } + + // reset visualizzazione collisioni + ResetCollisionMark() ; + + // Se arrivato alla fine dell'interpolazione + if ( m_dCoeff > COEFF_LIM) { + // recupero una nuova entità + m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; + m_dCoeff = 0 ; + } + + // Se appena arrivato alla fine di un percorso di lavoro (verifico anche completamento dei comandi aux di start per path vuote) + if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd == 0 && m_nCLPathInd > 0 && m_nAuxSInd >= m_nAuxSTot) { + // gestione fine percorso di lavoro + if ( ! ManagePathEnd( nStatus)) + return false ; + } + + // Se alla fine del percorso dopo esecuzione azioni ausiliarie (verifico anche completamento dei comandi aux di start per path vuote) + if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd >= m_nAuxETot && m_nAuxSInd >= m_nAuxSTot) { + // ricerca e gestione inizio percorso di lavoro + if ( ! FindAndManagePathStart( nStatus)) + return false ; + } + + // Se arrivato alla fine di una operazione + if ( m_nCLPathId == GDB_ID_NULL) { + // gestione fine operazione + if ( ! ManageOperationEnd( nStatus)) + return false ; + // ricerca e gestione nuova operazione + if ( ! FindAndManageOperationStart( false, false, nStatus)) + return false ; + // se non ce ne sono altre, sono alla fine + if ( m_nOpId == GDB_ID_NULL) { + OnProgramEnd() ; + nStatus = MCH_SIM_END ; + return false ; + } + // ricerca e gestione inizio percorso di lavoro + if ( ! FindAndManagePathStart( nStatus)) + return false ; + } + + // Se comandi in lista ancora da eseguire, procedo con uno step + if ( m_nCmdInd < int( m_CmdData.size())) { + return ExecCmdData( nStatus) ; + } + else { + m_CmdData.clear() ; + m_nCmdInd = 0 ; + } + + // Se sto eseguendo i movimenti ausiliari di inizio percorso + if ( m_nAuxSInd < m_nAuxSTot) + return ManagePathStartAux( nStatus) ; + + // Se sto eseguendo i movimenti ausiliari di fine percorso + if ( m_nAuxEInd < m_nAuxETot) + return ManagePathEndAux( nStatus) ; + + // Gestione movimento assi + return ManageMove( nStatus) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::GetAxisInfoPos( int nI, string& sName, string& sToken, bool& bLinear, double& dVal) const +{ + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // numero assi di calcolo e ausiliari + int nAxisCount = ( m_bShowAxes ? int( m_AxesName.size()) : 0) ; + int nAuxAxisCount = int( m_AuxAxesName.size()) ; + // recupero i dati dell'asse + if ( nI < 0 || nI >= nAxisCount + nAuxAxisCount) + return false ; + // se asse principale + if ( nI < nAxisCount) { + sName = m_AxesName[nI] ; + sToken = m_AxesToken[nI] ; + bLinear = m_AxesLinear[nI] ; + } + // altrimenti asse ausiliario + else { + sName = m_AuxAxesName[ nI - nAxisCount] ; + sToken = m_AuxAxesToken[ nI - nAxisCount] ; + bLinear = m_AuxAxesLinear[ nI - nAxisCount] ; + } + // recupero la posizione + if ( ! m_pMchMgr->GetAxisPos( sName, dVal)) + return false ; + // verifico se da invertire o offsettare + if ( nI < nAxisCount) { + if ( m_AxesInvert[nI]) + dVal = - dVal ; + dVal += m_AxesOffset[nI] ; + } + else { + if ( m_AuxAxesInvert[nI - nAxisCount]) + dVal = - dVal ; + dVal += m_AxesOffset[nI - nAxisCount] ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::GetToolInfo( string& sName, double& dSpeed) const +{ + // Inizializzo i parametri di ritorno + sName.clear() ; + dSpeed = 0 ; + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // Assegno il nome dell'utensile + sName = m_sTool ; + if ( sName.empty()) + return true ; + // Recupero speed + const Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; + return ( pMch != nullptr && pMch->GetParam( MPA_SPEED, dSpeed)) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::GetOperationInfo( string& sName, int& nType) const +{ + // Inizializzo i parametri di ritorno + sName.clear() ; + nType = OPER_NULL ; + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // Recupero il tipo + Operation* pOpe = GetOperation( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pOpe == nullptr) + return false ; + nType = pOpe->GetType() ; + // Recupero il nome + return m_pGeomDB->GetName( m_nOpId, sName) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::GetMoveInfo( int& nGmove, double& dFeed) const +{ + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // Recupero il movimento corrente + const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; + if ( pCamData == nullptr) + return false ; + // Assegno feed + dFeed = pCamData->GetFeed() ; + // Assegno tipo di movimento + nGmove = pCamData->GetMoveType() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::SetStep( double dStep) +{ + m_dStep = Clamp( dStep, MIN_STEP, MAX_STEP) ; + // imposto step per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::SetUiStatus( int nUiStatus) +{ + m_nUiStatus = nUiStatus ; + // imposto stato utente del simulatore per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMUISTAT, m_nUiStatus) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::GoHome( void) +{ + // controllo validità stato + if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr) + return false ; + // reset visualizzazione collisioni + ResetCollisionMark() ; + // reset stato macchina + OnResetMachine() ; + // porto la macchina in home + m_pMchMgr->ResetAllAxesPos() ; + // assegno valori home degli assi macchina attivi + return m_pMchMgr->GetAllCurrAxesHomePos( m_AxesVal) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::UpdateTool( bool bFirst, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // Recupero l'utensile della lavorazione corrente + Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pMch != nullptr) { + // recupero nome e dati nuovo utensile + string sTuuid, sTool ; + if ( ! pMch->GetParam( MPA_TUUID, sTuuid) || + ! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool)) + return false ; + string sTcPos ; string sHead ; int nExit ; + if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) { + if ( m_pMchMgr->TdbSetCurrTool( sTool)) { + m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ; + m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ; + m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ; + } + // ripristino l'utensile corrente + m_pMchMgr->TdbSetCurrTool( m_sTool) ; + } + // verifico se cambierà + bool bDiffTool = ( sTool != m_sTool) ; + // se cambierà ed esiste il corrente, lo scarico + if ( bDiffTool && ! m_sTool.empty()) { + // eventuale lancio script per scarico utensile + int nCurrErr ; + if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + // se prima volta, pulisco la testa + if ( bFirst) + m_pMchMgr->ResetHeadSet( sHead) ; + // recupero la lavorazione corrente e imposto la nuova + int nCurrMchId = m_pMchMgr->GetCurrMachining() ; + m_pMchMgr->SetCurrMachining( m_nOpId) ; + // carico l'utensile (e lo rendo corrente) + if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) + return false ; + m_sTool = sTool ; + m_sHead = sHead ; + m_nExit = nExit ; + m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; + double dTipFeed = 0 ; + m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; + m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; + // ripristino la lavorazione corrente + m_pMchMgr->SetCurrMachining( nCurrMchId) ; + // aggiorno gli assi macchina + if ( ! UpdateAxes()) + return false ; + // se cambiato oppure prima volta, lancio lo script di selezione + if ( bDiffTool || bFirst) { + int nCurrErr ; + if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + return ( nErr == 0) ; + } + // Provo con una disposizione + Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pDisp != nullptr) { + // recupero i dati + string sTool ; string sHead ; int nExit ; string sTcPos ; + pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ; + // se esiste utensile corrente e cambierà, lo scarico + if ( ! m_sTool.empty() && sTool != m_sTool) { + // eventuale lancio script per scarico utensile + int nCurrErr ; + if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + // carico l'utensile + if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) + return false ; + m_sTool = sTool ; + m_sHead = sHead ; + m_nExit = nExit ; + m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; + double dTipFeed = 0 ; + m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; + m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; + // aggiorno gli assi macchina + if ( ! UpdateAxes()) + return false ; + // eventuale lancio script + int nCurrErr ; + if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + return ( nErr == 0) ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::UpdateAxes( void) +{ + ResetAxes() ; + // Macchina corrente + Machine* pMachine = m_pMchMgr->GetCurrMachine() ; + if ( pMachine == nullptr) + return false ; + // Carico i nomi e i token degli assi macchina attivi + if ( ! pMachine->GetAllCurrAxesNames( m_AxesName) || + ! pMachine->GetAllCurrAxesTokens( m_AxesToken)) + return false ; + // Aggiorno flag di invertito, offset, tipo e posizione corrente degli assi macchina attivi + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + bool bInvert ; + m_pMachine->GetAxisInvert( m_AxesName[i], bInvert) ; + m_AxesInvert.push_back( bInvert) ; + double dOffset ; + m_pMachine->GetAxisOffset( m_AxesName[i], dOffset) ; + m_AxesOffset.push_back( dOffset) ; + bool bLinear ; + m_pMachine->GetAxisType( m_AxesName[i], bLinear) ; + m_AxesLinear.push_back( bLinear) ; + double dVal ; + m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; + m_AxesVal.emplace_back( dVal) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::UpdateAxesPos( void) +{ + // Macchina corrente + Machine* pMachine = m_pMchMgr->GetCurrMachine() ; + if ( pMachine == nullptr) + return false ; + // Aggiorno la posizione corrente degli assi macchina attivi + m_AxesVal.clear() ; + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + double dVal ; + m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; + m_AxesVal.emplace_back( dVal) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ResetAxes( void) +{ + // pulisco dati assi + m_AxesName.clear() ; + m_AxesToken.clear() ; + m_AxesInvert.clear() ; + m_AxesLinear.clear() ; + m_AxesVal.clear() ; + m_nAxesMask = 0 ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ResetAuxAxes( void) +{ + // pulisco dati assi ausiliari + m_AuxAxesName.clear() ; + m_AuxAxesToken.clear() ; + m_AuxAxesInvert.clear() ; + m_AuxAxesOffset.clear() ; + m_AuxAxesLinear.clear() ; + m_AuxAxesVal.clear() ; + m_AuxAxesEnd.clear() ; + m_AuxAxesLink.clear() ; + // abilito assi principali + m_bEnabAxes = true ; + m_bShowAxes = true ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) +{ + // verifico parametri + if ( ! bStart) + bFirst = false ; + // recupero la nuova operazione + if ( bStart) { + m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; + m_nOpInd = 0 ; + } + else + m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; + // ciclo sulle successive operazioni + while ( m_nOpId != GDB_ID_NULL) { + // se lavorazione valida + Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pMch != nullptr && ! pMch->IsEmpty()) { + bool bOk = true ; + // aggiorno utensile e assi conseguenti + int nErr ; + if ( ! UpdateTool( bFirst, nErr)) { + string sOut = "Err=" + ToString( nErr) ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) + nStatus = CalcStatusOnError( nErr) ; + bOk = false ; + } + ++ m_nOpInd ; + // imposto la lavorazione come corrente + m_pMchMgr->SetCurrMachining( m_nOpId) ; + // recupero punti di minimo e massimo ingombro + int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; + Point3d ptMin, ptMax ; + m_pGeomDB->GetInfo( nClId, KEY_MMIN, ptMin) ; + m_pGeomDB->GetInfo( nClId, KEY_MMAX, ptMax) ; + DBLVECTOR vAxMin, vAxMax ; + m_pGeomDB->GetInfo( nClId, KEY_MAXMIN, vAxMin) ; + m_pGeomDB->GetInfo( nClId, KEY_MAXMAX, vAxMax) ; + // richiamo gestione evento inizio lavorazione + if ( ! OnMachiningStart( m_nOpId, m_nOpInd, ptMin, ptMax, vAxMin, vAxMax)) { + nStatus = CalcStatusOnError( 0) ; + bOk = false ; + } + if ( ! bOk) + return false ; + break ; + } + // se disposizione con cambio di fase + Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pDisp != nullptr) { + // in alcuni casi la disposizione non è inizializzata + pDisp->Init( m_pMchMgr) ; + // recupero dati tavola + string sTable ; + pDisp->GetTable( sTable) ; + Point3d ptOri1 ; + pDisp->GetTableRef1( ptOri1) ; + // recupero la fase della disposizione + int nPhase = pDisp->GetPhase() ; + // recupero se con movimenti autonomi + bool bEmpty = pDisp->IsEmpty() ; + // recupero flag disposizione con movimenti manuali + bool bSomeByHand = pDisp->GetSomeByHand() ; + // se con movimenti autonomi + if ( ! bEmpty) { + // richiamo gestione evento appena prima di inizio disposizione + if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // cambio fase + m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; + // se previsto, aggiorno utensile e assi conseguenti + if ( pDisp->IsWithTool()) { + int nErr ; + if ( ! UpdateTool( bFirst, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + } + ++ m_nOpInd ; + // richiamo gestione evento inizio disposizione + if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // se ci sono movimenti manuali, aggiorno visualizzazione e breve pausa (200 ms) + if ( bSomeByHand) + Sleep( 200) ; + break ; + } + // altrimenti disposizione passiva + else { + // richiamo gestione evento appena prima di inizio disposizione + if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // cambio fase + m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; + ++ m_nOpInd ; + // richiamo gestione evento inizio e fine disposizione + if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) || + ! OnDispositionEnd()) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) + if ( nPhase != 1) { + ExeDraw() ; + Sleep( 200) ; + } + } + } + // passo alla operazione successiva + m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ManageOperationEnd( int& nStatus) +{ + bool bOk = false ; + // non c'è operazione in corso (solo prima disposizione senza lavorazioni) + if ( m_nOpId == GDB_ID_NULL) + bOk = true ; + // se altrimenti è una lavorazione + else if ( GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { + // richiamo gestione evento fine lavorazione + bOk = OnMachiningEnd() ; + } + // se altrimenti è una disposizione + else if ( GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { + // richiamo gestione evento fine disposizione + bOk = OnDispositionEnd() ; + } + // gestione stato + if ( ! bOk) + nStatus = CalcStatusOnError( 0) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::FindAndManagePathStart( int& nStatus) +{ + // se devo cercare il primo nella nuova operazione + if ( m_nCLPathId == GDB_ID_NULL) { + // aggiorno gli altri dati + int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; + m_nCLPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ; + m_nCLPathInd = 0 ; + m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + } + // altrimenti cerco il successivo nella stessa operazione + else { + // recupero un nuovo CLpath + while ( m_nEntId == GDB_ID_NULL) { + m_nCLPathId = m_pGeomDB->GetNextGroup( m_nCLPathId) ; + // se non ce ne sono altri, devo passare a una nuova lavorazione + if ( m_nCLPathId == GDB_ID_NULL) + break ; + m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + } + } + // se trovato nuovo CLpath con entità, gestisco inizio percorso di lavoro + if ( m_nEntId != GDB_ID_NULL) { + ++ m_nCLPathInd ; + // recupero punti di inizio e fine percorso + Point3d ptStart ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_START, ptStart) ; + Point3d ptEnd ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_END, ptEnd) ; + // recupero versore estrusione associato al percorso (normale al piano di interpolazione) + Vector3d vtExtr ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_EXTR, vtExtr) ; + // recupero punti di minimo e massimo ingombro + Point3d ptMin, ptMax ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMIN, ptMin) ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMAX, ptMax) ; + // Recupero valori degli assi di minimo e massimo ingombro + DBLVECTOR vAxMin, vAxMax ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMIN, vAxMin) ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMAX, vAxMax) ; + // recupero massima elevazione + double dElev = 0 ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_ELEV, dElev) ; + // recupero il numero di eventi ausiliari di inizio + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + // reset numero eventi ausiliari di fine + m_nAuxEInd = 0 ; + m_nAuxETot = 0 ; + // richiamo gestione evento inizio percorso di lavoro + if ( ! OnPathStart( m_nCLPathId, m_nCLPathInd, m_nAuxSTot, ptStart, ptEnd, vtExtr, ptMin, ptMax, vAxMin, vAxMax, dElev)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + } + // se altrimenti trovato nuovo CL path vuoto + else if ( m_nCLPathId != GDB_ID_NULL) { + // recupero il numero di eventi ausiliari di inizio + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + // recupero il numero di eventi ausiliari di fine + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ManagePathEnd( int& nStatus) +{ + // recupero il numero di eventi ausiliari di fine + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + // richiamo gestione evento fine percorso di lavoro + bool bOk = OnPathEnd( m_nAuxETot) ; + // gestione stato + if ( ! bOk) + nStatus = CalcStatusOnError( 0) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ManagePathStartAux( int& nStatus) +{ + // aggiorno indice corrente + ++ m_nAuxSInd ; + // recupero i dati per l'evento corrente + string sAS ; + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS + ToString( m_nAuxSInd), sAS)) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // richiamo gestione evento ausiliario prima di inizio percorso di lavoro + int nErr ; + if ( ! OnPathStartAux( m_nAuxSInd, sAS, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + nStatus = MCH_SIM_END_STEP ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ManagePathEndAux( int& nStatus) +{ + // aggiorno indice corrente + ++ m_nAuxEInd ; + // recupero i dati per l'evento corrente + string sAE ; + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE + ToString( m_nAuxEInd), sAE)) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // richiamo gestione evento ausiliario dopo fine percorso di lavoro + int nErr ; + if ( ! OnPathEndAux( m_nAuxEInd, sAE, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + nStatus = MCH_SIM_END_STEP ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ManageMove( int& nStatus) +{ + // Imposto lunghezza di movimento effettuata + double dCurrMove = 0 ; + while ( m_nEntId != GDB_ID_NULL) { + // eseguo movimento singolo + double dMove ; + if ( ! ManageSingleMove( nStatus, dMove)) + return false ; + dCurrMove += dMove ; + // se modalità play e fine entità e non raggiunta la lunghezza di movimento voluto + if ( m_nUiStatus == MCH_UISIM_PLAY && nStatus == MCH_SIM_END_STEP && dCurrMove < 0.75 * m_dStep) { + // recupero una nuova entità + m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; + m_dCoeff = 0 ; + } + else + break ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ManageSingleMove( int& nStatus, double& dMove) +{ + // Recupero posizione finale + const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; + if ( pCamData == nullptr) { + nStatus = MCH_SIM_ERR ; + return false ; + } + switch ( pCamData->GetAxesStatus()) { + case CamData::AS_OK : + break ; + case CamData::AS_OUTSTROKE : { + DBLVECTOR OutAxes = pCamData->GetAxesVal() ; + for ( size_t i = OutAxes.size() ; i < 5 ; ++ i) + OutAxes.emplace_back( 0) ; + DBLVECTOR vAng( OutAxes.begin() + 3, OutAxes.end()) ; + int nStat ; + m_pMachine->VerifyOutstroke( OutAxes[0], OutAxes[1], OutAxes[2], vAng, true, nStat) ; + nStatus = MCH_SIM_OUTSTROKE ; + return false ; } + case CamData::AS_DIR_ERR : + nStatus = MCH_SIM_DIR_ERR ; + return false ; + default : + nStatus = MCH_SIM_ERR ; + return false ; + } + DBLVECTOR AxesEnd = pCamData->GetAxesVal() ; + // Tipo di movimento + int nMoveType = pCamData->GetMoveType() ; + // Se inizio di nuova entità, mascheratura movimento + if ( m_nEntId != GDB_ID_NULL && m_dCoeff < EPS_ZERO) + m_nAxesMask = pCamData->GetAxesMask() ; + // Se movimento in rapido muovo solo gli assi abilitati dal mask + if ( nMoveType == 0) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + if ( ( m_nAxesMask & 1 << i) == 0) + AxesEnd[i] = m_AxesVal[i] ; + } + } + + // Se inizio di nuova entità + if ( m_nEntId != GDB_ID_NULL && m_dCoeff < EPS_ZERO) { + ++ m_nEntInd ; + const CamData* pNextCamData = GetCamData( m_pGeomDB->GetUserObj( m_pGeomDB->GetNext( m_nEntId))) ; + int nErr ; + if ( ! OnMoveStart( pCamData, pNextCamData, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + // Se movimento in rapido aggiorno quote degli assi disabilitati dal mask + if ( nMoveType == 0) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + if ( ( m_nAxesMask & 1 << i) == 0) + AxesEnd[i] = m_AxesVal[i] ; + } + } + } + + // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) + bool bOkI = true ; + PNTVECTOR vPtNoseI( m_VmTool.size()) ; + VCT3DVECTOR vVtDirI( m_VmTool.size()) ; + VCT3DVECTOR vVtAuxI( m_VmTool.size()) ; + for ( int i = 0 ; i < int( m_VmTool.size()) ; ++ i) + bOkI = GetHeadCurrPosDirAux( m_VmTool[i].sHead, m_VmTool[i].nExit, vPtNoseI[i], vVtDirI[i], vVtAuxI[i]) && bOkI ; + vector vFrVzmI( m_VmId.size()) ; + for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i) + bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ; + + // Dati per eventuale verifica di collisione + int nCdInd, nObjInd ; + bool bCollCheck = true ; + + // Eseguo movimento assi principali ed eventuali ausiliari + if ( m_bEnabAxes) { + // Calcolo distanza di movimento + double dSqDist = 0 ; + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + // coefficiente moltiplicativo per differenziare assi lineari e rotanti + double dSqCoeff = ( m_AxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; + dSqDist += dSqCoeff * ( AxesEnd[i] - m_AxesVal[i]) * ( AxesEnd[i] - m_AxesVal[i]) ; + } + // Calcolo distanza di movimento eventuali assi ausiliari + double dSqDistAux = 0 ; + for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { + if ( m_AuxAxesLink[i] != 0) + continue ; + // coefficiente moltiplicativo per differenziare assi lineari e rotanti + double dSqCoeff = ( m_AuxAxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; + dSqDistAux += dSqCoeff * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) ; + } + // Considero il massimo delle due distanze + double dPrevCoeff = m_dCoeff ; + double dDist = sqrt( max( dSqDist, dSqDistAux)) ; + if ( dDist > EPS_SMALL) { + double dStep = min( ( nMoveType == 0 ? 2 : 1) * m_dStep, MAX_STEP) ; + int nStep = max( int( dDist / dStep), 1) ; + m_dCoeff += 1. / nStep ; + if ( m_dCoeff > 1) + m_dCoeff = 1 ; + } + else + m_dCoeff = 1 ; + dMove = ( m_dCoeff - dPrevCoeff) * dDist ; + + // Log per debug + if ( ExeGetDebugLevel() >= 10) { + string sOut = "MoveType=" + ToString( nMoveType) + " Coeff=" + ToString( m_dCoeff) ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + } + + // Eseguo movimento rapido o lineare (non arco) + if ( nMoveType != 2 && nMoveType != 3) { + // se attivo CollisionCheck approssimo movimento con più step + int nStep = 1 ; + if ( NeedCollisionCheck()) + nStep = max( int( dMove / COLL_STEP), 1) ; + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; + DBLVECTOR vDeltaVal( m_AxesName.size()) ; + // assegno posizioni finali + for ( int j = 0 ; j < int( m_AxesName.size()) ; ++ j) { + double dPrevVal ; + m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ; + double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; + m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; + vDeltaVal[j] = dVal - dPrevVal ; + } + // muovo eventuali assi ausiliari + for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { + double dVal = 0 ; + if ( m_AuxAxesLink[j] == 0) { + dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; + } + else { + m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ; + if ( m_AuxAxesLink[j] > 0) + dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ; + else + dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ; + } + m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; + } + // se abilitato e non è rapido o non c'è verifica collisioni, eseguo eventuale Vmill + if ( m_bEnableVm && ( nMoveType != 0 || ! NeedCollisionCheck())) { + for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + } + // eseguo eventuale collision check + bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + } + } + // Eseguo movimento su arco + else { + // dati dell'arco + Point3d ptCen = pCamData->GetAxesCen() ; + double dAngCen = pCamData->GetAxesAngCen() ; + double dRad = pCamData->GetAxesRad() ; + Vector3d vtN = pCamData->GetAxesNormDir() ; + double dDeltaN = ( Point3d( AxesEnd[0], AxesEnd[1], AxesEnd[2]) - ptCen) * vtN ; + double dDiffAng = ( m_dCoeff - dPrevCoeff) * dAngCen ; + Vector3d vtRot = Point3d( m_AxesVal[0], m_AxesVal[1], m_AxesVal[2]) - ptCen ; + vtRot.Rotate( vtN, dPrevCoeff * dAngCen) ; + // se attivi Vmill o CollisionCheck approssimo movimento con più step + int nStep = 1 ; + if ( ! m_VmId.empty() || NeedCollisionCheck()) { + const double MIN_LEN_STEP = 2. ; + const double MAX_LEN_STEP = 10. ; + double dLenStep = Clamp( 0.1 * m_dTDiam, MIN_LEN_STEP, MAX_LEN_STEP) ; + nStep = max( int( abs( dDiffAng * DEGTORAD * dRad) / dLenStep), 1) ; + const double ANG_STEP = 5. ; + if ( abs( dDiffAng) / nStep > ANG_STEP) + nStep = int( abs( dDiffAng) / ANG_STEP) ; + } + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; + DBLVECTOR vDeltaVal( m_AxesName.size()) ; + // assi lineari + vtRot.Rotate( vtN, dDiffAng / nStep) ; + double dPrevVal, dVal ; + m_pMachine->GetAxisPos( m_AxesName[0], dPrevVal) ; + dVal = ptCen.x + vtRot.x + dCurrCoeff * dDeltaN * vtN.x ; + m_pMachine->SetAxisPos( m_AxesName[0], dVal) ; + vDeltaVal[0] = dVal - dPrevVal ; + m_pMachine->GetAxisPos( m_AxesName[1], dPrevVal) ; + dVal = ptCen.y + vtRot.y + dCurrCoeff * dDeltaN * vtN.y ; + m_pMachine->SetAxisPos( m_AxesName[1], dVal) ; + vDeltaVal[1] = dVal - dPrevVal ; + m_pMachine->GetAxisPos( m_AxesName[2], dPrevVal) ; + dVal = ptCen.z + vtRot.z + dCurrCoeff * dDeltaN * vtN.z ; + m_pMachine->SetAxisPos( m_AxesName[2], dVal) ; + vDeltaVal[2] = dVal - dPrevVal ; + // assi rotanti + for ( int j = 3 ; j < int( m_AxesName.size()) ; ++ j) { + double dPrevVal ; m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ; + double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; + m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; + vDeltaVal[j] = dVal - dPrevVal ; + } + // eventuali assi ausiliari + for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { + double dVal = 0 ; + if ( m_AuxAxesLink[j] == 0) { + dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; + } + else { + m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ; + if ( m_AuxAxesLink[j] > 0) + dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ; + else + dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ; + } + m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; + } + // se abilitato, eseguo eventuale Vmill + for ( int j = 0 ; m_bEnableVm && j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + // eseguo eventuale collision check + bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + } + } + } + + // altrimenti eseguo movimento soli eventuali assi ausiliari + else { + // Calcolo distanza di movimento + double dSqDist = 0 ; + for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { + // coefficiente moltiplicativo per differenziare assi lineari e rotanti + double dSqCoeff = ( m_AuxAxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; + dSqDist += dSqCoeff * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) ; + } + double dPrevCoeff = m_dCoeff ; + double dDist = sqrt( dSqDist) ; + if ( dDist > EPS_SMALL) { + double dStep = min( ( nMoveType == 0 ? 2 : 1) * m_dStep, MAX_STEP) ; + int nStep = max( int( dDist / dStep), 1) ; + m_dCoeff += 1. / nStep ; + if ( m_dCoeff > 1) + m_dCoeff = 1 ; + } + else + m_dCoeff = 1 ; + dMove = ( m_dCoeff - dPrevCoeff) * dDist ; + // se attivo CollisionCheck approssimo movimento con più step + int nStep = 1 ; + if ( NeedCollisionCheck()) + nStep = max( int( dMove / COLL_STEP), 1) ; + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; + // muovo eventuali assi ausiliari + for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { + if ( m_AuxAxesLink[j] == 0) { + double dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; + m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; + } + } + // se abilitato e non è rapido o non c'è verifica collisioni, eseguo eventuale Vmill + if ( m_bEnableVm && ( nMoveType != 0 || ! NeedCollisionCheck())) { + for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + } + // eseguo eventuale collision check + bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + } + } + + // Se riscontrata collisione + if ( ! bCollCheck) { + // Richiamo funzione di convalida collisione + int nErr ; + if ( ! OnCollision( nCdInd, nObjInd, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + // Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo + if ( m_dCoeff > COEFF_LIM) { + if ( m_bEnabAxes) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) + m_AxesVal[i] = AxesEnd[i] ; + } + // richiamo gestione evento fine entità, senza gestirne eventuali errori + int nErr ; + OnMoveEnd( nErr) ; + } + return false ; + } + } + + // Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo + if ( m_dCoeff > COEFF_LIM) { + if ( m_bEnabAxes) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) + m_AxesVal[i] = AxesEnd[i] ; + } + nStatus = MCH_SIM_END_STEP ; + // richiamo gestione evento fine entità + int nErr ; + if ( ! OnMoveEnd( nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + } + // Altrimenti sto muovendomi all'interno dell'entità + else + nStatus = MCH_SIM_OK ; + + return true ; +} + +//---------------------------------------------------------------------------- +int +SimulatorMP::CalcStatusOnError( int nErr) +{ + if ( Stopped()) + return MCH_SIM_STOP ; + else if ( nErr == ERR_OUTSTROKE) + return MCH_SIM_OUTSTROKE ; + else if ( nErr == ERR_COLLISION) + return MCH_SIM_COLLISION ; + else + return MCH_SIM_ERR ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA) +{ + int nHeadId = m_pMachine->GetHeadId( sHead) ; + int nExitId = m_pMachine->GetExitId( sHead, nExit) ; + if ( nHeadId == GDB_ID_NULL || nExitId == GDB_ID_NULL) + return false ; + Frame3d frExit ; m_pGeomDB->GetGroupGlobFrame( nExitId, frExit) ; + ptH = frExit.Orig() ; + vtH = frExit.VersZ() ; + vtA = V_NULL ; + int nDirAuxId = m_pGeomDB->GetFirstNameInGroup( nHeadId, MCH_AUX_VECT) ; + if ( nDirAuxId != GDB_ID_NULL) { + const IGeoVector3d* pGV = GetGeoVector3d( m_pGeomDB->GetGeoObj( nDirAuxId)) ; + if ( pGV != nullptr) { + Frame3d frHead ; m_pGeomDB->GetGroupGlobFrame( nHeadId, frHead) ; + vtA = pGV->GetVector() ; + vtA.ToGlob( frHead) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, + const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) +{ + // Recupero Zmap + IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( nVmId)) ; + if ( pVZM == nullptr) { + string sOut = " --> GetVolZmap (" + ToString( nVmId) +") Error <--" ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + return false ; + } + // Porto gli estremi nel riferimento opportuno dello Zmap + Point3d ptHiL = ptHi ; ptHiL.ToLoc( frVzmI) ; + Vector3d vtHiL = vtHi ; vtHiL.ToLoc( frVzmI) ; + Vector3d vtAiL = vtAi ; vtAiL.ToLoc( frVzmI) ; + Point3d ptHfL = ptHf ; ptHfL.ToLoc( frVzmF) ; + Vector3d vtHfL = vtHf ; vtHfL.ToLoc( frVzmF) ; + Vector3d vtAfL = vtAf ; vtAfL.ToLoc( frVzmF) ; + // Eventuali offset + ptHiL += dVmTdOffs * vtHiL + dVmAdOffs * vtAiL ; + ptHfL += dVmTdOffs * vtHfL + dVmAdOffs * vtAfL ; + // Log per debug + if ( ExeGetDebugLevel() >= 10) { + string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) + + " Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + + ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + } + // Se utensile che non lavora di testa + if ( ! m_bCutOnTip) { + // se movimento di testa (angolo movimento verso la testa oltre 5.8deg), non eseguo asportazione + Vector3d vtDirM = Media( vtHiL, vtHfL) ; + vtDirM.Normalize() ; + double dAxMove = ( ptHfL - ptHiL) * vtDirM ; + if ( dAxMove < -EPS_SMALL) { + double dMove = ( ptHfL - ptHiL).Len() ; + if ( dAxMove < -0.1 * abs( dMove)) + return true ; + } + } + // Eseguo + bool bOk = pVZM->MillingStep( nCurrTool, ptHiL, vtHiL, vtAiL, ptHfL, vtHfL, vtAfL) ; + if ( ! bOk) { + if ( ExeGetDebugLevel() < 10) { + string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) + + " Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + + ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + } + LOG_DBG_INFO( GetEMkLogger(), " --> MillingStep Error <--") + } + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) +{ + // se non ci sono oggetti da controllare o non ci sono grezzi o equivalenti, tutto bene + if ( ! NeedCollisionCheck()) + return true ; + // ciclo sui grezzi o equivalenti + for ( int i = 0 ; i < int( m_CdId.size()) ; ++ i) { + // se modo hidden è da saltare + int nMode ; + if ( m_pGeomDB->GetCalcMode( m_CdId[i], nMode) && nMode == GDB_MD_HIDDEN) + continue ; + // verifico se è il grezzo in lavorazione + bool bIsRaw = ( find( m_VmId.begin(), m_VmId.end(), m_CdId[i]) != m_VmId.end()) ; + // recupero solido o trimesh, se altro lo salto + const IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( m_CdId[i])) ; + const ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeomDB->GetGeoObj( m_CdId[i])) ; + if ( pVZM == nullptr && pSTM == nullptr) + continue ; + // recupero il riferimento + Frame3d frCd ; m_pGeomDB->GetGlobFrame( m_CdId[i], frCd) ; + // ciclo sugli oggetti con cui verificare + for ( int j = 0 ; j < int( m_CollObj.size()) ; ++ j) { + // se modo hidden è da saltare + int nMode ; + if ( m_pGeomDB->GetCalcMode( m_CollObj[j].nFrameId, nMode) && nMode == GDB_MD_HIDDEN) + continue ; + // verifico se è l'utensile attivo + string sHead ; m_pGeomDB->GetName( m_pGeomDB->GetParentId( m_CollObj[j].nFrameId), sHead) ; + string sExit ; m_pGeomDB->GetName( m_CollObj[j].nFrameId, sExit) ; + bool bIsTool = m_CollObj[j].bToolOn || + ( sHead == m_sHead && ( sExit == "_T" + ToString( m_nExit) || sExit == "_TT" + ToString( m_nExit))) ; + // se utensile attivo su grezzo in lavoro e non è rapido, salto + if ( bIsTool && bIsRaw && nMoveType != 0) + continue ; + // esecuzione controlli di collisione + bool bOk = true ; + // oggetti che richiedono frame associato (Box, Cylinder, Sphere, Cone) + if ( m_CollObj[j].nType != MCH_SIM_COB_POLY) { + // se riferimento non trovato, si salta + const IGeoFrame3d* pGeoFrame = GetGeoFrame3d( m_pGeomDB->GetGeoObj( m_CollObj[j].nFrameId)) ; + if ( pGeoFrame == nullptr) + continue ; + Frame3d frObj = pGeoFrame->GetFrame() ; + if ( ! m_CollObj[j].vtMove.IsSmall()) + frObj.Translate( m_CollObj[j].vtMove.x * frObj.VersX() + + m_CollObj[j].vtMove.y * frObj.VersY() + + m_CollObj[j].vtMove.z * frObj.VersZ()) ; + Frame3d frParent ; m_pGeomDB->GetGlobFrame( m_CollObj[j].nFrameId, frParent) ; + frObj.LocToLoc( frParent, frCd) ; + // controlli di collisione + if ( m_CollObj[j].nType == MCH_SIM_COB_BOX) { + Vector3d vtDiag( m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3) ; + if ( pVZM != nullptr) + bOk = ! pVZM->CDeBox( frObj, vtDiag, m_dSafeDist) ; + else + bOk = ! CDeBoxClosedSurfTm( frObj, vtDiag, *pSTM, m_dSafeDist) ; + } + else if ( m_CollObj[j].nType == MCH_SIM_COB_CYL) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeCylinder( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_dSafeDist) ; + else + bOk = ! CDeCylClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, *pSTM, m_dSafeDist) ; + } + else if ( m_CollObj[j].nType == MCH_SIM_COB_SPHE) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeSphere( frObj.Orig(), m_CollObj[j].dPar1, m_dSafeDist) ; + else + bOk = ! CDeSpheClosedSurfTm( frObj.Orig(), m_CollObj[j].dPar1, *pSTM, m_dSafeDist) ; + } + else if ( m_CollObj[j].nType == MCH_SIM_COB_CONE) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeConeFrustum( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3, m_dSafeDist) ; + else + bOk = ! CDeConeFrustumClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3, *pSTM, m_dSafeDist) ; + } + } + // altrimenti poliedro + else { + SurfLocal SurfLoc( m_pGeomDB, m_CollObj[j].nFrameId, frCd) ; + const ISurfTriMesh* pStmLoc = GetSurfTriMesh( SurfLoc) ; + if ( pStmLoc != nullptr) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeSurfTm( *pStmLoc, m_dSafeDist) ; + else + bOk = ! CDeClosedSurfTmClosedSurfTm( *pStmLoc, *pSTM, m_dSafeDist) ; + } + else + bOk = false ; + } + // se trovata collisione + if ( ! bOk) { + nCdInd = i ; + nObjInd = j ; + return false ; + } + } + } + return true ; +} + +//---------------------------------------------------------------------------- +static int +FindCollisionMarkId( const IGeomDB* pGeomDB, int nCollId) +{ + int nCollParId = pGeomDB->GetParentId( nCollId) ; + string sCollParName = "COLLISION" ; + pGeomDB->GetName( nCollParId, sCollParName) ; + if ( sCollParName != "COLLISION") + return nCollParId ; + else { + int nCollGprId = pGeomDB->GetParentId( nCollParId) ; + int nCollSolId = pGeomDB->GetFirstNameInGroup( nCollGprId, "SOLID") ; + if ( nCollSolId != GDB_ID_NULL) + return nCollSolId ; + else + return nCollGprId ; + } +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::SetCollisionMark( int nCdInd, int nObjInd) +{ + if ( m_pGeomDB == nullptr) + return false ; + m_nCollMarkId.clear() ; + int nCdMarkId = FindCollisionMarkId( m_pGeomDB, m_CdId[nCdInd]) ; + m_pGeomDB->SetMark( nCdMarkId, GDB_MK_ON) ; + m_nCollMarkId.push_back( nCdMarkId) ; + int nCoMarkId = FindCollisionMarkId( m_pGeomDB, m_CollObj[nObjInd].nFrameId) ; + m_pGeomDB->SetMark( nCoMarkId, GDB_MK_ON_2) ; + m_nCollMarkId.push_back( nCoMarkId) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ResetCollisionMark( void) +{ + if ( m_pGeomDB == nullptr) + return false ; + for ( auto nId : m_nCollMarkId) + m_pGeomDB->ResetMark( nId) ; + m_nCollMarkId.clear() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnInit( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_INIT)) + return true ; + // chiamo la funzione di ingresso nella simulazione + return m_pMachine->LuaCallFunction( ON_SIMUL_INIT) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnExit( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_EXIT)) + return true ; + // chiamo la funzione di uscita dalla simulazione + return m_pMachine->LuaCallFunction( ON_SIMUL_EXIT) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnProgramStart( bool bFirst) +{ + // assegno flag inizio simulazione + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIM1ST, bFirst) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_START)) + return true ; + // chiamo la funzione di inizio simulazione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_START) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnProgramEnd( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_END)) + return true ; + // chiamo la funzione di fine simulazione + return m_pMachine->LuaCallFunction( ON_SIMUL_END) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnDispositionStarting( int nOpId, int nOpInd, int nPhase, + const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) +{ + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; + // assegno nuovo indice di fase + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; + // assegno nome e valore riferimento della tavola corrente + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; + // assegno flag disposizione passiva + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; + // assegno flag disposizione con operazioni manuali + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_STARTING)) + return true ; + // chiamo la funzione di inizio disposizione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_STARTING) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnDispositionStart( int nOpId, int nOpInd, int nPhase, + const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) +{ + // assegno identificativo e indice disposizione + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; + // assegno nuovo indice di fase + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; + // assegno nome e valore riferimento della tavola corrente + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; + // assegno flag disposizione passiva + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; + // assegno flag disposizione con operazioni manuali + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_START)) + return true ; + // chiamo la funzione di inizio disposizione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_START) ; + // recupero i dati di ritorno + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnDispositionEnd( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_END)) + return true ; + // chiamo la funzione di fine disposizione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_END) ; + // recupero i dati di ritorno + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnToolSelect( const string& sTool, const string& sHead, int nExit, const string& sTcPos, + bool bFirst, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // reset oggetti per verifica collisione con grezzo + m_CollObj.clear() ; + // assegno il nome dell'utensile, la testa e l'uscita + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TOOL, sTool) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_HEAD, sHead) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXIT, nExit) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TCPOS, sTcPos)) + return false ; + // assegno il token e il nome degli assi + bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; + int nNumAxes = int( m_AxesName.size()) ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) { + if ( i <= nNumAxes) { + if ( ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisToken( i, bIsRobot), m_AxesToken[i-1]) || + ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisName( i, bIsRobot), m_AxesName[i-1])) + return false ; + } + else { + if ( ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisToken( i, bIsRobot)) || + ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisName( i, bIsRobot))) + return false ; + } + } + // assegno il flag di chiamata di utensile iniziale + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FIRST, bFirst)) + return false ; + // reset errore + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) + return false ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_SELECT)) + return true ; + // chiamo la funzione di selezione utensile + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_SELECT) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // recupero dati per verifica collisione + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SAFEDIST, m_dSafeDist) ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // recupero i dati di ritorno per assi ausiliari + ResetAuxAxes() ; + int nNumAuxAxes = 0 ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) + return ( bOk && nErr == 0) ; + m_AuxAxesName.reserve( nNumAuxAxes) ; + m_AuxAxesToken.reserve( nNumAuxAxes) ; + m_AuxAxesInvert.reserve( nNumAuxAxes) ; + m_AuxAxesOffset.reserve( nNumAuxAxes) ; + m_AuxAxesLinear.reserve( nNumAuxAxes) ; + m_AuxAxesVal.reserve( nNumAuxAxes) ; + m_AuxAxesEnd.reserve( nNumAuxAxes) ; + for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) { + string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; + string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ; + if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) && + m_pMachine->GetAxisToken( sName, sToken) && + m_pMachine->GetAxisInvert( sName, bInvert) && + m_pMachine->GetAxisOffset( sName, dOffset) && + m_pMachine->GetAxisType( sName, bLinear) && + m_pMachine->GetAxisPos( sName, dVal)) { + // se non è già negli assi principali, lo aggiungo + if ( find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) { + m_AuxAxesName.emplace_back( sName) ; + m_AuxAxesToken.emplace_back( sToken) ; + m_AuxAxesInvert.push_back( bInvert) ; + m_AuxAxesOffset.push_back( dOffset) ; + m_AuxAxesLinear.push_back( bLinear) ; + m_AuxAxesVal.emplace_back( dVal) ; + m_AuxAxesEnd.emplace_back( dVal) ; + m_AuxAxesLink.emplace_back( 0) ; + } + } + else { + bOk = false ; + nErr = ERR_TOOL_SEL ; + } + } + + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // assegno il prossimo utensile + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTOOL, sNextTool) ; + // assegno la prossima testa + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTHEAD, sNextHead) ; + // assegno la prossima uscita + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTEXIT, nNextExit) ; + // assegno l'eventuale prossima posizione nel TC + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTCPOS, sNextTcPos) ; + // reset errore + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_DESELECT)) + return bOk ; + // chiamo la funzione di deselezione utensile + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_DESELECT) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) +{ + // assegno identificativo e indice lavorazione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHID, nOpId) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHIND, nOpInd)) + return false ; + // assegno punti estremi dell'ingombro della lavorazione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMIN, ptMin) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMAX, ptMax)) + return false ; + // assegno punti estremi dell'ingombro degli assi della lavorazione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMIN, vAxMin) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMAX, vAxMax)) + return false ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_START)) + return true ; + // chiamo la funzione di inizio disposizione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_START) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnMachiningEnd( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_END)) + return true ; + // chiamo la funzione di fine lavorazione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_END) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, + const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) +{ + // assegno identificativo e indice percorso di lavorazione + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHID, nClPathId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHIND, nClPathInd) ; + // assegno numero di dati ausiliari iniziali + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAS) ; + // assegno punti iniziale e finale e versore estrusione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_START, ptStart) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_END, ptEnd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXTR, vtExtr) ; + // assegno punti estremi dell'ingombro del percorso di lavorazione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMIN, ptMin) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMAX, ptMax) ; + // assegno punti estremi dell'ingombro degli assi della lavorazione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMIN, vAxMin) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMAX, vAxMax) ; + // assegno la massima elevazione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ELEV, dElev) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START)) + return bOk ; + // chiamo la funzione di inizio percorso di lavorazione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnPathEnd( int nAE) +{ + // assegno numero di dati ausiliari finali + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAE) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END)) + return bOk ; + // chiamo la funzione di fine percorso di lavorazione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnPathStartAux( int nInd, const string& sAS, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START_AUX)) + return true ; + // assegno indice, valore dato ausiliario e resetto errore + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAS) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // chiamo la funzione di evento ausiliario all'inizio del percorso + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START_AUX) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnPathEndAux( int nInd, const string& sAE, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END_AUX)) + return true ; + // assegno indice, valore dato ausiliario e resetto errore + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAE) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // chiamo la funzione di evento ausiliario alla fine del percorso + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END_AUX) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // recupero e assegno i dati + // dati generali e reset errore + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEID, m_nEntId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEIND, m_nEntInd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVE, pCamData->GetMoveType()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MASK, pCamData->GetAxesMask()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG, pCamData->GetFlag()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG2, pCamData->GetFlag2()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INDEX, pCamData->GetIndex()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // valore degli assi all'inizio e alla fine del movimento + bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; + int nNumAxes = int( m_AxesName.size()) ; + const DBLVECTOR& AxesEnd = pCamData->GetAxesVal() ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) { + if ( i <= nNumAxes) { + bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot), m_AxesVal[i-1]) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot), AxesEnd[i-1]) ; + } + else { + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot)) ; + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot)) ; + } + } + // versori utensile, correzione e ausiliario alla fine del movimento + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TDIR, pCamData->GetToolDir()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_CDIR, pCamData->GetCorrDir()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ADIR, pCamData->GetBackAuxDir()) ; + // anticipazione di alcuni dati dell'eventuale movimento successivo dello stesso percorso + if ( pNextCamData != nullptr && pNextCamData->GetAxesStatus() == CamData::AS_OK) { + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVESUCC, pNextCamData->GetMoveType()) ; + const DBLVECTOR& AxesNext = pNextCamData->GetAxesVal() ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) { + if ( i <= nNumAxes) + bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot), AxesNext[i-1]) ; + else + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ; + } + } + else { + bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_MOVESUCC) ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ; + } + // reset abilitazione assi attivi + bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_ENABAXES) ; + // reset numero assi ausiliari + bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_AUXAXES) ; + + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_START)) { + ResetAuxAxes() ; + return bOk ; + } + // chiamo la funzione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_START) ; + // con errore, esco + if ( ! bOk) { + ResetAuxAxes() ; + return false ; + } + + // verifico codice di errore + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + if ( nErr != 0) + return false ; + + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + + // reset assi ausiliari + ResetAuxAxes() ; + + // recupero i dati di ritorno + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_MASK, m_nAxesMask) ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ENABAXES, m_bEnabAxes)) + m_bEnabAxes = true ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SHOWAXES, m_bShowAxes)) + m_bShowAxes = m_bEnabAxes ; + int nNumAuxAxes = 0 ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) + return true ; + m_AuxAxesName.reserve( nNumAuxAxes) ; + m_AuxAxesToken.reserve( nNumAuxAxes) ; + m_AuxAxesInvert.reserve( nNumAuxAxes) ; + m_AuxAxesOffset.reserve( nNumAuxAxes) ; + m_AuxAxesLinear.reserve( nNumAuxAxes) ; + m_AuxAxesVal.reserve( nNumAuxAxes) ; + m_AuxAxesEnd.reserve( nNumAuxAxes) ; + for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) { + string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; double dEnd ; string sLink ; + string sAuxAxVal = GLOB_VAR + GVAR_AN ; ReplaceString( sAuxAxVal, "N", ToString( i)) ; + string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ; + string sAuxAxMaster = GLOB_VAR + GVAR_ANM ; ReplaceString( sAuxAxMaster, "N", ToString( i)) ; + if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) && + m_pMachine->GetAxisToken( sName, sToken) && + m_pMachine->GetAxisInvert( sName, bInvert) && + m_pMachine->GetAxisOffset( sName, dOffset) && + m_pMachine->GetAxisType( sName, bLinear) && + m_pMachine->GetAxisPos( sName, dVal)) { + // se assi principali abilitati e da agganciare ad asse principale + if ( m_bEnabAxes && m_pMachine->LuaGetGlobVar( sAuxAxMaster, sLink)) { + bool bNeg = ( sLink.find( '-') != string::npos) ; + string sMainAxis = sLink ; ReplaceString( sMainAxis, "-", "") ; + int nInd = 0 ; + for ( int i = 0 ; nInd == 0 && i < int( m_AxesName.size()) ; ++ i) { + if ( m_AxesName[i] == sMainAxis) + nInd = i + 1 ; + } + // se trovato asse principale di riferimento + if ( nInd > 0) { + m_AuxAxesName.emplace_back( sName) ; + m_AuxAxesToken.emplace_back( sToken) ; + m_AuxAxesInvert.push_back( bInvert) ; + m_AuxAxesOffset.push_back( dOffset) ; + m_AuxAxesLinear.push_back( bLinear) ; + m_AuxAxesVal.emplace_back( 0) ; + m_AuxAxesEnd.emplace_back( 0) ; + m_AuxAxesLink.emplace_back( ( bNeg ? -nInd : nInd)) ; + } + } + // se altrimenti specificato valore finale del movimento + else if ( m_pMachine->LuaGetGlobVar( sAuxAxVal, dEnd)) { + // se assi principali disabilitati o non è tra questi, lo aggiungo + if ( ! m_bEnabAxes || find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) { + m_AuxAxesName.emplace_back( sName) ; + m_AuxAxesToken.emplace_back( sToken) ; + m_AuxAxesInvert.push_back( bInvert) ; + m_AuxAxesOffset.push_back( dOffset) ; + m_AuxAxesLinear.push_back( bLinear) ; + m_AuxAxesVal.emplace_back( dVal) ; + m_AuxAxesEnd.emplace_back( dEnd) ; + m_AuxAxesLink.emplace_back( 0) ; + if ( ! m_pMachine->VerifyOutstroke( sName, dEnd)) { + nErr = 1 ; + bOk = false ; + } + } + } + // altrimenti errore + else + bOk = false ; + } + else + bOk = false ; + } + + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnMoveEnd( int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_END)) + return true ; + // reset errore + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) + return false ; + // chiamo la funzione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_END) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnCollision( int nCdInd, int nObjInd, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_COLLISION)) + return true ; + // reset stato di errore + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) + return false ; + // assegno identificativi grezzo e oggetto in collisione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMVMID, m_CdId[nCdInd])) + return false ; + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMCOBIND, m_CollObj[nObjInd].nInd)) + return false ; + // chiamo la funzione + if ( ! m_pMachine->LuaCallFunction( ON_SIMUL_COLLISION)) + return false ; + // verifico codice di errore + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // l'errore standard di collisione è stato portato da 1 a 11 per non collidere con altri tipi di errori + if ( nErr == 1) { + nErr = ERR_COLLISION ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + } + // evidenzio le geometrie in collisione + if ( nErr == ERR_COLLISION) { + SetCollisionMark( nCdInd, nObjInd) ; + ExeDraw() ; + } + + return ( nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::OnResetMachine( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_RESET_MACHINE)) + return true ; + // eseguo reset macchina + return m_pMachine->LuaCallFunction( ON_RESET_MACHINE) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) +{ + // verifiche sui parametri + if ( nInd <= 0 || nFrameId <= GDB_ID_NULL) + return false ; + switch ( nType) { + case MCH_SIM_COB_BOX : + if ( abs( dPar1) < EPS_SMALL || abs( dPar2) < EPS_SMALL || abs( dPar3) < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_CYL : + if ( dPar1 < EPS_SMALL || abs( dPar2) < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_SPHE : + if ( dPar1 < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_CONE : + if ( ( dPar1 < EPS_SMALL && dPar2 < EPS_SMALL) || dPar3 < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_POLY : + if ( ! ExeSurfIsClosed( nFrameId)) + return false ; + break ; + default : + return false ; + } + // aggiungo al vettore + m_CollObj.emplace_back( nInd, bToolOn, nFrameId, nType, vtMove, dPar1, dPar2, dPar3) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::SetToolForVmill( const string& sTool, const string& sHead, int nExit, int nFlag, double dPar1, double dPar2, + const INTVECTOR& vVmill, bool bFirst) +{ + // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) + CmdLogOff cmdLogOff ; + // se vVmill vuoto, esco + if ( vVmill.empty()) + return true ; + // se utensile, testa o uscita non definiti, reset ed esco + if ( IsEmptyOrSpaces( sTool) || IsEmptyOrSpaces( sHead) || nExit < 1) { + ExeVolZmapResetTools( vVmill) ; + if ( bFirst) + m_bEnableVm = false ; + return false ; + } + // imposto utensile come corrente + string sOldTool ; m_pMchMgr->TdbGetCurrToolParam( TPA_NAME, sOldTool) ; + if ( sTool != sOldTool && ! m_pMchMgr->TdbSetCurrTool( sTool)) { + ExeVolZmapResetTools( vVmill) ; + if ( bFirst) + m_bEnableVm = false ; + return false ; + } + // recupero dati utensile + int nInd = 1 ; + int nType ; m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nType) ; + double dLen ; m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, dLen) ; + double dDiam ; m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, dDiam) ; + double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; + double dCornR ; m_pMchMgr->TdbGetCurrToolParam( TPA_CORNRAD, dCornR) ; + double dSideAng ; m_pMchMgr->TdbGetCurrToolParam( TPA_SIDEANG, dSideAng) ; + double dMaxMat ; m_pMchMgr->TdbGetCurrToolParam( TPA_MAXMAT, dMaxMat) ; + string sNotes ; m_pMchMgr->TdbGetCurrToolParam( TPA_USERNOTES, sNotes) ; + bool bAdditive = ( nFlag == 1) ; + // ricerca dell'outline e del diametro gambo + int nExitId = m_pMachine->GetExitId( sHead, nExit) ; + int nToolId = m_pGeomDB->GetFirstNameInGroup( nExitId, sTool) ; + int nOutlineId = m_pGeomDB->GetFirstNameInGroup( nToolId, "Outline") ; + double dMaxStemDiam = dDiam ; m_pGeomDB->GetInfo( nToolId, "D_STEM", dMaxStemDiam) ; + // imposto profilo utensile per Vmill + if ( bAdditive) + ExeVolZmapSetAdditiveTool( vVmill, sTool, dPar1, dPar2, 0, nInd, bFirst) ; + else if ( nOutlineId != GDB_ID_NULL) + ExeVolZmapSetGenTool( vVmill, sTool, nOutlineId, nInd, bFirst) ; + else if ( nType == TT_MORTISE_STD) + ExeVolZmapSetMortiserTool( vVmill, sTool, dLen, dDiam, dThick, dCornR, nInd, bFirst) ; + else if ( nType == TT_CHISEL_STD) + ExeVolZmapSetChiselTool( vVmill, sTool, dLen, dDiam, dDiam, nInd, bFirst) ; + else if ( nType == TT_SAW_STD || nType == TT_SAW_FLAT) + ExeVolZmapSetSawTool( vVmill, sTool, dLen, dDiam, dThick, 0, dCornR, nInd, bFirst) ; + else if ( nType == TT_WATERJET) + ExeVolZmapSetStdTool( vVmill, sTool, dLen + 50, dDiam, dCornR, dMaxMat, nInd, bFirst) ; + else if ( abs( dSideAng) < EPS_ANG_SMALL || abs( dThick) < EPS_SMALL) { + ExeVolZmapSetStdTool( vVmill, sTool, dLen, dDiam, dCornR, dMaxMat, nInd, bFirst) ; + } + else { + bool bExtra = ( dThick > 0) ; + double dTipLen = abs( dThick) ; + double dTotLen = ( bExtra ? dLen + dTipLen : dLen) ; + double dDelta ; + if ( dSideAng > 0) { + if ( dCornR < EPS_SMALL) + dDelta = 2 * dTipLen * tan( dSideAng * DEGTORAD) ; + else + dDelta = 2 * ( dCornR * cos( dSideAng * DEGTORAD) + ( dTipLen - dCornR + dCornR * sin( dSideAng * DEGTORAD)) * tan( dSideAng * DEGTORAD)) ; + } + else + dDelta = 2 * tan( dSideAng * DEGTORAD) * dTipLen ; + double dStemDiam = ( bExtra ? dDiam : dDiam + dDelta) ; + double dTipDiam = ( bExtra ? dDiam - dDelta : dDiam) ; + ExeVolZmapSetAdvTool( vVmill, sTool, dTotLen, dStemDiam, dTipLen, dTipDiam, dCornR, dMaxMat, nInd, bFirst) ; + } + // eventuali offset per Vmill (per adattare lo ZeroT macchina con quello di Zmap) + double dVmTdOffs = 0 ; + double dVmAdOffs = 0 ; + if ( nType == TT_MORTISE_STD) { + dVmTdOffs = 0 ; + dVmAdOffs = 0.5 * dThick ; + } + else if ( nType == TT_SAW_STD || nType == TT_SAW_FLAT) { + dVmTdOffs = ( ( dLen <= dThick) ? -dLen + dThick : 0) ; + dVmAdOffs = 0 ; + } + // inserisco in lista utensili per virtual milling + if ( bFirst) { + m_VmTool.resize( 1) ; + m_VmTool[0] = VmTool( sTool, sHead, nExit, dVmTdOffs, dVmAdOffs) ; + } + else + m_VmTool.emplace_back( sTool, sHead, nExit, dVmTdOffs, dVmAdOffs) ; + // ripristino eventuale diverso utensile corrente + if ( sTool != sOldTool) + m_pMchMgr->TdbSetCurrTool( sOldTool) ; + + if ( bFirst) + m_bEnableVm = true ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::EnableToolsForVmill( bool bEnable) +{ + m_bEnableVm = bEnable ; + return true ; +} + +//---------------------------------------------------------------------------- +int +SimulatorMP::MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) +{ + // Verifico ci siano assi da muovere + if ( vAxNaEpSt.empty()) + return SIM_AXMV_RES_ERR ; + // Salvo i dati di movimento + m_CmdData.emplace_back( 1, nMoveType, vAxNaEpSt) ; + // Log dati + if ( ExeGetDebugLevel() >= 5) { + string sOut = "Save=SimulMoveAxes," + ToString( nMoveType) ; + for ( int i = 0 ; i < int( vAxNaEpSt.size()) ; ++ i) + sOut += "," + vAxNaEpSt[i].sName + + "," + ToString( vAxNaEpSt[i].dEndPos, 3) + + "," + ToString( vAxNaEpSt[i].dStep, 3) ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) + } + + return SIM_AXMV_RES_OK ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ExecCmdData( int& nStatus) +{ + // Comando corrente + auto& CmdCurr = m_CmdData[m_nCmdInd] ; + + // Stampe di debug + if ( ExeGetDebugLevel() >= 5) { + if ( CmdCurr.nType == 1) { + string sOut = "Cmd=SimulMoveAxes," + ToString( CmdCurr.nMoveType) ; + for ( int i = 0 ; i < int( CmdCurr.vAxNaEpSt.size()) ; ++ i) + sOut += "," + CmdCurr.vAxNaEpSt[i].sName + + "," + ToString( CmdCurr.vAxNaEpSt[i].dEndPos, 3) + + "," + ToString( CmdCurr.vAxNaEpSt[i].dStep, 3) ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) + } + } + + // Eseguo + if ( CmdCurr.nType == 1) { + // Numero assi da muovere + int nAxCount = int( CmdCurr.vAxNaEpSt.size()) ; + // Posizioni iniziali + DBLVECTOR vPrev( nAxCount) ; + for ( int i = 0 ; i < nAxCount ; ++ i) { + if ( ! m_pMchMgr->GetAxisPos( CmdCurr.vAxNaEpSt[i].sName, vPrev[i])) + return SIM_AXMV_RES_ERR ; + } + // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) + bool bExecVmill = (( CmdCurr.nMoveType != 0 || ! NeedCollisionCheck()) && ! m_VmTool.empty() && ! m_VmId.empty()) ; + PNTVECTOR vPtNoseI ; + VCT3DVECTOR vVtDirI ; + VCT3DVECTOR vVtAuxI ; + vector vFrVzmI ; + if ( bExecVmill) { + vPtNoseI.resize( m_VmTool.size()) ; + vVtDirI.resize( m_VmTool.size()) ; + vVtAuxI.resize( m_VmTool.size()) ; + vFrVzmI.resize( m_VmId.size()) ; + bool bOkI = true ; + for ( int i = 0 ; i < int( m_VmTool.size()) ; ++ i) + bOkI = GetHeadCurrPosDirAux( m_VmTool[i].sHead, m_VmTool[i].nExit, vPtNoseI[i], vVtDirI[i], vVtAuxI[i]) && bOkI ; + for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i) + bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ; + } + // Determino gli step di movimento + static const int STEP_FEED = -1 ; + static const int STEP_RAPID = -2 ; + static const int STEP_RAPROT = -3 ; + static const int STEP_COLLROT = -4 ; + int nStep = 1 ; + for ( int i = 0 ; i < nAxCount ; ++ i) { + double dMove = abs( CmdCurr.vAxNaEpSt[i].dEndPos - vPrev[i]) ; + double dStep = CmdCurr.vAxNaEpSt[i].dStep ; + if ( dStep < 0) { + if ( abs( dStep - STEP_FEED) < EPS_SMALL) + dStep = m_dStep ; + else if ( abs( dStep - STEP_RAPID) < EPS_SMALL) + dStep = 4 * m_dStep ; + else if ( abs( dStep - STEP_RAPROT) < EPS_SMALL) + dStep = 0.4 * m_dStep ; + else // STEP_COLLROT + dStep = min( 0.4 * m_dStep, 10.) ; + } + dStep = max( dStep, 1.) ; + int nAxStep = int( dMove / dStep) + 1 ; + nStep = max( nStep, nAxStep) ; + } + double dCoeff = 1. / nStep ; + m_dCmdCoeff += dCoeff * ( 1. - m_dCmdCoeff) ; + + // Eseguo il movimento + bool bMoveOk = true ; + for ( int j = 0 ; j < nAxCount ; ++ j) { + bMoveOk = m_pMchMgr->SetAxisPos( CmdCurr.vAxNaEpSt[j].sName, ( 1 - dCoeff) * vPrev[j] + dCoeff * CmdCurr.vAxNaEpSt[j].dEndPos) && bMoveOk ; + } + // Se abilitato e richiesto, eseguo eventuale Vmill + if ( m_bEnableVm && bExecVmill) { + for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + } + // Verifico collisioni + int nCdInd, nObjInd ; + bool bCollCheck = ExecCollisionCheck( nCdInd, nObjInd, CmdCurr.nMoveType) ; + if ( ! bCollCheck) { + // Richiamo funzione di convalida collisione + int nErr ; + if ( ! OnCollision( nCdInd, nObjInd, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + UpdateAxesPos() ; + return false ; + } + } + // In caso di errore esco + if ( ! bMoveOk) { + nStatus = MCH_SIM_OUTSTROKE ; + UpdateAxesPos() ; + return false ; + } + } + UpdateAxesPos() ; + + // Aggiorno dati interpolazione + if ( m_dCmdCoeff > COEFF_LIM) { + m_nCmdInd += 1 ; + m_dCmdCoeff = 0 ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::ExecAllCmdData( int& nStatus) +{ + // Eseguo tutti i comandi pendenti + while ( m_nCmdInd < int( m_CmdData.size())) { + if ( ! ExecCmdData( nStatus)) + return false ; + ExeDraw() ; + } + m_CmdData.clear() ; + m_nCmdInd = 0 ; + m_dCmdCoeff = 0 ; + + return true ; +} diff --git a/SimulatorMP.h b/SimulatorMP.h new file mode 100644 index 0000000..6ea5048 --- /dev/null +++ b/SimulatorMP.h @@ -0,0 +1,202 @@ +//---------------------------------------------------------------------------- +// EgalTech 2024-2024 +//---------------------------------------------------------------------------- +// File : SimulatorMP.h Data : 01.09.24 Versione : 2.6i1 +// Contenuto : Dichiarazione della classe SimulatorMP. +// Simulatore multi-processo. +// +// +// Modifiche : 01.09.24 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "Simulator.h" +#include "CamData.h" + +class IGeomDB ; +class Machine ; +class PerformanceCounter ; + +//---------------------------------------------------------------------------- +ISimulator* CreateSimulatorMP( void) ; + +//---------------------------------------------------------------------------- +class SimulatorMP : public ISimulator +{ + public : // ISimulator + ~SimulatorMP( void) override ; + bool Init( MachMgr* pMchMgr) override ; + bool Start( bool bFirst) override ; + bool Move( int& nStatus) override ; + bool GoHome( void) override ; + bool SetStep( double dStep) override ; + bool SetUiStatus( int nUiStatus) override ; + bool GetAxisInfoPos( int nI, std::string& sName, std::string& sToken, bool& bLinear, double& dVal) const override ; + bool GetToolInfo( std::string& sName, double& dSpeed) const override ; + bool GetOperationInfo( std::string& sName, int& nType) const override ; + bool GetMoveInfo( int& nGmove, double& dFeed) const override ; + bool AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, + const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) override ; + bool ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) override ; + bool OnCollision( int nCdInd, int nObjInd, int& nErr) override ; + bool SetToolForVmill( const std::string& sTool, const std::string& sHead, int nExit, int nFlag, + double dPar1, double dPar2, const INTVECTOR& vVmill, bool bFirst) override ; + bool EnableToolsForVmill( bool bEnable) override ; + int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) override ; + + public : + SimulatorMP( void) ; + + private : + bool UpdateTool( bool bFirst, int& nErr) ; + bool UpdateAxes( void) ; + bool UpdateAxesPos( void) ; + bool ResetInterpolation( void) ; + bool ResetAxes( void) ; + bool ResetAuxAxes( void) ; + + private : + bool VerifySetup( void) ; + bool FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) ; + bool ManageOperationEnd( int& nStatus) ; + bool FindAndManagePathStart( int& nStatus) ; + bool ManagePathEnd( int& nStatus) ; + bool ManagePathStartAux( int& nStatus) ; + bool ManagePathEndAux( int& nStatus) ; + bool ManageMove( int& nStatus) ; + bool ManageSingleMove( int& nStatus, double& dMove) ; + int CalcStatusOnError( int nErr) ; + bool GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA) ; + bool ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, + const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) ; + bool NeedCollisionCheck( void) const + { return ( ! m_CollObj.empty() && ! m_CdId.empty()) ; } + bool Stopped( void) + { return ( m_nUiStatus == MCH_UISIM_STOP) ; } + bool SetCollisionMark( int nCdInd, int nObjInd) ; + bool ResetCollisionMark( void) ; + bool OnInit( void) ; + bool OnExit( void) ; + bool OnProgramStart( bool bFirst) ; + bool OnProgramEnd( void) ; + bool OnDispositionStarting( int nOpId, int nOpInd, int nPhase, + const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; + bool OnDispositionStart( int nOpId, int nOpInd, int nPhase, + const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; + bool OnDispositionEnd( void) ; + bool OnToolSelect( const std::string& sTool, const std::string& sHead, int nExit, const std::string& sTcPos, bool bFirst, int& nErr) ; + bool OnToolDeselect( const std::string& sNextTool, const std::string& sNextHead, int nNextExit, const std::string& sNextTcPos, int& nErr) ; + bool OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) ; + bool OnMachiningEnd( void) ; + bool OnPathStartAux( int nInd, const std::string& sAS, int& nErr) ; + bool OnPathEndAux( int nInd, const std::string& sAE, int& nErr) ; + bool OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, + const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) ; + bool OnPathEnd( int nAE) ; + bool OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) ; + bool OnMoveEnd( int& nErr) ; + bool OnResetMachine( void) ; + bool ExecCmdData( int& nStatus) ; + bool ExecAllCmdData( int& nStatus) ; + + private : + struct CollObj { + int nInd ; + bool bToolOn ; + int nFrameId ; + int nType ; + Vector3d vtMove ; + double dPar1 ; + double dPar2 ; + double dPar3 ; + CollObj( void) : nInd( 0), bToolOn( false), nFrameId( -1), nType( 0), vtMove(), dPar1( 0), dPar2( 0), dPar3( 0) {} + CollObj( int nI, bool bTOn, int nF, int nT, const Vector3d& vtM, double dP1, double dP2, double dP3) + : nInd( nI), bToolOn( bTOn), nFrameId( nF), nType( nT), vtMove( vtM), dPar1( dP1), dPar2( dP2), dPar3( dP3) {} + } ; + typedef std::vector COBVECTOR ; + struct VmTool + { + std::string sName ; + std::string sHead ; + int nExit ; + double dTdOffs ; + double dAdOffs ; + VmTool( void) : nExit( 0), dTdOffs( 0), dAdOffs( 0) {} + VmTool( std::string sN, std::string sH, int nE, double dT, double dA) + : sName( sN), sHead( sH), nExit( nE), dTdOffs( dT), dAdOffs( dA) {} + } ; + typedef std::vector VMTVECTOR ; + enum { SIS_CREATED = 0, + SIS_INITIALIZED = 1, + SIS_READYTOSTART = 2, + SIS_READYTORUN = 3} ; + + private : + struct CmdData { + int nType ; + int nMoveType ; + SAMVECTOR vAxNaEpSt ; + CmdData( void) : nType(0) {} + CmdData( int nT, int nM, const SAMVECTOR& vAx) + : nType( nT), nMoveType( nM), vAxNaEpSt( vAx) {} + } ; + typedef std::vector CMDVECTOR ; + + private : + MachMgr* m_pMchMgr ; // puntatore al gestore di tutte le lavorazioni + IGeomDB* m_pGeomDB ; // puntatore al DB geometrico + Machine* m_pMachine ; // puntatore alla macchina + PerformanceCounter* m_pPerfCnt ; // timer per calcolo FPS + int m_nStatus ; // stato interno del simulatore (creato, inizializzato, pronto al movimento) + double m_dStep ; // lunghezza di riferimento per la velocità di simulazione + int m_nUiStatus ; // stato simulazione a livello utente + int m_nOpId ; // identificativo della operazione (lavoraz.) corrente + int m_nOpInd ; // contatore della operazione (lavoraz.) corrente + int m_nCLPathId ; // identificativo del percorso di lavoro corrente + int m_nCLPathInd ; // contatore del percorso di lavoro corrente nell'operazione + int m_nEntId ; // identificativo dell'entità corrente + int m_nEntInd ; // contatore dell'entità corrente nel percorso di lavoro + double m_dCoeff ; // coefficiente di esecuzione del movimento corrente (0...1) + int m_nAuxSTot ; // numero totale movimenti ausiliari di inizio percorso + int m_nAuxSInd ; // indice del movimento ausiliario di inizio percorso corrente + int m_nAuxETot ; // numero totale movimenti ausiliari di fine percorso + int m_nAuxEInd ; // indice del movimento ausiliario di fine percorso corrente + std::string m_sTool ; // nome dell'utensile corrente + std::string m_sHead ; // nome della testa corrente + int m_nExit ; // indice dell'uscita corrente + double m_dTDiam ; // diametro dell'utensile corrente + bool m_bCutOnTip ; // flag capacità di lavorare di testa dell'utensile corrente + bool m_bEnableVm ; // flag abilitazione Virtual Milling + INTVECTOR m_VmId ; // vettore identificativi Zmap per Virtual Milling + INTVECTOR m_CdId ; // vettore identificativi Zmap per Collision Detection + VMTVECTOR m_VmTool ; // vettore utensili attivi per virtual milling + COBVECTOR m_CollObj ; // vettore oggetti da testare per collisione con grezzo + double m_dSafeDist ; // distanza di sicurezza per verifica collisioni + INTVECTOR m_nCollMarkId ; // elenco oggetti marcati per visualizzare meglio la collisione rilevata + int m_nAxesMask ; // maschera a bit di abilitazione movimento assi (solo se rapido) + bool m_bEnabAxes ; // flag abilitazione movimento assi attivi + bool m_bShowAxes ; // flag visualizzazione assi attivi + STRVECTOR m_AxesName ; // nomi degli assi macchina attivi + STRVECTOR m_AxesToken ; // token degli assi macchina attivi + BOOLVECTOR m_AxesInvert ; // flag di asse con verso invertito degli assi macchina attivi + DBLVECTOR m_AxesOffset ; // valore di offset delgli assi macchina ttivi + BOOLVECTOR m_AxesLinear ; // flag di lineare degli assi macchina attivi + DBLVECTOR m_AxesVal ; // valori degli assi macchina all'inizio del movimento corrente + STRVECTOR m_AuxAxesName ; // nomi degli assi macchina ausiliari abilitati + STRVECTOR m_AuxAxesToken ; // token degli assi macchina ausiliari abilitati + BOOLVECTOR m_AuxAxesInvert ; // flag di asse con verso invertito degli assi macchina ausiliari abilitati + DBLVECTOR m_AuxAxesOffset ; // valore di offset degli assi macchina ausiliari abilitati + BOOLVECTOR m_AuxAxesLinear ; // flag di lineare degli assi macchina ausiliari abilitati + DBLVECTOR m_AuxAxesVal ; // valori degli assi macchina ausiliari all'inizio del movimento corrente + DBLVECTOR m_AuxAxesEnd ; // valori degli assi macchina ausiliari alla fine del movimento corrente + INTVECTOR m_AuxAxesLink ; // indice + 1 asse principale di aggancio (negativo valore opposto, 0 nessuno) + CMDVECTOR m_CmdData ; // vettore comandi in attesa di esecuzione + int m_nCmdInd ; // indice prossimo comando da eseguire + double m_dCmdCoeff ; // coefficiente di movimento nel comando +} ; diff --git a/Simulator.cpp b/SimulatorSP.cpp similarity index 94% rename from Simulator.cpp rename to SimulatorSP.cpp index 1fca5c7..39c7ea3 100644 --- a/Simulator.cpp +++ b/SimulatorSP.cpp @@ -1,2452 +1,2460 @@ -//---------------------------------------------------------------------------- -// EgalTech 2015-2016 -//---------------------------------------------------------------------------- -// File : Simulator.cpp Data : 04.01.17 Versione : 1.6x5 -// Contenuto : Implementazione della classe Simulator. -// -// -// -// Modifiche : 19.10.15 DS Creazione modulo. -// 26.02.16 DS Aggiunta gestione archi. -// 04.01.17 DS Riorganizzazione codice. -// -//---------------------------------------------------------------------------- - -//--------------------------- Include ---------------------------------------- -#include "stdafx.h" -#include "Simulator.h" -#include "MachMgr.h" -#include "Disposition.h" -#include "Machining.h" -#include "MachiningConst.h" -#include "OutputConst.h" -#include "DllMain.h" -#include "/EgtDev/Include/EGkCDeBoxClosedSurfTm.h" -#include "/EgtDev/Include/EGkCDeCylClosedSurfTm.h" -#include "/EgtDev/Include/EGkCDeSpheClosedSurfTm.h" -#include "/EgtDev/Include/EGkCDeConeFrustumClosedSurfTm.h" -#include "/EgtDev/Include/EGkCDeClosedSurfTmClosedSurfTm.h" -#include "/EgtDev/Include/EGkVolZmap.h" -#include "/EgtDev/Include/EGkGeoVector3d.h" -#include "/EgtDev/Include/EGkStringUtils3d.h" -#include "/EgtDev/Include/EGkSurfLocal.h" -#include "/EgtDev/Include/EXeCmdLogOff.h" -#include "/EgtDev/Include/EXeConst.h" -#include "/EgtDev/Include/EMkToolConst.h" -#include "/EgtDev/Include/EMkOperationConst.h" -#include "/EgtDev/Include/EgtPerfCounter.h" -#include "/EgtDev/Include/EgtNumUtils.h" - -using namespace std ; - -//------------------------------ Errors -------------------------------------- -// 1001 = "Error with setup : xxx" - -//---------------------------------------------------------------------------- -static const double MIN_STEP = 1.0 ; -static const double MAX_STEP = 500.0 ; -static const double MID_STEP = 50.0 ; -static const double COLL_STEP = 10. ; -static const double SQ_COEFF_ROT_MOVE = 100. ; -static const double COEFF_LIM = 0.999 ; -static const double SAFEDIST_STD = 5.0 ; -static const int ERR_OUTSTROKE = 1 ; -static const int ERR_COLLISION = 11 ; -static const int ERR_TOOL_SEL = 21 ; - -//---------------------------------------------------------------------------- -Simulator::Simulator( void) -{ - m_pMchMgr = nullptr ; - m_pGeomDB = nullptr ; - m_pMachine = nullptr ; - m_pPerfCnt = nullptr ; - m_nStatus = SIS_CREATED ; - m_dStep = MID_STEP ; - m_nUiStatus = MCH_UISIM_NULL ; - m_nOpId = GDB_ID_NULL ; - m_nOpInd = 0 ; - m_nCLPathId = GDB_ID_NULL ; - m_nCLPathInd = 0 ; - m_nEntId = GDB_ID_NULL ; - m_nEntInd = 0 ; - m_dCoeff = 0 ; - m_nAuxSTot = 0 ; - m_nAuxSInd = 0 ; - m_nAuxETot = 0 ; - m_nAuxEInd = 0 ; - m_nExit = 0 ; - m_dTDiam = 0 ; - m_bCutOnTip = false ; - m_bEnableVm = false ; - m_dSafeDist = SAFEDIST_STD ; - m_nAxesMask = 0 ; - m_bEnabAxes = true ; - m_bShowAxes = true ; - m_AxesName.reserve( 8) ; - m_AxesToken.reserve( 8) ; - m_AxesLinear.reserve( 8) ; - m_AxesVal.reserve( 8) ; -} - -//---------------------------------------------------------------------------- -Simulator::~Simulator( void) -{ - // porto la macchina in posizione home - GoHome() ; - // gestione evento uscita dal simulatore - OnExit() ; - // rimuovo tavola variabili globali - m_pMachine->LuaResetGlobVar( GLOB_VAR) ; - // rimuovo performance counter - if ( m_pPerfCnt != nullptr) { - delete m_pPerfCnt ; - m_pPerfCnt = nullptr ; - } -} - -//---------------------------------------------------------------------------- -bool -Simulator::Init( MachMgr* pMchMgr) -{ - // verifico ambiente - if ( pMchMgr == nullptr || pMchMgr->GetContextId() == 0 || - pMchMgr->GetGeomDB() == nullptr || pMchMgr->GetCurrMachine() == nullptr) - return false ; - m_pMchMgr = pMchMgr ; - m_pGeomDB = m_pMchMgr->GetGeomDB() ; - m_pMachine = m_pMchMgr->GetCurrMachine() ; - m_pPerfCnt = new PerformanceCounter ; - m_nStatus = SIS_INITIALIZED ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::Start( bool bFirst) -{ - // Verifico ci sia una macchinata corrente - if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr || m_pMachine == nullptr || - m_pMchMgr->GetCurrMachGroup() == GDB_ID_NULL) - return false ; - m_pMchMgr->ResetLastError() ; - m_pMchMgr->ResetWarnings() ; - - bool bOk = true ; - - // Se appena entrati in simulazione - if ( m_nStatus == SIS_INITIALIZED) { - // Forzo aggiornamento attrezzaggio della macchinata - if ( ! m_pMchMgr->UpdateCurrSetup()) - bOk = false ; - // Verifico attrezzaggio - if ( ! VerifySetup()) - bOk = false ; - } - - // Reset utensile, interpolazione e assi correnti - m_sTool.clear() ; - m_sHead.clear() ; - m_nExit = 0 ; - m_dTDiam = 0 ; - m_bCutOnTip = false ; - ResetInterpolation() ; - ResetAxes() ; - ResetAuxAxes() ; - - // porto la macchina in home - if ( ! GoHome()) - bOk = false ; - - // Verifico la disposizione iniziale della macchinata - m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; - m_nOpInd = 1 ; - if ( m_pMchMgr->GetOperationType( m_nOpId) != OPER_DISP) - bOk = false ; - - // Definisco tabella variabili globali - if ( ! m_pMachine->LuaCreateGlobTable( GLOB_VAR)) - bOk = false ; - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INCHES, ! ExeUiUnitsAreMM()) ; - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_VER, GetEMkVer()) ; - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MACHNAME, m_pMachine->GetMachineName()) ; - - // Se appena entrati in simulazione - if ( m_nStatus == SIS_INITIALIZED) { - if ( ! OnInit()) - bOk = false ; - m_nStatus = SIS_READYTOSTART ; - } - - // Richiamo funzione per evento avvio simulazione - if ( ! OnProgramStart( bFirst)) - bOk = false ; - - // Arrivo alla preparazione per la prima lavorazione - int nStatus ; - if ( ! FindAndManageOperationStart( true, bFirst, nStatus) && nStatus != MCH_SIM_STOP) - bOk = false ; - // se sono ancora su disposizione - if ( m_pMchMgr->GetOperationType( m_nOpId) == OPER_DISP) { - // ricerca e gestione inizio percorso di lavoro - if ( ! FindAndManagePathStart( nStatus)) - return false ; - // eventuali comandi ausiliari di inizio percorso - while ( m_nAuxSInd < m_nAuxSTot) { - if ( ! ManagePathStartAux( nStatus)) - return false ; - } - // aggiornamento assi per eventuali teste caricate - UpdateAxes() ; - } - - // Reset timer - if ( m_pPerfCnt != nullptr) - m_pPerfCnt->Start() ; - - // Imposto lo stato interno - m_nStatus = ( bOk ? SIS_READYTORUN : SIS_READYTOSTART) ; - - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::VerifySetup( void) -{ - // se attrezzaggio non definito, nulla da verificare - if ( ! m_pMchMgr->GetCurrSetupMgr().Exists()) - return true ; - - // lancio la verifica - STRVECTOR vsErr ; - if ( m_pMchMgr->VerifyCurrSetup( vsErr)) - return true ; - - // gestisco errore - string sErr = "Error with setup :" ; - for ( const auto& sTmp : vsErr) - sErr += " " + sTmp ; - m_pMchMgr->SetLastError( 1001, sErr) ; - return false ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ResetInterpolation( void) -{ - m_nOpId = GDB_ID_NULL ; - m_nOpInd = 0 ; - m_nCLPathId = GDB_ID_NULL ; - m_nCLPathInd = 0 ; - m_nEntId = GDB_ID_NULL ; - m_nEntInd = 0 ; - m_dCoeff = 0 ; - m_nAuxSTot = 0 ; - m_nAuxSInd = 0 ; - m_nAuxETot = 0 ; - m_nAuxEInd = 0 ; - m_VmId.clear() ; - m_CdId.clear() ; - m_VmTool.clear() ; - m_CollObj.clear() ; - m_dSafeDist = SAFEDIST_STD ; - m_nAxesMask = 0 ; - m_bEnabAxes = true ; - m_bShowAxes = true ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::Move( int& nStatus) -{ - // Verifiche - if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr || m_nStatus != SIS_READYTORUN) { - nStatus = MCH_SIM_ERR ; - return false ; - } - - // Recupero tempo impiegato (calcolo + visualizzazione precedenti) - if ( m_pPerfCnt != nullptr && ExeGetDebugLevel() >= 5) { - double dElapsed = m_pPerfCnt->Stop() ; - string sOut = "Elapsed=" + ToString( dElapsed, 1) ; - LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) - m_pPerfCnt->Start() ; - } - - // reset visualizzazione collisioni - ResetCollisionMark() ; - - // Se arrivato alla fine dell'interpolazione - if ( m_dCoeff > COEFF_LIM) { - // recupero una nuova entità - m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; - m_dCoeff = 0 ; - } - - // Se appena arrivato alla fine di un percorso di lavoro (verifico anche completamento dei comandi aux di start per path vuote) - if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd == 0 && m_nCLPathInd > 0 && m_nAuxSInd >= m_nAuxSTot) { - // gestione fine percorso di lavoro - if ( ! ManagePathEnd( nStatus)) - return false ; - } - - // Se alla fine del percorso dopo esecuzione azioni ausiliarie (verifico anche completamento dei comandi aux di start per path vuote) - if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd >= m_nAuxETot && m_nAuxSInd >= m_nAuxSTot) { - // ricerca e gestione inizio percorso di lavoro - if ( ! FindAndManagePathStart( nStatus)) - return false ; - } - - // Se arrivato alla fine di una operazione - if ( m_nCLPathId == GDB_ID_NULL) { - // gestione fine operazione - if ( ! ManageOperationEnd( nStatus)) - return false ; - // ricerca e gestione nuova operazione - if ( ! FindAndManageOperationStart( false, false, nStatus)) - return false ; - // se non ce ne sono altre, sono alla fine - if ( m_nOpId == GDB_ID_NULL) { - OnProgramEnd() ; - nStatus = MCH_SIM_END ; - return false ; - } - // ricerca e gestione inizio percorso di lavoro - if ( ! FindAndManagePathStart( nStatus)) - return false ; - } - - // Se sto eseguendo i movimenti ausiliari di inizio percorso - if ( m_nAuxSInd < m_nAuxSTot) - return ManagePathStartAux( nStatus) ; - - // Se sto eseguendo i movimenti ausiliari di fine percorso - if ( m_nAuxEInd < m_nAuxETot) - return ManagePathEndAux( nStatus) ; - - // Gestione movimento assi - return ManageMove( nStatus) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::GetAxisInfoPos( int nI, string& sName, string& sToken, bool& bLinear, double& dVal) const -{ - // Verifiche - if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) - return false ; - // numero assi di calcolo e ausiliari - int nAxisCount = ( m_bShowAxes ? int( m_AxesName.size()) : 0) ; - int nAuxAxisCount = int( m_AuxAxesName.size()) ; - // recupero i dati dell'asse - if ( nI < 0 || nI >= nAxisCount + nAuxAxisCount) - return false ; - // se asse principale - if ( nI < nAxisCount) { - sName = m_AxesName[nI] ; - sToken = m_AxesToken[nI] ; - bLinear = m_AxesLinear[nI] ; - } - // altrimenti asse ausiliario - else { - sName = m_AuxAxesName[ nI - nAxisCount] ; - sToken = m_AuxAxesToken[ nI - nAxisCount] ; - bLinear = m_AuxAxesLinear[ nI - nAxisCount] ; - } - // recupero la posizione - if ( ! m_pMchMgr->GetAxisPos( sName, dVal)) - return false ; - // verifico se da invertire o offsettare - if ( nI < nAxisCount) { - if ( m_AxesInvert[nI]) - dVal = - dVal ; - dVal += m_AxesOffset[nI] ; - } - else { - if ( m_AuxAxesInvert[nI - nAxisCount]) - dVal = - dVal ; - dVal += m_AxesOffset[nI - nAxisCount] ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::GetToolInfo( string& sName, double& dSpeed) const -{ - // Inizializzo i parametri di ritorno - sName.clear() ; - dSpeed = 0 ; - // Verifiche - if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) - return false ; - // Assegno il nome dell'utensile - sName = m_sTool ; - if ( sName.empty()) - return true ; - // Recupero speed - const Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; - return ( pMch != nullptr && pMch->GetParam( MPA_SPEED, dSpeed)) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::GetOperationInfo( string& sName, int& nType) const -{ - // Inizializzo i parametri di ritorno - sName.clear() ; - nType = OPER_NULL ; - // Verifiche - if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) - return false ; - // Recupero il tipo - Operation* pOpe = GetOperation( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pOpe == nullptr) - return false ; - nType = pOpe->GetType() ; - // Recupero il nome - return m_pGeomDB->GetName( m_nOpId, sName) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::GetMoveInfo( int& nGmove, double& dFeed) const -{ - // Verifiche - if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) - return false ; - // Recupero il movimento corrente - const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; - if ( pCamData == nullptr) - return false ; - // Assegno feed - dFeed = pCamData->GetFeed() ; - // Assegno tipo di movimento - nGmove = pCamData->GetMoveType() ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::SetStep( double dStep) -{ - m_dStep = Clamp( dStep, MIN_STEP, MAX_STEP) ; - // imposto step per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::SetUiStatus( int nUiStatus) -{ - m_nUiStatus = nUiStatus ; - // imposto stato utente del simulatore per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMUISTAT, m_nUiStatus) ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::GoHome( void) -{ - // controllo validità stato - if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr) - return false ; - // reset visualizzazione collisioni - ResetCollisionMark() ; - // reset stato macchina - OnResetMachine() ; - // porto la macchina in home - m_pMchMgr->ResetAllAxesPos() ; - // assegno valori home degli assi macchina attivi - return m_pMchMgr->GetAllCurrAxesHomePos( m_AxesVal) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::UpdateTool( bool bFirst, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // Recupero l'utensile della lavorazione corrente - Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pMch != nullptr) { - // recupero nome e dati nuovo utensile - string sTuuid, sTool ; - if ( ! pMch->GetParam( MPA_TUUID, sTuuid) || - ! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool)) - return false ; - string sTcPos ; string sHead ; int nExit ; - if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) { - if ( m_pMchMgr->TdbSetCurrTool( sTool)) { - m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ; - m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ; - m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ; - } - // ripristino l'utensile corrente - m_pMchMgr->TdbSetCurrTool( m_sTool) ; - } - // verifico se cambierà - bool bDiffTool = ( sTool != m_sTool) ; - // se cambierà ed esiste il corrente, lo scarico - if ( bDiffTool && ! m_sTool.empty()) { - // eventuale lancio script per scarico utensile - int nCurrErr ; - if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - } - // se prima volta, pulisco la testa - if ( bFirst) - m_pMchMgr->ResetHeadSet( sHead) ; - // recupero la lavorazione corrente e imposto la nuova - int nCurrMchId = m_pMchMgr->GetCurrMachining() ; - m_pMchMgr->SetCurrMachining( m_nOpId) ; - // carico l'utensile (e lo rendo corrente) - if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) - return false ; - m_sTool = sTool ; - m_sHead = sHead ; - m_nExit = nExit ; - m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; - double dTipFeed = 0 ; - m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; - m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; - // ripristino la lavorazione corrente - m_pMchMgr->SetCurrMachining( nCurrMchId) ; - // aggiorno gli assi macchina - if ( ! UpdateAxes()) - return false ; - // se cambiato oppure prima volta, lancio lo script di selezione - if ( bDiffTool || bFirst) { - int nCurrErr ; - if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - } - return ( nErr == 0) ; - } - // Provo con una disposizione - Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pDisp != nullptr) { - // recupero i dati - string sTool ; string sHead ; int nExit ; string sTcPos ; - pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ; - // se esiste utensile corrente e cambierà, lo scarico - if ( ! m_sTool.empty() && sTool != m_sTool) { - // eventuale lancio script per scarico utensile - int nCurrErr ; - if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - } - // carico l'utensile - if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) - return false ; - m_sTool = sTool ; - m_sHead = sHead ; - m_nExit = nExit ; - m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; - double dTipFeed = 0 ; - m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; - m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; - // aggiorno gli assi macchina - if ( ! UpdateAxes()) - return false ; - // eventuale lancio script - int nCurrErr ; - if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - return ( nErr == 0) ; - } - return false ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::UpdateAxes( void) -{ - ResetAxes() ; - // Macchina corrente - Machine* pMachine = m_pMchMgr->GetCurrMachine() ; - if ( pMachine == nullptr) - return false ; - // Carico i nomi e i token degli assi macchina attivi - if ( ! pMachine->GetAllCurrAxesNames( m_AxesName) || - ! pMachine->GetAllCurrAxesTokens( m_AxesToken)) - return false ; - // Aggiorno flag di invertito, offset, tipo e posizione corrente degli assi macchina attivi - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { - bool bInvert ; - m_pMachine->GetAxisInvert( m_AxesName[i], bInvert) ; - m_AxesInvert.push_back( bInvert) ; - double dOffset ; - m_pMachine->GetAxisOffset( m_AxesName[i], dOffset) ; - m_AxesOffset.push_back( dOffset) ; - bool bLinear ; - m_pMachine->GetAxisType( m_AxesName[i], bLinear) ; - m_AxesLinear.push_back( bLinear) ; - double dVal ; - m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; - m_AxesVal.emplace_back( dVal) ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::UpdateAxesPos( void) -{ - // Macchina corrente - Machine* pMachine = m_pMchMgr->GetCurrMachine() ; - if ( pMachine == nullptr) - return false ; - // Aggiorno la posizione corrente degli assi macchina attivi - m_AxesVal.clear() ; - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { - double dVal ; - m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; - m_AxesVal.emplace_back( dVal) ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ResetAxes( void) -{ - // pulisco dati assi - m_AxesName.clear() ; - m_AxesToken.clear() ; - m_AxesInvert.clear() ; - m_AxesLinear.clear() ; - m_AxesVal.clear() ; - m_nAxesMask = 0 ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ResetAuxAxes( void) -{ - // pulisco dati assi ausiliari - m_AuxAxesName.clear() ; - m_AuxAxesToken.clear() ; - m_AuxAxesInvert.clear() ; - m_AuxAxesOffset.clear() ; - m_AuxAxesLinear.clear() ; - m_AuxAxesVal.clear() ; - m_AuxAxesEnd.clear() ; - m_AuxAxesLink.clear() ; - // abilito assi principali - m_bEnabAxes = true ; - m_bShowAxes = true ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) -{ - // verifico parametri - if ( ! bStart) - bFirst = false ; - // recupero la nuova operazione - if ( bStart) { - m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; - m_nOpInd = 0 ; - } - else - m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; - // ciclo sulle successive operazioni - while ( m_nOpId != GDB_ID_NULL) { - // se lavorazione valida - Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pMch != nullptr && ! pMch->IsEmpty()) { - bool bOk = true ; - // aggiorno utensile e assi conseguenti - int nErr ; - if ( ! UpdateTool( bFirst, nErr)) { - string sOut = "Err=" + ToString( nErr) ; - LOG_INFO( GetEMkLogger(), sOut.c_str()) - nStatus = CalcStatusOnError( nErr) ; - bOk = false ; - } - ++ m_nOpInd ; - // imposto la lavorazione come corrente - m_pMchMgr->SetCurrMachining( m_nOpId) ; - // recupero punti di minimo e massimo ingombro - int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; - Point3d ptMin, ptMax ; - m_pGeomDB->GetInfo( nClId, KEY_MMIN, ptMin) ; - m_pGeomDB->GetInfo( nClId, KEY_MMAX, ptMax) ; - DBLVECTOR vAxMin, vAxMax ; - m_pGeomDB->GetInfo( nClId, KEY_MAXMIN, vAxMin) ; - m_pGeomDB->GetInfo( nClId, KEY_MAXMAX, vAxMax) ; - // richiamo gestione evento inizio lavorazione - if ( ! OnMachiningStart( m_nOpId, m_nOpInd, ptMin, ptMax, vAxMin, vAxMax)) { - nStatus = CalcStatusOnError( 0) ; - bOk = false ; - } - if ( ! bOk) - return false ; - break ; - } - // se disposizione con cambio di fase - Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pDisp != nullptr) { - // in alcuni casi la disposizione non è inizializzata - pDisp->Init( m_pMchMgr) ; - // recupero dati tavola - string sTable ; - pDisp->GetTable( sTable) ; - Point3d ptOri1 ; - pDisp->GetTableRef1( ptOri1) ; - // recupero la fase della disposizione - int nPhase = pDisp->GetPhase() ; - // recupero se con movimenti autonomi - bool bEmpty = pDisp->IsEmpty() ; - // recupero flag disposizione con movimenti manuali - bool bSomeByHand = pDisp->GetSomeByHand() ; - // se con movimenti autonomi - if ( ! bEmpty) { - // richiamo gestione evento appena prima di inizio disposizione - if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { - nStatus = CalcStatusOnError( 0) ; - return false ; - } - // cambio fase - m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; - // se previsto, aggiorno utensile e assi conseguenti - if ( pDisp->IsWithTool()) { - int nErr ; - if ( ! UpdateTool( bFirst, nErr)) { - nStatus = CalcStatusOnError( nErr) ; - return false ; - } - } - ++ m_nOpInd ; - // richiamo gestione evento inizio disposizione - if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { - nStatus = CalcStatusOnError( 0) ; - return false ; - } - // se ci sono movimenti manuali, aggiorno visualizzazione e breve pausa (200 ms) - if ( bSomeByHand) - Sleep( 200) ; - break ; - } - // altrimenti disposizione passiva - else { - // richiamo gestione evento appena prima di inizio disposizione - if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand)) { - nStatus = CalcStatusOnError( 0) ; - return false ; - } - // cambio fase - m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; - ++ m_nOpInd ; - // richiamo gestione evento inizio e fine disposizione - if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) || - ! OnDispositionEnd()) { - nStatus = CalcStatusOnError( 0) ; - return false ; - } - // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) - if ( nPhase != 1) { - ExeDraw() ; - Sleep( 200) ; - } - } - } - // passo alla operazione successiva - m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ManageOperationEnd( int& nStatus) -{ - bool bOk = false ; - // non c'è operazione in corso (solo prima disposizione senza lavorazioni) - if ( m_nOpId == GDB_ID_NULL) - bOk = true ; - // se altrimenti è una lavorazione - else if ( GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { - // richiamo gestione evento fine lavorazione - bOk = OnMachiningEnd() ; - } - // se altrimenti è una disposizione - else if ( GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { - // richiamo gestione evento fine disposizione - bOk = OnDispositionEnd() ; - } - // gestione stato - if ( ! bOk) - nStatus = CalcStatusOnError( 0) ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::FindAndManagePathStart( int& nStatus) -{ - // se devo cercare il primo nella nuova operazione - if ( m_nCLPathId == GDB_ID_NULL) { - // aggiorno gli altri dati - int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; - m_nCLPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ; - m_nCLPathInd = 0 ; - m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; - m_nEntInd = 0 ; - m_dCoeff = 0 ; - } - // altrimenti cerco il successivo nella stessa operazione - else { - // recupero un nuovo CLpath - while ( m_nEntId == GDB_ID_NULL) { - m_nCLPathId = m_pGeomDB->GetNextGroup( m_nCLPathId) ; - // se non ce ne sono altri, devo passare a una nuova lavorazione - if ( m_nCLPathId == GDB_ID_NULL) - break ; - m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; - m_nEntInd = 0 ; - m_dCoeff = 0 ; - } - } - // se trovato nuovo CLpath con entità, gestisco inizio percorso di lavoro - if ( m_nEntId != GDB_ID_NULL) { - ++ m_nCLPathInd ; - // recupero punti di inizio e fine percorso - Point3d ptStart ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_START, ptStart) ; - Point3d ptEnd ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_END, ptEnd) ; - // recupero versore estrusione associato al percorso (normale al piano di interpolazione) - Vector3d vtExtr ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_EXTR, vtExtr) ; - // recupero punti di minimo e massimo ingombro - Point3d ptMin, ptMax ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMIN, ptMin) ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMAX, ptMax) ; - // Recupero valori degli assi di minimo e massimo ingombro - DBLVECTOR vAxMin, vAxMax ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMIN, vAxMin) ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMAX, vAxMax) ; - // recupero massima elevazione - double dElev = 0 ; - m_pGeomDB->GetInfo( m_nCLPathId, KEY_ELEV, dElev) ; - // recupero il numero di eventi ausiliari di inizio - if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) - m_nAuxSTot = 0 ; - m_nAuxSInd = 0 ; - // reset numero eventi ausiliari di fine - m_nAuxEInd = 0 ; - m_nAuxETot = 0 ; - // richiamo gestione evento inizio percorso di lavoro - if ( ! OnPathStart( m_nCLPathId, m_nCLPathInd, m_nAuxSTot, ptStart, ptEnd, vtExtr, ptMin, ptMax, vAxMin, vAxMax, dElev)) { - nStatus = CalcStatusOnError( 0) ; - return false ; - } - } - // se altrimenti trovato nuovo CL path vuoto - else if ( m_nCLPathId != GDB_ID_NULL) { - // recupero il numero di eventi ausiliari di inizio - if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) - m_nAuxSTot = 0 ; - m_nAuxSInd = 0 ; - // recupero il numero di eventi ausiliari di fine - if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) - m_nAuxETot = 0 ; - m_nAuxEInd = 0 ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ManagePathEnd( int& nStatus) -{ - // recupero il numero di eventi ausiliari di fine - if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) - m_nAuxETot = 0 ; - m_nAuxEInd = 0 ; - // richiamo gestione evento fine percorso di lavoro - bool bOk = OnPathEnd( m_nAuxETot) ; - // gestione stato - if ( ! bOk) - nStatus = CalcStatusOnError( 0) ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ManagePathStartAux( int& nStatus) -{ - // aggiorno indice corrente - ++ m_nAuxSInd ; - // recupero i dati per l'evento corrente - string sAS ; - if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS + ToString( m_nAuxSInd), sAS)) { - nStatus = MCH_SIM_ERR ; - return false ; - } - // richiamo gestione evento ausiliario prima di inizio percorso di lavoro - int nErr ; - if ( ! OnPathStartAux( m_nAuxSInd, sAS, nErr)) { - nStatus = CalcStatusOnError( nErr) ; - return false ; - } - nStatus = MCH_SIM_END_STEP ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ManagePathEndAux( int& nStatus) -{ - // aggiorno indice corrente - ++ m_nAuxEInd ; - // recupero i dati per l'evento corrente - string sAE ; - if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE + ToString( m_nAuxEInd), sAE)) { - nStatus = MCH_SIM_ERR ; - return false ; - } - // richiamo gestione evento ausiliario dopo fine percorso di lavoro - int nErr ; - if ( ! OnPathEndAux( m_nAuxEInd, sAE, nErr)) { - nStatus = CalcStatusOnError( nErr) ; - return false ; - } - nStatus = MCH_SIM_END_STEP ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ManageMove( int& nStatus) -{ - // Imposto lunghezza di movimento effettuata - double dCurrMove = 0 ; - while ( m_nEntId != GDB_ID_NULL) { - // eseguo movimento singolo - double dMove ; - if ( ! ManageSingleMove( nStatus, dMove)) - return false ; - dCurrMove += dMove ; - // se modalità play e fine entità e non raggiunta la lunghezza di movimento voluto - if ( m_nUiStatus == MCH_UISIM_PLAY && nStatus == MCH_SIM_END_STEP && dCurrMove < 0.75 * m_dStep) { - // recupero una nuova entità - m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; - m_dCoeff = 0 ; - } - else - break ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ManageSingleMove( int& nStatus, double& dMove) -{ - // Recupero posizione finale - const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; - if ( pCamData == nullptr) { - nStatus = MCH_SIM_ERR ; - return false ; - } - switch ( pCamData->GetAxesStatus()) { - case CamData::AS_OK : - break ; - case CamData::AS_OUTSTROKE : { - DBLVECTOR OutAxes = pCamData->GetAxesVal() ; - for ( size_t i = OutAxes.size() ; i < 5 ; ++ i) - OutAxes.emplace_back( 0) ; - DBLVECTOR vAng( OutAxes.begin() + 3, OutAxes.end()) ; - int nStat ; - m_pMachine->VerifyOutstroke( OutAxes[0], OutAxes[1], OutAxes[2], vAng, true, nStat) ; - nStatus = MCH_SIM_OUTSTROKE ; - return false ; } - case CamData::AS_DIR_ERR : - nStatus = MCH_SIM_DIR_ERR ; - return false ; - default : - nStatus = MCH_SIM_ERR ; - return false ; - } - DBLVECTOR AxesEnd = pCamData->GetAxesVal() ; - // Tipo di movimento - int nMoveType = pCamData->GetMoveType() ; - // Se inizio di nuova entità, mascheratura movimento - if ( m_nEntId != GDB_ID_NULL && m_dCoeff < EPS_ZERO) - m_nAxesMask = pCamData->GetAxesMask() ; - // Se movimento in rapido muovo solo gli assi abilitati dal mask - if ( nMoveType == 0) { - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { - if ( ( m_nAxesMask & 1 << i) == 0) - AxesEnd[i] = m_AxesVal[i] ; - } - } - - // Se inizio di nuova entità - if ( m_nEntId != GDB_ID_NULL && m_dCoeff < EPS_ZERO) { - ++ m_nEntInd ; - const CamData* pNextCamData = GetCamData( m_pGeomDB->GetUserObj( m_pGeomDB->GetNext( m_nEntId))) ; - int nErr ; - if ( ! OnMoveStart( pCamData, pNextCamData, nErr)) { - nStatus = CalcStatusOnError( nErr) ; - return false ; - } - // Se movimento in rapido aggiorno quote degli assi disabilitati dal mask - if ( nMoveType == 0) { - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { - if ( ( m_nAxesMask & 1 << i) == 0) - AxesEnd[i] = m_AxesVal[i] ; - } - } - } - - // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) - bool bOkI = true ; - PNTVECTOR vPtNoseI( m_VmTool.size()) ; - VCT3DVECTOR vVtDirI( m_VmTool.size()) ; - VCT3DVECTOR vVtAuxI( m_VmTool.size()) ; - for ( int i = 0 ; i < int( m_VmTool.size()) ; ++ i) - bOkI = GetHeadCurrPosDirAux( m_VmTool[i].sHead, m_VmTool[i].nExit, vPtNoseI[i], vVtDirI[i], vVtAuxI[i]) && bOkI ; - vector vFrVzmI( m_VmId.size()) ; - for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i) - bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ; - - // Dati per eventuale verifica di collisione - int nCdInd, nObjInd ; - bool bCollCheck = true ; - - // Eseguo movimento assi principali ed eventuali ausiliari - if ( m_bEnabAxes) { - // Calcolo distanza di movimento - double dSqDist = 0 ; - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { - // coefficiente moltiplicativo per differenziare assi lineari e rotanti - double dSqCoeff = ( m_AxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; - dSqDist += dSqCoeff * ( AxesEnd[i] - m_AxesVal[i]) * ( AxesEnd[i] - m_AxesVal[i]) ; - } - // Calcolo distanza di movimento eventuali assi ausiliari - double dSqDistAux = 0 ; - for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { - if ( m_AuxAxesLink[i] != 0) - continue ; - // coefficiente moltiplicativo per differenziare assi lineari e rotanti - double dSqCoeff = ( m_AuxAxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; - dSqDistAux += dSqCoeff * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) ; - } - // Considero il massimo delle due distanze - double dPrevCoeff = m_dCoeff ; - double dDist = sqrt( max( dSqDist, dSqDistAux)) ; - if ( dDist > EPS_SMALL) { - double dStep = min( ( nMoveType == 0 ? 2 : 1) * m_dStep, MAX_STEP) ; - int nStep = max( int( dDist / dStep), 1) ; - m_dCoeff += 1. / nStep ; - if ( m_dCoeff > 1) - m_dCoeff = 1 ; - } - else - m_dCoeff = 1 ; - dMove = ( m_dCoeff - dPrevCoeff) * dDist ; - - // Log per debug - if ( ExeGetDebugLevel() >= 10) { - string sOut = "MoveType=" + ToString( nMoveType) + " Coeff=" + ToString( m_dCoeff) ; - LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) - } - - // Eseguo movimento rapido o lineare (non arco) - if ( nMoveType != 2 && nMoveType != 3) { - // se attivo CollisionCheck approssimo movimento con più step - int nStep = 1 ; - if ( NeedCollisionCheck()) - nStep = max( int( dMove / COLL_STEP), 1) ; - for ( int i = 1 ; i <= nStep ; ++ i) { - double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; - DBLVECTOR vDeltaVal( m_AxesName.size()) ; - // assegno posizioni finali - for ( int j = 0 ; j < int( m_AxesName.size()) ; ++ j) { - double dPrevVal ; - m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ; - double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; - m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; - vDeltaVal[j] = dVal - dPrevVal ; - } - // muovo eventuali assi ausiliari - for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { - double dVal = 0 ; - if ( m_AuxAxesLink[j] == 0) { - dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; - } - else { - m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ; - if ( m_AuxAxesLink[j] > 0) - dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ; - else - dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ; - } - m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; - } - // se abilitato e non è rapido o non c'è verifica collisioni, eseguo eventuale Vmill - if ( m_bEnableVm && ( nMoveType != 0 || ! NeedCollisionCheck())) { - for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { - Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; - bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; - for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { - Frame3d frVzmF ; - bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; - ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, - vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; - // se ultimo utensile, salvo riferimento per prossimo inizio - if ( j == int( m_VmTool.size()) - 1) - vFrVzmI[k] = frVzmF ; - } - // aggiorno prossimo inizio - vPtNoseI[j] = ptNoseF ; - vVtDirI[j] = vtDirF ; - vVtAuxI[j] = vtAuxF ; - } - } - // eseguo eventuale collision check - bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; - } - } - // Eseguo movimento su arco - else { - // dati dell'arco - Point3d ptCen = pCamData->GetAxesCen() ; - double dAngCen = pCamData->GetAxesAngCen() ; - double dRad = pCamData->GetAxesRad() ; - Vector3d vtN = pCamData->GetAxesNormDir() ; - double dDeltaN = ( Point3d( AxesEnd[0], AxesEnd[1], AxesEnd[2]) - ptCen) * vtN ; - double dDiffAng = ( m_dCoeff - dPrevCoeff) * dAngCen ; - Vector3d vtRot = Point3d( m_AxesVal[0], m_AxesVal[1], m_AxesVal[2]) - ptCen ; - vtRot.Rotate( vtN, dPrevCoeff * dAngCen) ; - // se attivi Vmill o CollisionCheck approssimo movimento con più step - int nStep = 1 ; - if ( ! m_VmId.empty() || NeedCollisionCheck()) { - const double MIN_LEN_STEP = 2. ; - const double MAX_LEN_STEP = 10. ; - double dLenStep = Clamp( 0.1 * m_dTDiam, MIN_LEN_STEP, MAX_LEN_STEP) ; - nStep = max( int( abs( dDiffAng * DEGTORAD * dRad) / dLenStep), 1) ; - const double ANG_STEP = 5. ; - if ( abs( dDiffAng) / nStep > ANG_STEP) - nStep = int( abs( dDiffAng) / ANG_STEP) ; - } - for ( int i = 1 ; i <= nStep ; ++ i) { - double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; - DBLVECTOR vDeltaVal( m_AxesName.size()) ; - // assi lineari - vtRot.Rotate( vtN, dDiffAng / nStep) ; - double dPrevVal, dVal ; - m_pMachine->GetAxisPos( m_AxesName[0], dPrevVal) ; - dVal = ptCen.x + vtRot.x + dCurrCoeff * dDeltaN * vtN.x ; - m_pMachine->SetAxisPos( m_AxesName[0], dVal) ; - vDeltaVal[0] = dVal - dPrevVal ; - m_pMachine->GetAxisPos( m_AxesName[1], dPrevVal) ; - dVal = ptCen.y + vtRot.y + dCurrCoeff * dDeltaN * vtN.y ; - m_pMachine->SetAxisPos( m_AxesName[1], dVal) ; - vDeltaVal[1] = dVal - dPrevVal ; - m_pMachine->GetAxisPos( m_AxesName[2], dPrevVal) ; - dVal = ptCen.z + vtRot.z + dCurrCoeff * dDeltaN * vtN.z ; - m_pMachine->SetAxisPos( m_AxesName[2], dVal) ; - vDeltaVal[2] = dVal - dPrevVal ; - // assi rotanti - for ( int j = 3 ; j < int( m_AxesName.size()) ; ++ j) { - double dPrevVal ; m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ; - double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; - m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; - vDeltaVal[j] = dVal - dPrevVal ; - } - // eventuali assi ausiliari - for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { - double dVal = 0 ; - if ( m_AuxAxesLink[j] == 0) { - dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; - } - else { - m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ; - if ( m_AuxAxesLink[j] > 0) - dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ; - else - dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ; - } - m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; - } - // se abilitato, eseguo eventuale Vmill - for ( int j = 0 ; m_bEnableVm && j < int( m_VmTool.size()) ; ++ j) { - Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; - bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; - for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { - Frame3d frVzmF ; - bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; - ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, - vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; - // se ultimo utensile, salvo riferimento per prossimo inizio - if ( j == int( m_VmTool.size()) - 1) - vFrVzmI[k] = frVzmF ; - } - // aggiorno prossimo inizio - vPtNoseI[j] = ptNoseF ; - vVtDirI[j] = vtDirF ; - vVtAuxI[j] = vtAuxF ; - } - // eseguo eventuale collision check - bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; - } - } - } - - // altrimenti eseguo movimento soli eventuali assi ausiliari - else { - // Calcolo distanza di movimento - double dSqDist = 0 ; - for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { - // coefficiente moltiplicativo per differenziare assi lineari e rotanti - double dSqCoeff = ( m_AuxAxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; - dSqDist += dSqCoeff * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) ; - } - double dPrevCoeff = m_dCoeff ; - double dDist = sqrt( dSqDist) ; - if ( dDist > EPS_SMALL) { - double dStep = min( ( nMoveType == 0 ? 2 : 1) * m_dStep, MAX_STEP) ; - int nStep = max( int( dDist / dStep), 1) ; - m_dCoeff += 1. / nStep ; - if ( m_dCoeff > 1) - m_dCoeff = 1 ; - } - else - m_dCoeff = 1 ; - dMove = ( m_dCoeff - dPrevCoeff) * dDist ; - // se attivo CollisionCheck approssimo movimento con più step - int nStep = 1 ; - if ( NeedCollisionCheck()) - nStep = max( int( dMove / COLL_STEP), 1) ; - for ( int i = 1 ; i <= nStep ; ++ i) { - double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; - // muovo eventuali assi ausiliari - for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { - if ( m_AuxAxesLink[j] == 0) { - double dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; - m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; - } - } - // se abilitato e non è rapido o non c'è verifica collisioni, eseguo eventuale Vmill - if ( m_bEnableVm && ( nMoveType != 0 || ! NeedCollisionCheck())) { - for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { - Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; - bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; - for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { - Frame3d frVzmF ; - bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; - ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, - vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; - // se ultimo utensile, salvo riferimento per prossimo inizio - if ( j == int( m_VmTool.size()) - 1) - vFrVzmI[k] = frVzmF ; - } - // aggiorno prossimo inizio - vPtNoseI[j] = ptNoseF ; - vVtDirI[j] = vtDirF ; - vVtAuxI[j] = vtAuxF ; - } - } - // eseguo eventuale collision check - bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; - } - } - - // Se riscontrata collisione - if ( ! bCollCheck) { - // Richiamo funzione di convalida collisione - int nErr ; - if ( ! OnCollision( nCdInd, nObjInd, nErr)) { - nStatus = CalcStatusOnError( nErr) ; - // Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo - if ( m_dCoeff > COEFF_LIM) { - if ( m_bEnabAxes) { - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) - m_AxesVal[i] = AxesEnd[i] ; - } - // richiamo gestione evento fine entità, senza gestirne eventuali errori - int nErr ; - OnMoveEnd( nErr) ; - } - return false ; - } - } - - // Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo - if ( m_dCoeff > COEFF_LIM) { - if ( m_bEnabAxes) { - for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) - m_AxesVal[i] = AxesEnd[i] ; - } - nStatus = MCH_SIM_END_STEP ; - // richiamo gestione evento fine entità - int nErr ; - if ( ! OnMoveEnd( nErr)) { - nStatus = CalcStatusOnError( nErr) ; - return false ; - } - } - // Altrimenti sto muovendomi all'interno dell'entità - else - nStatus = MCH_SIM_OK ; - - return true ; -} - -//---------------------------------------------------------------------------- -int -Simulator::CalcStatusOnError( int nErr) -{ - if ( Stopped()) - return MCH_SIM_STOP ; - else if ( nErr == ERR_OUTSTROKE) - return MCH_SIM_OUTSTROKE ; - else if ( nErr == ERR_COLLISION) - return MCH_SIM_COLLISION ; - else - return MCH_SIM_ERR ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA) -{ - int nHeadId = m_pMachine->GetHeadId( sHead) ; - int nExitId = m_pMachine->GetExitId( sHead, nExit) ; - if ( nHeadId == GDB_ID_NULL || nExitId == GDB_ID_NULL) - return false ; - Frame3d frExit ; m_pGeomDB->GetGroupGlobFrame( nExitId, frExit) ; - ptH = frExit.Orig() ; - vtH = frExit.VersZ() ; - vtA = V_NULL ; - int nDirAuxId = m_pGeomDB->GetFirstNameInGroup( nHeadId, MCH_AUX_VECT) ; - if ( nDirAuxId != GDB_ID_NULL) { - const IGeoVector3d* pGV = GetGeoVector3d( m_pGeomDB->GetGeoObj( nDirAuxId)) ; - if ( pGV != nullptr) { - Frame3d frHead ; m_pGeomDB->GetGroupGlobFrame( nHeadId, frHead) ; - vtA = pGV->GetVector() ; - vtA.ToGlob( frHead) ; - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, - const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, - const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) -{ - // Recupero Zmap - IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( nVmId)) ; - if ( pVZM == nullptr) { - string sOut = " --> GetVolZmap (" + ToString( nVmId) +") Error <--" ; - LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) - return false ; - } - // Porto gli estremi nel riferimento opportuno dello Zmap - Point3d ptHiL = ptHi ; ptHiL.ToLoc( frVzmI) ; - Vector3d vtHiL = vtHi ; vtHiL.ToLoc( frVzmI) ; - Vector3d vtAiL = vtAi ; vtAiL.ToLoc( frVzmI) ; - Point3d ptHfL = ptHf ; ptHfL.ToLoc( frVzmF) ; - Vector3d vtHfL = vtHf ; vtHfL.ToLoc( frVzmF) ; - Vector3d vtAfL = vtAf ; vtAfL.ToLoc( frVzmF) ; - // Eventuali offset - ptHiL += dVmTdOffs * vtHiL + dVmAdOffs * vtAiL ; - ptHfL += dVmTdOffs * vtHfL + dVmAdOffs * vtAfL ; - // Log per debug - if ( ExeGetDebugLevel() >= 10) { - string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) + - " Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + - ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; - LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) - } - // Se utensile che non lavora di testa - if ( ! m_bCutOnTip) { - // se movimento di testa (angolo movimento verso la testa oltre 5.8deg), non eseguo asportazione - Vector3d vtDirM = Media( vtHiL, vtHfL) ; - vtDirM.Normalize() ; - double dAxMove = ( ptHfL - ptHiL) * vtDirM ; - if ( dAxMove < -EPS_SMALL) { - double dMove = ( ptHfL - ptHiL).Len() ; - if ( dAxMove < -0.1 * abs( dMove)) - return true ; - } - } - // Eseguo - bool bOk = pVZM->MillingStep( nCurrTool, ptHiL, vtHiL, vtAiL, ptHfL, vtHfL, vtAfL) ; - if ( ! bOk) { - if ( ExeGetDebugLevel() < 10) { - string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) + - " Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + - ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; - LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) - } - LOG_DBG_INFO( GetEMkLogger(), " --> MillingStep Error <--") - } - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) -{ - // se non ci sono oggetti da controllare o non ci sono grezzi o equivalenti, tutto bene - if ( ! NeedCollisionCheck()) - return true ; - // ciclo sui grezzi o equivalenti - for ( int i = 0 ; i < int( m_CdId.size()) ; ++ i) { - // se modo hidden è da saltare - int nMode ; - if ( m_pGeomDB->GetCalcMode( m_CdId[i], nMode) && nMode == GDB_MD_HIDDEN) - continue ; - // verifico se è il grezzo in lavorazione - bool bIsRaw = ( find( m_VmId.begin(), m_VmId.end(), m_CdId[i]) != m_VmId.end()) ; - // recupero solido o trimesh, se altro lo salto - const IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( m_CdId[i])) ; - const ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeomDB->GetGeoObj( m_CdId[i])) ; - if ( pVZM == nullptr && pSTM == nullptr) - continue ; - // recupero il riferimento - Frame3d frCd ; m_pGeomDB->GetGlobFrame( m_CdId[i], frCd) ; - // ciclo sugli oggetti con cui verificare - for ( int j = 0 ; j < int( m_CollObj.size()) ; ++ j) { - // se modo hidden è da saltare - int nMode ; - if ( m_pGeomDB->GetCalcMode( m_CollObj[j].nFrameId, nMode) && nMode == GDB_MD_HIDDEN) - continue ; - // verifico se è l'utensile attivo - string sHead ; m_pGeomDB->GetName( m_pGeomDB->GetParentId( m_CollObj[j].nFrameId), sHead) ; - string sExit ; m_pGeomDB->GetName( m_CollObj[j].nFrameId, sExit) ; - bool bIsTool = m_CollObj[j].bToolOn || - ( sHead == m_sHead && ( sExit == "_T" + ToString( m_nExit) || sExit == "_TT" + ToString( m_nExit))) ; - // se utensile attivo su grezzo in lavoro e non è rapido, salto - if ( bIsTool && bIsRaw && nMoveType != 0) - continue ; - // esecuzione controlli di collisione - bool bOk = true ; - // oggetti che richiedono frame associato (Box, Cylinder, Sphere, Cone) - if ( m_CollObj[j].nType != MCH_SIM_COB_POLY) { - // se riferimento non trovato, si salta - const IGeoFrame3d* pGeoFrame = GetGeoFrame3d( m_pGeomDB->GetGeoObj( m_CollObj[j].nFrameId)) ; - if ( pGeoFrame == nullptr) - continue ; - Frame3d frObj = pGeoFrame->GetFrame() ; - if ( ! m_CollObj[j].vtMove.IsSmall()) - frObj.Translate( m_CollObj[j].vtMove.x * frObj.VersX() + - m_CollObj[j].vtMove.y * frObj.VersY() + - m_CollObj[j].vtMove.z * frObj.VersZ()) ; - Frame3d frParent ; m_pGeomDB->GetGlobFrame( m_CollObj[j].nFrameId, frParent) ; - frObj.LocToLoc( frParent, frCd) ; - // controlli di collisione - if ( m_CollObj[j].nType == MCH_SIM_COB_BOX) { - Vector3d vtDiag( m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3) ; - if ( pVZM != nullptr) - bOk = ! pVZM->CDeBox( frObj, vtDiag, m_dSafeDist) ; - else - bOk = ! CDeBoxClosedSurfTm( frObj, vtDiag, *pSTM, m_dSafeDist) ; - } - else if ( m_CollObj[j].nType == MCH_SIM_COB_CYL) { - if ( pVZM != nullptr) - bOk = ! pVZM->CDeCylinder( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_dSafeDist) ; - else - bOk = ! CDeCylClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, *pSTM, m_dSafeDist) ; - } - else if ( m_CollObj[j].nType == MCH_SIM_COB_SPHE) { - if ( pVZM != nullptr) - bOk = ! pVZM->CDeSphere( frObj.Orig(), m_CollObj[j].dPar1, m_dSafeDist) ; - else - bOk = ! CDeSpheClosedSurfTm( frObj.Orig(), m_CollObj[j].dPar1, *pSTM, m_dSafeDist) ; - } - else if ( m_CollObj[j].nType == MCH_SIM_COB_CONE) { - if ( pVZM != nullptr) - bOk = ! pVZM->CDeConeFrustum( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3, m_dSafeDist) ; - else - bOk = ! CDeConeFrustumClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3, *pSTM, m_dSafeDist) ; - } - } - // altrimenti poliedro - else { - SurfLocal SurfLoc( m_pGeomDB, m_CollObj[j].nFrameId, frCd) ; - const ISurfTriMesh* pStmLoc = GetSurfTriMesh( SurfLoc) ; - if ( pStmLoc != nullptr) { - if ( pVZM != nullptr) - bOk = ! pVZM->CDeSurfTm( *pStmLoc, m_dSafeDist) ; - else - bOk = ! CDeClosedSurfTmClosedSurfTm( *pStmLoc, *pSTM, m_dSafeDist) ; - } - else - bOk = false ; - } - // se trovata collisione - if ( ! bOk) { - nCdInd = i ; - nObjInd = j ; - return false ; - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -static int -FindCollisionMarkId( const IGeomDB* pGeomDB, int nCollId) -{ - int nCollParId = pGeomDB->GetParentId( nCollId) ; - string sCollParName = "COLLISION" ; - pGeomDB->GetName( nCollParId, sCollParName) ; - if ( sCollParName != "COLLISION") - return nCollParId ; - else { - int nCollGprId = pGeomDB->GetParentId( nCollParId) ; - int nCollSolId = pGeomDB->GetFirstNameInGroup( nCollGprId, "SOLID") ; - if ( nCollSolId != GDB_ID_NULL) - return nCollSolId ; - else - return nCollGprId ; - } -} - -//---------------------------------------------------------------------------- -bool -Simulator::SetCollisionMark( int nCdInd, int nObjInd) -{ - if ( m_pGeomDB == nullptr) - return false ; - m_nCollMarkId.clear() ; - int nCdMarkId = FindCollisionMarkId( m_pGeomDB, m_CdId[nCdInd]) ; - m_pGeomDB->SetMark( nCdMarkId, GDB_MK_ON) ; - m_nCollMarkId.push_back( nCdMarkId) ; - int nCoMarkId = FindCollisionMarkId( m_pGeomDB, m_CollObj[nObjInd].nFrameId) ; - m_pGeomDB->SetMark( nCoMarkId, GDB_MK_ON_2) ; - m_nCollMarkId.push_back( nCoMarkId) ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::ResetCollisionMark( void) -{ - if ( m_pGeomDB == nullptr) - return false ; - for ( auto nId : m_nCollMarkId) - m_pGeomDB->ResetMark( nId) ; - m_nCollMarkId.clear() ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnInit( void) -{ - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_INIT)) - return true ; - // chiamo la funzione di ingresso nella simulazione - return m_pMachine->LuaCallFunction( ON_SIMUL_INIT) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnExit( void) -{ - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_EXIT)) - return true ; - // chiamo la funzione di uscita dalla simulazione - return m_pMachine->LuaCallFunction( ON_SIMUL_EXIT) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnProgramStart( bool bFirst) -{ - // assegno flag inizio simulazione - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIM1ST, bFirst) ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_START)) - return true ; - // chiamo la funzione di inizio simulazione - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_START) ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnProgramEnd( void) -{ - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_END)) - return true ; - // chiamo la funzione di fine simulazione - return m_pMachine->LuaCallFunction( ON_SIMUL_END) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnDispositionStarting( int nOpId, int nOpInd, int nPhase, - const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) -{ - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; - // assegno nuovo indice di fase - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; - // assegno nome e valore riferimento della tavola corrente - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; - // assegno flag disposizione passiva - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; - // assegno flag disposizione con operazioni manuali - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_STARTING)) - return true ; - // chiamo la funzione di inizio disposizione - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_STARTING) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnDispositionStart( int nOpId, int nOpInd, int nPhase, - const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) -{ - // assegno identificativo e indice disposizione - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; - // assegno nuovo indice di fase - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; - // assegno nome e valore riferimento della tavola corrente - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; - // assegno flag disposizione passiva - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; - // assegno flag disposizione con operazioni manuali - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_START)) - return true ; - // chiamo la funzione di inizio disposizione - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_START) ; - // recupero i dati di ritorno - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnDispositionEnd( void) -{ - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_END)) - return true ; - // chiamo la funzione di fine disposizione - bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_END) ; - // recupero i dati di ritorno - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnToolSelect( const string& sTool, const string& sHead, int nExit, const string& sTcPos, - bool bFirst, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // reset oggetti per verifica collisione con grezzo - m_CollObj.clear() ; - // assegno il nome dell'utensile, la testa e l'uscita - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TOOL, sTool) || - ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_HEAD, sHead) || - ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXIT, nExit) || - ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TCPOS, sTcPos)) - return false ; - // assegno il token e il nome degli assi - bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; - int nNumAxes = int( m_AxesName.size()) ; - for ( int i = 1 ; i <= MAX_AXES ; ++ i) { - if ( i <= nNumAxes) { - if ( ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisToken( i, bIsRobot), m_AxesToken[i-1]) || - ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisName( i, bIsRobot), m_AxesName[i-1])) - return false ; - } - else { - if ( ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisToken( i, bIsRobot)) || - ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisName( i, bIsRobot))) - return false ; - } - } - // assegno il flag di chiamata di utensile iniziale - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FIRST, bFirst)) - return false ; - // reset errore - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) - return false ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_SELECT)) - return true ; - // chiamo la funzione di selezione utensile - bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_SELECT) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - // recupero dati per verifica collisione - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SAFEDIST, m_dSafeDist) ; - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; - // verifico codice di errore - bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - // recupero i dati di ritorno per assi ausiliari - ResetAuxAxes() ; - int nNumAuxAxes = 0 ; - if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) - return ( bOk && nErr == 0) ; - m_AuxAxesName.reserve( nNumAuxAxes) ; - m_AuxAxesToken.reserve( nNumAuxAxes) ; - m_AuxAxesInvert.reserve( nNumAuxAxes) ; - m_AuxAxesOffset.reserve( nNumAuxAxes) ; - m_AuxAxesLinear.reserve( nNumAuxAxes) ; - m_AuxAxesVal.reserve( nNumAuxAxes) ; - m_AuxAxesEnd.reserve( nNumAuxAxes) ; - for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) { - string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; - string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ; - if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) && - m_pMachine->GetAxisToken( sName, sToken) && - m_pMachine->GetAxisInvert( sName, bInvert) && - m_pMachine->GetAxisOffset( sName, dOffset) && - m_pMachine->GetAxisType( sName, bLinear) && - m_pMachine->GetAxisPos( sName, dVal)) { - // se non è già negli assi principali, lo aggiungo - if ( find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) { - m_AuxAxesName.emplace_back( sName) ; - m_AuxAxesToken.emplace_back( sToken) ; - m_AuxAxesInvert.push_back( bInvert) ; - m_AuxAxesOffset.push_back( dOffset) ; - m_AuxAxesLinear.push_back( bLinear) ; - m_AuxAxesVal.emplace_back( dVal) ; - m_AuxAxesEnd.emplace_back( dVal) ; - m_AuxAxesLink.emplace_back( 0) ; - } - } - else { - bOk = false ; - nErr = ERR_TOOL_SEL ; - } - } - - return ( bOk && nErr == 0) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // assegno il prossimo utensile - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTOOL, sNextTool) ; - // assegno la prossima testa - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTHEAD, sNextHead) ; - // assegno la prossima uscita - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTEXIT, nNextExit) ; - // assegno l'eventuale prossima posizione nel TC - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTCPOS, sNextTcPos) ; - // reset errore - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_DESELECT)) - return bOk ; - // chiamo la funzione di deselezione utensile - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_DESELECT) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - // verifico codice di errore - bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, - const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) -{ - // assegno identificativo e indice lavorazione - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHID, nOpId) || - ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHIND, nOpInd)) - return false ; - // assegno punti estremi dell'ingombro della lavorazione - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMIN, ptMin) || - ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMAX, ptMax)) - return false ; - // assegno punti estremi dell'ingombro degli assi della lavorazione - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMIN, vAxMin) || - ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMAX, vAxMax)) - return false ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_START)) - return true ; - // chiamo la funzione di inizio disposizione - bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_START) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnMachiningEnd( void) -{ - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_END)) - return true ; - // chiamo la funzione di fine lavorazione - bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_END) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, - const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, - const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) -{ - // assegno identificativo e indice percorso di lavorazione - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHID, nClPathId) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHIND, nClPathInd) ; - // assegno numero di dati ausiliari iniziali - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAS) ; - // assegno punti iniziale e finale e versore estrusione - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_START, ptStart) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_END, ptEnd) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXTR, vtExtr) ; - // assegno punti estremi dell'ingombro del percorso di lavorazione - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMIN, ptMin) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMAX, ptMax) ; - // assegno punti estremi dell'ingombro degli assi della lavorazione - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMIN, vAxMin) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMAX, vAxMax) ; - // assegno la massima elevazione - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ELEV, dElev) ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START)) - return bOk ; - // chiamo la funzione di inizio percorso di lavorazione - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnPathEnd( int nAE) -{ - // assegno numero di dati ausiliari finali - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAE) ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END)) - return bOk ; - // chiamo la funzione di fine percorso di lavorazione - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnPathStartAux( int nInd, const string& sAS, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START_AUX)) - return true ; - // assegno indice, valore dato ausiliario e resetto errore - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAS) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - // chiamo la funzione di evento ausiliario all'inizio del percorso - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START_AUX) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - // verifico codice di errore - bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnPathEndAux( int nInd, const string& sAE, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END_AUX)) - return true ; - // assegno indice, valore dato ausiliario e resetto errore - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAE) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - // chiamo la funzione di evento ausiliario alla fine del percorso - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END_AUX) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - // verifico codice di errore - bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // recupero e assegno i dati - // dati generali e reset errore - bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEID, m_nEntId) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEIND, m_nEntInd) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVE, pCamData->GetMoveType()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MASK, pCamData->GetAxesMask()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG, pCamData->GetFlag()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG2, pCamData->GetFlag2()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INDEX, pCamData->GetIndex()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - // valore degli assi all'inizio e alla fine del movimento - bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; - int nNumAxes = int( m_AxesName.size()) ; - const DBLVECTOR& AxesEnd = pCamData->GetAxesVal() ; - for ( int i = 1 ; i <= MAX_AXES ; ++ i) { - if ( i <= nNumAxes) { - bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot), m_AxesVal[i-1]) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot), AxesEnd[i-1]) ; - } - else { - bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot)) ; - bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot)) ; - } - } - // versori utensile, correzione e ausiliario alla fine del movimento - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TDIR, pCamData->GetToolDir()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_CDIR, pCamData->GetCorrDir()) ; - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ADIR, pCamData->GetBackAuxDir()) ; - // anticipazione di alcuni dati dell'eventuale movimento successivo dello stesso percorso - if ( pNextCamData != nullptr && pNextCamData->GetAxesStatus() == CamData::AS_OK) { - bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVESUCC, pNextCamData->GetMoveType()) ; - const DBLVECTOR& AxesNext = pNextCamData->GetAxesVal() ; - for ( int i = 1 ; i <= MAX_AXES ; ++ i) { - if ( i <= nNumAxes) - bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot), AxesNext[i-1]) ; - else - bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ; - } - } - else { - bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_MOVESUCC) ; - for ( int i = 1 ; i <= MAX_AXES ; ++ i) - bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ; - } - // reset abilitazione assi attivi - bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_ENABAXES) ; - // reset numero assi ausiliari - bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_AUXAXES) ; - - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_START)) { - ResetAuxAxes() ; - return bOk ; - } - // chiamo la funzione - bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_START) ; - // con errore, esco - if ( ! bOk) { - ResetAuxAxes() ; - return false ; - } - - // verifico codice di errore - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - if ( nErr != 0) - return false ; - - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - - // reset assi ausiliari - ResetAuxAxes() ; - - // recupero i dati di ritorno - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_MASK, m_nAxesMask) ; - if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ENABAXES, m_bEnabAxes)) - m_bEnabAxes = true ; - if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SHOWAXES, m_bShowAxes)) - m_bShowAxes = m_bEnabAxes ; - int nNumAuxAxes = 0 ; - if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) - return true ; - m_AuxAxesName.reserve( nNumAuxAxes) ; - m_AuxAxesToken.reserve( nNumAuxAxes) ; - m_AuxAxesInvert.reserve( nNumAuxAxes) ; - m_AuxAxesOffset.reserve( nNumAuxAxes) ; - m_AuxAxesLinear.reserve( nNumAuxAxes) ; - m_AuxAxesVal.reserve( nNumAuxAxes) ; - m_AuxAxesEnd.reserve( nNumAuxAxes) ; - for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) { - string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; double dEnd ; string sLink ; - string sAuxAxVal = GLOB_VAR + GVAR_AN ; ReplaceString( sAuxAxVal, "N", ToString( i)) ; - string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ; - string sAuxAxMaster = GLOB_VAR + GVAR_ANM ; ReplaceString( sAuxAxMaster, "N", ToString( i)) ; - if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) && - m_pMachine->GetAxisToken( sName, sToken) && - m_pMachine->GetAxisInvert( sName, bInvert) && - m_pMachine->GetAxisOffset( sName, dOffset) && - m_pMachine->GetAxisType( sName, bLinear) && - m_pMachine->GetAxisPos( sName, dVal)) { - // se assi principali abilitati e da agganciare ad asse principale - if ( m_bEnabAxes && m_pMachine->LuaGetGlobVar( sAuxAxMaster, sLink)) { - bool bNeg = ( sLink.find( '-') != string::npos) ; - string sMainAxis = sLink ; ReplaceString( sMainAxis, "-", "") ; - int nInd = 0 ; - for ( int i = 0 ; nInd == 0 && i < int( m_AxesName.size()) ; ++ i) { - if ( m_AxesName[i] == sMainAxis) - nInd = i + 1 ; - } - // se trovato asse principale di riferimento - if ( nInd > 0) { - m_AuxAxesName.emplace_back( sName) ; - m_AuxAxesToken.emplace_back( sToken) ; - m_AuxAxesInvert.push_back( bInvert) ; - m_AuxAxesOffset.push_back( dOffset) ; - m_AuxAxesLinear.push_back( bLinear) ; - m_AuxAxesVal.emplace_back( 0) ; - m_AuxAxesEnd.emplace_back( 0) ; - m_AuxAxesLink.emplace_back( ( bNeg ? -nInd : nInd)) ; - } - } - // se altrimenti specificato valore finale del movimento - else if ( m_pMachine->LuaGetGlobVar( sAuxAxVal, dEnd)) { - // se assi principali disabilitati o non è tra questi, lo aggiungo - if ( ! m_bEnabAxes || find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) { - m_AuxAxesName.emplace_back( sName) ; - m_AuxAxesToken.emplace_back( sToken) ; - m_AuxAxesInvert.push_back( bInvert) ; - m_AuxAxesOffset.push_back( dOffset) ; - m_AuxAxesLinear.push_back( bLinear) ; - m_AuxAxesVal.emplace_back( dVal) ; - m_AuxAxesEnd.emplace_back( dEnd) ; - m_AuxAxesLink.emplace_back( 0) ; - if ( ! m_pMachine->VerifyOutstroke( sName, dEnd)) { - nErr = 1 ; - bOk = false ; - } - } - } - // altrimenti errore - else - bOk = false ; - } - else - bOk = false ; - } - - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnMoveEnd( int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_END)) - return true ; - // reset errore - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) - return false ; - // chiamo la funzione - bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_END) ; - // forzo aggiornamento posizione assi (possono essere stati mossi nello script) - UpdateAxesPos() ; - // verifico codice di errore - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnCollision( int nCdInd, int nObjInd, int& nErr) -{ - // reset stato di errore da script - nErr = 0 ; - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_COLLISION)) - return true ; - // reset stato di errore - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) - return false ; - // assegno identificativi grezzo e oggetto in collisione - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMVMID, m_CdId[nCdInd])) - return false ; - if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMCOBIND, m_CollObj[nObjInd].nInd)) - return false ; - // chiamo la funzione - if ( ! m_pMachine->LuaCallFunction( ON_SIMUL_COLLISION)) - return false ; - // verifico codice di errore - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - // l'errore standard di collisione è stato portato da 1 a 11 per non collidere con altri tipi di errori - if ( nErr == 1) { - nErr = ERR_COLLISION ; - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - } - // evidenzio le geometrie in collisione - if ( nErr == ERR_COLLISION) { - SetCollisionMark( nCdInd, nObjInd) ; - ExeDraw() ; - } - - return ( nErr == 0) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::OnResetMachine( void) -{ - // verifico esistenza funzione - if ( ! m_pMachine->LuaExistsFunction( ON_RESET_MACHINE)) - return true ; - // eseguo reset macchina - return m_pMachine->LuaCallFunction( ON_RESET_MACHINE) ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) -{ - // verifiche sui parametri - if ( nInd <= 0 || nFrameId <= GDB_ID_NULL) - return false ; - switch ( nType) { - case MCH_SIM_COB_BOX : - if ( abs( dPar1) < EPS_SMALL || abs( dPar2) < EPS_SMALL || abs( dPar3) < EPS_SMALL) - return false ; - break ; - case MCH_SIM_COB_CYL : - if ( dPar1 < EPS_SMALL || abs( dPar2) < EPS_SMALL) - return false ; - break ; - case MCH_SIM_COB_SPHE : - if ( dPar1 < EPS_SMALL) - return false ; - break ; - case MCH_SIM_COB_CONE : - if ( ( dPar1 < EPS_SMALL && dPar2 < EPS_SMALL) || dPar3 < EPS_SMALL) - return false ; - break ; - case MCH_SIM_COB_POLY : - if ( ! ExeSurfIsClosed( nFrameId)) - return false ; - break ; - default : - return false ; - } - // aggiungo al vettore - m_CollObj.emplace_back( nInd, bToolOn, nFrameId, nType, vtMove, dPar1, dPar2, dPar3) ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::SetToolForVmill( const string& sTool, const string& sHead, int nExit, int nFlag, double dPar1, double dPar2, - const INTVECTOR& vVmill, bool bFirst) -{ - // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) - CmdLogOff cmdLogOff ; - // se vVmill vuoto, esco - if ( vVmill.empty()) - return true ; - // se utensile, testa o uscita non definiti, reset ed esco - if ( IsEmptyOrSpaces( sTool) || IsEmptyOrSpaces( sHead) || nExit < 1) { - ExeVolZmapResetTools( vVmill) ; - if ( bFirst) - m_bEnableVm = false ; - return false ; - } - // imposto utensile come corrente - string sOldTool ; m_pMchMgr->TdbGetCurrToolParam( TPA_NAME, sOldTool) ; - if ( sTool != sOldTool && ! m_pMchMgr->TdbSetCurrTool( sTool)) { - ExeVolZmapResetTools( vVmill) ; - if ( bFirst) - m_bEnableVm = false ; - return false ; - } - // recupero dati utensile - int nInd = 1 ; - int nType ; m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nType) ; - double dLen ; m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, dLen) ; - double dDiam ; m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, dDiam) ; - double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; - double dCornR ; m_pMchMgr->TdbGetCurrToolParam( TPA_CORNRAD, dCornR) ; - double dSideAng ; m_pMchMgr->TdbGetCurrToolParam( TPA_SIDEANG, dSideAng) ; - double dMaxMat ; m_pMchMgr->TdbGetCurrToolParam( TPA_MAXMAT, dMaxMat) ; - string sNotes ; m_pMchMgr->TdbGetCurrToolParam( TPA_USERNOTES, sNotes) ; - bool bAdditive = ( nFlag == 1) ; - // ricerca dell'outline e del diametro gambo - int nExitId = m_pMachine->GetExitId( sHead, nExit) ; - int nToolId = m_pGeomDB->GetFirstNameInGroup( nExitId, sTool) ; - int nOutlineId = m_pGeomDB->GetFirstNameInGroup( nToolId, "Outline") ; - double dMaxStemDiam = dDiam ; m_pGeomDB->GetInfo( nToolId, "D_STEM", dMaxStemDiam) ; - // imposto profilo utensile per Vmill - if ( bAdditive) - ExeVolZmapSetAdditiveTool( vVmill, sTool, dPar1, dPar2, 0, nInd, bFirst) ; - else if ( nOutlineId != GDB_ID_NULL) - ExeVolZmapSetGenTool( vVmill, sTool, nOutlineId, nInd, bFirst) ; - else if ( nType == TT_MORTISE_STD) - ExeVolZmapSetMortiserTool( vVmill, sTool, dLen, dDiam, dThick, dCornR, nInd, bFirst) ; - else if ( nType == TT_CHISEL_STD) - ExeVolZmapSetChiselTool( vVmill, sTool, dLen, dDiam, dDiam, nInd, bFirst) ; - else if ( nType == TT_SAW_STD || nType == TT_SAW_FLAT) - ExeVolZmapSetSawTool( vVmill, sTool, dLen, dDiam, dThick, 0, dCornR, nInd, bFirst) ; - else if ( nType == TT_WATERJET) - ExeVolZmapSetStdTool( vVmill, sTool, dLen + 50, dDiam, dCornR, dMaxMat, nInd, bFirst) ; - else if ( abs( dSideAng) < EPS_ANG_SMALL || abs( dThick) < EPS_SMALL) { - ExeVolZmapSetStdTool( vVmill, sTool, dLen, dDiam, dCornR, dMaxMat, nInd, bFirst) ; - } - else { - bool bExtra = ( dThick > 0) ; - double dTipLen = abs( dThick) ; - double dTotLen = ( bExtra ? dLen + dTipLen : dLen) ; - double dDelta ; - if ( dSideAng > 0) { - if ( dCornR < EPS_SMALL) - dDelta = 2 * dTipLen * tan( dSideAng * DEGTORAD) ; - else - dDelta = 2 * ( dCornR * cos( dSideAng * DEGTORAD) + ( dTipLen - dCornR + dCornR * sin( dSideAng * DEGTORAD)) * tan( dSideAng * DEGTORAD)) ; - } - else - dDelta = 2 * tan( dSideAng * DEGTORAD) * dTipLen ; - double dStemDiam = ( bExtra ? dDiam : dDiam + dDelta) ; - double dTipDiam = ( bExtra ? dDiam - dDelta : dDiam) ; - ExeVolZmapSetAdvTool( vVmill, sTool, dTotLen, dStemDiam, dTipLen, dTipDiam, dCornR, dMaxMat, nInd, bFirst) ; - } - // eventuali offset per Vmill (per adattare lo ZeroT macchina con quello di Zmap) - double dVmTdOffs = 0 ; - double dVmAdOffs = 0 ; - if ( nType == TT_MORTISE_STD) { - dVmTdOffs = 0 ; - dVmAdOffs = 0.5 * dThick ; - } - else if ( nType == TT_SAW_STD || nType == TT_SAW_FLAT) { - dVmTdOffs = ( ( dLen <= dThick) ? -dLen + dThick : 0) ; - dVmAdOffs = 0 ; - } - // inserisco in lista utensili per virtual milling - if ( bFirst) { - m_VmTool.resize( 1) ; - m_VmTool[0] = VmTool( sTool, sHead, nExit, dVmTdOffs, dVmAdOffs) ; - } - else - m_VmTool.emplace_back( sTool, sHead, nExit, dVmTdOffs, dVmAdOffs) ; - // ripristino eventuale diverso utensile corrente - if ( sTool != sOldTool) - m_pMchMgr->TdbSetCurrTool( sOldTool) ; - - if ( bFirst) - m_bEnableVm = true ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -Simulator::EnableToolsForVmill( bool bEnable) -{ - m_bEnableVm = bEnable ; - return true ; -} - -//---------------------------------------------------------------------------- -int -Simulator::MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) -{ - // Salvo lo step di simulazione corrente - double dOrigStep = m_dStep ; - // Verifico ci siano assi da muovere - if ( vAxNaEpSt.empty()) - return SIM_AXMV_RES_ERR ; - // Tipo di cinematica - bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; - // Numero assi da muovere - int nAxCount = int( vAxNaEpSt.size()) ; - // Posizioni iniziali - DBLVECTOR vPrev( nAxCount) ; - for ( int i = 0 ; i < nAxCount ; ++ i) { - if ( ! m_pMchMgr->GetAxisPos( vAxNaEpSt[i].sName, vPrev[i])) - return SIM_AXMV_RES_ERR ; - } - // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) - bool bExecVmill = (( nMoveType != 0 || ! NeedCollisionCheck()) && ! m_VmTool.empty() && ! m_VmId.empty()) ; - PNTVECTOR vPtNoseI ; - VCT3DVECTOR vVtDirI ; - VCT3DVECTOR vVtAuxI ; - vector vFrVzmI ; - if ( bExecVmill) { - vPtNoseI.resize( m_VmTool.size()) ; - vVtDirI.resize( m_VmTool.size()) ; - vVtAuxI.resize( m_VmTool.size()) ; - vFrVzmI.resize( m_VmId.size()) ; - bool bOkI = true ; - for ( int i = 0 ; i < int( m_VmTool.size()) ; ++ i) - bOkI = GetHeadCurrPosDirAux( m_VmTool[i].sHead, m_VmTool[i].nExit, vPtNoseI[i], vVtDirI[i], vVtAuxI[i]) && bOkI ; - for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i) - bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ; - } - // Determino gli step di movimento - static const int STEP_FEED = -1 ; - static const int STEP_RAPID = -2 ; - static const int STEP_RAPROT = -3 ; - static const int STEP_COLLROT = -4 ; - bool bViewAllFrames = true ; - int nStep = 1 ; - for ( int i = 0 ; i < nAxCount ; ++ i) { - double dMove = abs( vAxNaEpSt[i].dEndPos - vPrev[i]) ; - double dStep = vAxNaEpSt[i].dStep ; - if ( dStep < 0) { - if ( abs( dStep - STEP_FEED) < EPS_SMALL) - dStep = m_dStep ; - else if ( abs( dStep - STEP_RAPID) < EPS_SMALL) - dStep = 4 * m_dStep ; - else if ( abs( dStep - STEP_RAPROT) < EPS_SMALL) { - dStep = 0.4 * m_dStep ; - bViewAllFrames = ( bIsRobot ? true : false) ; - } - else { // STEP_COLLROT - dStep = min( 0.4 * m_dStep, 10.) ; - bViewAllFrames = ( bIsRobot ? true : false) ; - } - } - dStep = max( dStep, 1.) ; - int nAxStep = int( dMove / dStep) + 1 ; - nStep = max( nStep, nAxStep) ; - } - // Eseguo il movimento - for ( int i = 1 ; i <= nStep ; ++ i) { - // Muovo - bool bMoveOk = true ; - double dCoeff = double( i) / nStep ; - for ( int j = 0 ; j < nAxCount ; ++ j) { - bMoveOk = m_pMchMgr->SetAxisPos( vAxNaEpSt[j].sName, ( 1 - dCoeff) * vPrev[j] + dCoeff * vAxNaEpSt[j].dEndPos) && bMoveOk ; - } - // Se abilitato e richiesto, eseguo eventuale Vmill - if ( m_bEnableVm && bExecVmill) { - for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { - Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; - bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; - for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { - Frame3d frVzmF ; - bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; - ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, - vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; - // se ultimo utensile, salvo riferimento per prossimo inizio - if ( j == int( m_VmTool.size()) - 1) - vFrVzmI[k] = frVzmF ; - } - // aggiorno prossimo inizio - vPtNoseI[j] = ptNoseF ; - vVtDirI[j] = vtDirF ; - vVtAuxI[j] = vtAuxF ; - } - } - // Aggiorno visualizzazione - if ( bViewAllFrames || ( i % 4) == 0 || i == nStep) - ExeDraw() ; - // Verifico collisioni - int nCdInd, nObjInd ; - bool bCollCheck = ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; - if ( ! bCollCheck) { - // Richiamo funzione di convalida collisione - int nPrevErr ; - m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nPrevErr) ; - int nErr ; - if ( ! OnCollision( nCdInd, nObjInd, nErr) && nErr == ERR_COLLISION) { - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - if ( ExeGetEnableUI()) { - // Box di messaggio : Collisione! AVVERTIMENTO - ExeMessageBox( ExeGetMsg( 5319), ExeGetMsg( 5315), MB_OK | MB_ICONWARNING) ; - // Gestione Pausa - m_nUiStatus = MCH_UISIM_PAUSE ; - while ( m_nUiStatus == MCH_UISIM_PAUSE) { - // -11 notifica al simulatore pausa dopo collisione - ExeProcessEvents( -11, 4) ; - } - } - } - else { - m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nPrevErr) ; - } - } - // In caso di errore esco - if ( ! bMoveOk) - return SIM_AXMV_RES_ERR ; - // Gestione aggiornamenti... - if ( ExeGetEnableUI()) { - // Aggiornamento interfaccia - ExeProcessEvents( 0, 4) ; - while ( m_nUiStatus == MCH_UISIM_PAUSE) { - ExeProcessEvents( 0, 4) ; - } - // Gestione Stop - if ( m_nUiStatus == MCH_UISIM_STOP) - return SIM_AXMV_RES_STOP ; - // Se cambia lo step di simulazione in modo significativo ... - if ( abs( m_dStep - dOrigStep) > 10 || abs( ( m_dStep - dOrigStep) / ( m_dStep + dOrigStep)) > 0.2) { - double dRat = m_dStep / dOrigStep ; - for ( int j = 0 ; j < nAxCount ; ++ j) { - if ( vAxNaEpSt[j].dStep > 0) - const_cast( vAxNaEpSt[j].dStep) *= dRat ; - } - return MoveAxes( nMoveType, vAxNaEpSt) ; - } - } - } - - return SIM_AXMV_RES_OK ; -} +//---------------------------------------------------------------------------- +// EgalTech 2015-2024 +//---------------------------------------------------------------------------- +// File : SimulatorSP.cpp Data : 01.09.24 Versione : 2.6i1 +// Contenuto : Implementazione della classe SimulatorSP. +// Simulatore singolo processo. +// +// +// Modifiche : 19.10.15 DS Creazione modulo. +// 26.02.16 DS Aggiunta gestione archi. +// 04.01.17 DS Riorganizzazione codice. +// 01.09.24 DS Rinominato. +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "SimulatorSP.h" +#include "MachMgr.h" +#include "Disposition.h" +#include "Machining.h" +#include "MachiningConst.h" +#include "OutputConst.h" +#include "DllMain.h" +#include "/EgtDev/Include/EGkCDeBoxClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeCylClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeSpheClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeConeFrustumClosedSurfTm.h" +#include "/EgtDev/Include/EGkCDeClosedSurfTmClosedSurfTm.h" +#include "/EgtDev/Include/EGkVolZmap.h" +#include "/EgtDev/Include/EGkGeoVector3d.h" +#include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EGkSurfLocal.h" +#include "/EgtDev/Include/EXeCmdLogOff.h" +#include "/EgtDev/Include/EXeConst.h" +#include "/EgtDev/Include/EMkToolConst.h" +#include "/EgtDev/Include/EMkOperationConst.h" +#include "/EgtDev/Include/EgtPerfCounter.h" +#include "/EgtDev/Include/EgtNumUtils.h" + +using namespace std ; + +//------------------------------ Errors -------------------------------------- +// 1001 = "Error with setup : xxx" + +//---------------------------------------------------------------------------- +static const double MIN_STEP = 1.0 ; +static const double MAX_STEP = 500.0 ; +static const double MID_STEP = 50.0 ; +static const double COLL_STEP = 10. ; +static const double SQ_COEFF_ROT_MOVE = 100. ; +static const double COEFF_LIM = 0.999 ; +static const double SAFEDIST_STD = 5.0 ; +static const int ERR_OUTSTROKE = 1 ; +static const int ERR_COLLISION = 11 ; +static const int ERR_TOOL_SEL = 21 ; + +//---------------------------------------------------------------------------- +ISimulator* +CreateSimulatorSP( void) +{ + return static_cast ( new( nothrow) SimulatorSP) ; +} + +//---------------------------------------------------------------------------- +SimulatorSP::SimulatorSP( void) +{ + m_pMchMgr = nullptr ; + m_pGeomDB = nullptr ; + m_pMachine = nullptr ; + m_pPerfCnt = nullptr ; + m_nStatus = SIS_CREATED ; + m_dStep = MID_STEP ; + m_nUiStatus = MCH_UISIM_NULL ; + m_nOpId = GDB_ID_NULL ; + m_nOpInd = 0 ; + m_nCLPathId = GDB_ID_NULL ; + m_nCLPathInd = 0 ; + m_nEntId = GDB_ID_NULL ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + m_nExit = 0 ; + m_dTDiam = 0 ; + m_bCutOnTip = false ; + m_bEnableVm = false ; + m_dSafeDist = SAFEDIST_STD ; + m_nAxesMask = 0 ; + m_bEnabAxes = true ; + m_bShowAxes = true ; + m_AxesName.reserve( 8) ; + m_AxesToken.reserve( 8) ; + m_AxesLinear.reserve( 8) ; + m_AxesVal.reserve( 8) ; +} + +//---------------------------------------------------------------------------- +SimulatorSP::~SimulatorSP( void) +{ + // porto la macchina in posizione home + GoHome() ; + // gestione evento uscita dal simulatore + OnExit() ; + // rimuovo tavola variabili globali + m_pMachine->LuaResetGlobVar( GLOB_VAR) ; + // rimuovo performance counter + if ( m_pPerfCnt != nullptr) { + delete m_pPerfCnt ; + m_pPerfCnt = nullptr ; + } +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::Init( MachMgr* pMchMgr) +{ + // verifico ambiente + if ( pMchMgr == nullptr || pMchMgr->GetContextId() == 0 || + pMchMgr->GetGeomDB() == nullptr || pMchMgr->GetCurrMachine() == nullptr) + return false ; + m_pMchMgr = pMchMgr ; + m_pGeomDB = m_pMchMgr->GetGeomDB() ; + m_pMachine = m_pMchMgr->GetCurrMachine() ; + m_pPerfCnt = new PerformanceCounter ; + m_nStatus = SIS_INITIALIZED ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::Start( bool bFirst) +{ + // Verifico ci sia una macchinata corrente + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr || m_pMachine == nullptr || + m_pMchMgr->GetCurrMachGroup() == GDB_ID_NULL) + return false ; + m_pMchMgr->ResetLastError() ; + m_pMchMgr->ResetWarnings() ; + + bool bOk = true ; + + // Se appena entrati in simulazione + if ( m_nStatus == SIS_INITIALIZED) { + // Forzo aggiornamento attrezzaggio della macchinata + if ( ! m_pMchMgr->UpdateCurrSetup()) + bOk = false ; + // Verifico attrezzaggio + if ( ! VerifySetup()) + bOk = false ; + } + + // Reset utensile, interpolazione e assi correnti + m_sTool.clear() ; + m_sHead.clear() ; + m_nExit = 0 ; + m_dTDiam = 0 ; + m_bCutOnTip = false ; + ResetInterpolation() ; + ResetAxes() ; + ResetAuxAxes() ; + + // porto la macchina in home + if ( ! GoHome()) + bOk = false ; + + // Verifico la disposizione iniziale della macchinata + m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; + m_nOpInd = 1 ; + if ( m_pMchMgr->GetOperationType( m_nOpId) != OPER_DISP) + bOk = false ; + + // Definisco tabella variabili globali + if ( ! m_pMachine->LuaCreateGlobTable( GLOB_VAR)) + bOk = false ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INCHES, ! ExeUiUnitsAreMM()) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_VER, GetEMkVer()) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MACHNAME, m_pMachine->GetMachineName()) ; + + // Se appena entrati in simulazione + if ( m_nStatus == SIS_INITIALIZED) { + if ( ! OnInit()) + bOk = false ; + m_nStatus = SIS_READYTOSTART ; + } + + // Richiamo funzione per evento avvio simulazione + if ( ! OnProgramStart( bFirst)) + bOk = false ; + + // Arrivo alla preparazione per la prima lavorazione + int nStatus ; + if ( ! FindAndManageOperationStart( true, bFirst, nStatus) && nStatus != MCH_SIM_STOP) + bOk = false ; + // se sono ancora su disposizione + if ( m_pMchMgr->GetOperationType( m_nOpId) == OPER_DISP) { + // ricerca e gestione inizio percorso di lavoro + if ( ! FindAndManagePathStart( nStatus)) + return false ; + // eventuali comandi ausiliari di inizio percorso + while ( m_nAuxSInd < m_nAuxSTot) { + if ( ! ManagePathStartAux( nStatus)) + return false ; + } + // aggiornamento assi per eventuali teste caricate + UpdateAxes() ; + } + + // Reset timer + if ( m_pPerfCnt != nullptr) + m_pPerfCnt->Start() ; + + // Imposto lo stato interno + m_nStatus = ( bOk ? SIS_READYTORUN : SIS_READYTOSTART) ; + + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::VerifySetup( void) +{ + // se attrezzaggio non definito, nulla da verificare + if ( ! m_pMchMgr->GetCurrSetupMgr().Exists()) + return true ; + + // lancio la verifica + STRVECTOR vsErr ; + if ( m_pMchMgr->VerifyCurrSetup( vsErr)) + return true ; + + // gestisco errore + string sErr = "Error with setup :" ; + for ( const auto& sTmp : vsErr) + sErr += " " + sTmp ; + m_pMchMgr->SetLastError( 1001, sErr) ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ResetInterpolation( void) +{ + m_nOpId = GDB_ID_NULL ; + m_nOpInd = 0 ; + m_nCLPathId = GDB_ID_NULL ; + m_nCLPathInd = 0 ; + m_nEntId = GDB_ID_NULL ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + m_VmId.clear() ; + m_CdId.clear() ; + m_VmTool.clear() ; + m_CollObj.clear() ; + m_dSafeDist = SAFEDIST_STD ; + m_nAxesMask = 0 ; + m_bEnabAxes = true ; + m_bShowAxes = true ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::Move( int& nStatus) +{ + // Verifiche + if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr || m_nStatus != SIS_READYTORUN) { + nStatus = MCH_SIM_ERR ; + return false ; + } + + // Recupero tempo impiegato (calcolo + visualizzazione precedenti) + if ( m_pPerfCnt != nullptr && ExeGetDebugLevel() >= 5) { + double dElapsed = m_pPerfCnt->Stop() ; + string sOut = "Elapsed=" + ToString( dElapsed, 1) ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + m_pPerfCnt->Start() ; + } + + // reset visualizzazione collisioni + ResetCollisionMark() ; + + // Se arrivato alla fine dell'interpolazione + if ( m_dCoeff > COEFF_LIM) { + // recupero una nuova entità + m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; + m_dCoeff = 0 ; + } + + // Se appena arrivato alla fine di un percorso di lavoro (verifico anche completamento dei comandi aux di start per path vuote) + if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd == 0 && m_nCLPathInd > 0 && m_nAuxSInd >= m_nAuxSTot) { + // gestione fine percorso di lavoro + if ( ! ManagePathEnd( nStatus)) + return false ; + } + + // Se alla fine del percorso dopo esecuzione azioni ausiliarie (verifico anche completamento dei comandi aux di start per path vuote) + if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd >= m_nAuxETot && m_nAuxSInd >= m_nAuxSTot) { + // ricerca e gestione inizio percorso di lavoro + if ( ! FindAndManagePathStart( nStatus)) + return false ; + } + + // Se arrivato alla fine di una operazione + if ( m_nCLPathId == GDB_ID_NULL) { + // gestione fine operazione + if ( ! ManageOperationEnd( nStatus)) + return false ; + // ricerca e gestione nuova operazione + if ( ! FindAndManageOperationStart( false, false, nStatus)) + return false ; + // se non ce ne sono altre, sono alla fine + if ( m_nOpId == GDB_ID_NULL) { + OnProgramEnd() ; + nStatus = MCH_SIM_END ; + return false ; + } + // ricerca e gestione inizio percorso di lavoro + if ( ! FindAndManagePathStart( nStatus)) + return false ; + } + + // Se sto eseguendo i movimenti ausiliari di inizio percorso + if ( m_nAuxSInd < m_nAuxSTot) + return ManagePathStartAux( nStatus) ; + + // Se sto eseguendo i movimenti ausiliari di fine percorso + if ( m_nAuxEInd < m_nAuxETot) + return ManagePathEndAux( nStatus) ; + + // Gestione movimento assi + return ManageMove( nStatus) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::GetAxisInfoPos( int nI, string& sName, string& sToken, bool& bLinear, double& dVal) const +{ + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // numero assi di calcolo e ausiliari + int nAxisCount = ( m_bShowAxes ? int( m_AxesName.size()) : 0) ; + int nAuxAxisCount = int( m_AuxAxesName.size()) ; + // recupero i dati dell'asse + if ( nI < 0 || nI >= nAxisCount + nAuxAxisCount) + return false ; + // se asse principale + if ( nI < nAxisCount) { + sName = m_AxesName[nI] ; + sToken = m_AxesToken[nI] ; + bLinear = m_AxesLinear[nI] ; + } + // altrimenti asse ausiliario + else { + sName = m_AuxAxesName[ nI - nAxisCount] ; + sToken = m_AuxAxesToken[ nI - nAxisCount] ; + bLinear = m_AuxAxesLinear[ nI - nAxisCount] ; + } + // recupero la posizione + if ( ! m_pMchMgr->GetAxisPos( sName, dVal)) + return false ; + // verifico se da invertire o offsettare + if ( nI < nAxisCount) { + if ( m_AxesInvert[nI]) + dVal = - dVal ; + dVal += m_AxesOffset[nI] ; + } + else { + if ( m_AuxAxesInvert[nI - nAxisCount]) + dVal = - dVal ; + dVal += m_AxesOffset[nI - nAxisCount] ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::GetToolInfo( string& sName, double& dSpeed) const +{ + // Inizializzo i parametri di ritorno + sName.clear() ; + dSpeed = 0 ; + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // Assegno il nome dell'utensile + sName = m_sTool ; + if ( sName.empty()) + return true ; + // Recupero speed + const Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; + return ( pMch != nullptr && pMch->GetParam( MPA_SPEED, dSpeed)) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::GetOperationInfo( string& sName, int& nType) const +{ + // Inizializzo i parametri di ritorno + sName.clear() ; + nType = OPER_NULL ; + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // Recupero il tipo + Operation* pOpe = GetOperation( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pOpe == nullptr) + return false ; + nType = pOpe->GetType() ; + // Recupero il nome + return m_pGeomDB->GetName( m_nOpId, sName) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::GetMoveInfo( int& nGmove, double& dFeed) const +{ + // Verifiche + if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) + return false ; + // Recupero il movimento corrente + const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; + if ( pCamData == nullptr) + return false ; + // Assegno feed + dFeed = pCamData->GetFeed() ; + // Assegno tipo di movimento + nGmove = pCamData->GetMoveType() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::SetStep( double dStep) +{ + m_dStep = Clamp( dStep, MIN_STEP, MAX_STEP) ; + // imposto step per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::SetUiStatus( int nUiStatus) +{ + m_nUiStatus = nUiStatus ; + // imposto stato utente del simulatore per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMUISTAT, m_nUiStatus) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::GoHome( void) +{ + // controllo validità stato + if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr) + return false ; + // reset visualizzazione collisioni + ResetCollisionMark() ; + // reset stato macchina + OnResetMachine() ; + // porto la macchina in home + m_pMchMgr->ResetAllAxesPos() ; + // assegno valori home degli assi macchina attivi + return m_pMchMgr->GetAllCurrAxesHomePos( m_AxesVal) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::UpdateTool( bool bFirst, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // Recupero l'utensile della lavorazione corrente + Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pMch != nullptr) { + // recupero nome e dati nuovo utensile + string sTuuid, sTool ; + if ( ! pMch->GetParam( MPA_TUUID, sTuuid) || + ! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool)) + return false ; + string sTcPos ; string sHead ; int nExit ; + if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) { + if ( m_pMchMgr->TdbSetCurrTool( sTool)) { + m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ; + m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ; + m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ; + } + // ripristino l'utensile corrente + m_pMchMgr->TdbSetCurrTool( m_sTool) ; + } + // verifico se cambierà + bool bDiffTool = ( sTool != m_sTool) ; + // se cambierà ed esiste il corrente, lo scarico + if ( bDiffTool && ! m_sTool.empty()) { + // eventuale lancio script per scarico utensile + int nCurrErr ; + if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + // se prima volta, pulisco la testa + if ( bFirst) + m_pMchMgr->ResetHeadSet( sHead) ; + // recupero la lavorazione corrente e imposto la nuova + int nCurrMchId = m_pMchMgr->GetCurrMachining() ; + m_pMchMgr->SetCurrMachining( m_nOpId) ; + // carico l'utensile (e lo rendo corrente) + if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) + return false ; + m_sTool = sTool ; + m_sHead = sHead ; + m_nExit = nExit ; + m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; + double dTipFeed = 0 ; + m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; + m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; + // ripristino la lavorazione corrente + m_pMchMgr->SetCurrMachining( nCurrMchId) ; + // aggiorno gli assi macchina + if ( ! UpdateAxes()) + return false ; + // se cambiato oppure prima volta, lancio lo script di selezione + if ( bDiffTool || bFirst) { + int nCurrErr ; + if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + return ( nErr == 0) ; + } + // Provo con una disposizione + Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pDisp != nullptr) { + // recupero i dati + string sTool ; string sHead ; int nExit ; string sTcPos ; + pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ; + // se esiste utensile corrente e cambierà, lo scarico + if ( ! m_sTool.empty() && sTool != m_sTool) { + // eventuale lancio script per scarico utensile + int nCurrErr ; + if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + // carico l'utensile + if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) + return false ; + m_sTool = sTool ; + m_sHead = sHead ; + m_nExit = nExit ; + m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; + double dTipFeed = 0 ; + m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; + m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; + // aggiorno gli assi macchina + if ( ! UpdateAxes()) + return false ; + // eventuale lancio script + int nCurrErr ; + if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { + nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + return ( nErr == 0) ; + } + return false ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::UpdateAxes( void) +{ + ResetAxes() ; + // Macchina corrente + Machine* pMachine = m_pMchMgr->GetCurrMachine() ; + if ( pMachine == nullptr) + return false ; + // Carico i nomi e i token degli assi macchina attivi + if ( ! pMachine->GetAllCurrAxesNames( m_AxesName) || + ! pMachine->GetAllCurrAxesTokens( m_AxesToken)) + return false ; + // Aggiorno flag di invertito, offset, tipo e posizione corrente degli assi macchina attivi + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + bool bInvert ; + m_pMachine->GetAxisInvert( m_AxesName[i], bInvert) ; + m_AxesInvert.push_back( bInvert) ; + double dOffset ; + m_pMachine->GetAxisOffset( m_AxesName[i], dOffset) ; + m_AxesOffset.push_back( dOffset) ; + bool bLinear ; + m_pMachine->GetAxisType( m_AxesName[i], bLinear) ; + m_AxesLinear.push_back( bLinear) ; + double dVal ; + m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; + m_AxesVal.emplace_back( dVal) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::UpdateAxesPos( void) +{ + // Macchina corrente + Machine* pMachine = m_pMchMgr->GetCurrMachine() ; + if ( pMachine == nullptr) + return false ; + // Aggiorno la posizione corrente degli assi macchina attivi + m_AxesVal.clear() ; + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + double dVal ; + m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; + m_AxesVal.emplace_back( dVal) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ResetAxes( void) +{ + // pulisco dati assi + m_AxesName.clear() ; + m_AxesToken.clear() ; + m_AxesInvert.clear() ; + m_AxesLinear.clear() ; + m_AxesVal.clear() ; + m_nAxesMask = 0 ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ResetAuxAxes( void) +{ + // pulisco dati assi ausiliari + m_AuxAxesName.clear() ; + m_AuxAxesToken.clear() ; + m_AuxAxesInvert.clear() ; + m_AuxAxesOffset.clear() ; + m_AuxAxesLinear.clear() ; + m_AuxAxesVal.clear() ; + m_AuxAxesEnd.clear() ; + m_AuxAxesLink.clear() ; + // abilito assi principali + m_bEnabAxes = true ; + m_bShowAxes = true ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) +{ + // verifico parametri + if ( ! bStart) + bFirst = false ; + // recupero la nuova operazione + if ( bStart) { + m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; + m_nOpInd = 0 ; + } + else + m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; + // ciclo sulle successive operazioni + while ( m_nOpId != GDB_ID_NULL) { + // se lavorazione valida + Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pMch != nullptr && ! pMch->IsEmpty()) { + bool bOk = true ; + // aggiorno utensile e assi conseguenti + int nErr ; + if ( ! UpdateTool( bFirst, nErr)) { + string sOut = "Err=" + ToString( nErr) ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) + nStatus = CalcStatusOnError( nErr) ; + bOk = false ; + } + ++ m_nOpInd ; + // imposto la lavorazione come corrente + m_pMchMgr->SetCurrMachining( m_nOpId) ; + // recupero punti di minimo e massimo ingombro + int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; + Point3d ptMin, ptMax ; + m_pGeomDB->GetInfo( nClId, KEY_MMIN, ptMin) ; + m_pGeomDB->GetInfo( nClId, KEY_MMAX, ptMax) ; + DBLVECTOR vAxMin, vAxMax ; + m_pGeomDB->GetInfo( nClId, KEY_MAXMIN, vAxMin) ; + m_pGeomDB->GetInfo( nClId, KEY_MAXMAX, vAxMax) ; + // richiamo gestione evento inizio lavorazione + if ( ! OnMachiningStart( m_nOpId, m_nOpInd, ptMin, ptMax, vAxMin, vAxMax)) { + nStatus = CalcStatusOnError( 0) ; + bOk = false ; + } + if ( ! bOk) + return false ; + break ; + } + // se disposizione con cambio di fase + Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pDisp != nullptr) { + // in alcuni casi la disposizione non è inizializzata + pDisp->Init( m_pMchMgr) ; + // recupero dati tavola + string sTable ; + pDisp->GetTable( sTable) ; + Point3d ptOri1 ; + pDisp->GetTableRef1( ptOri1) ; + // recupero la fase della disposizione + int nPhase = pDisp->GetPhase() ; + // recupero se con movimenti autonomi + bool bEmpty = pDisp->IsEmpty() ; + // recupero flag disposizione con movimenti manuali + bool bSomeByHand = pDisp->GetSomeByHand() ; + // se con movimenti autonomi + if ( ! bEmpty) { + // richiamo gestione evento appena prima di inizio disposizione + if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // cambio fase + m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; + // se previsto, aggiorno utensile e assi conseguenti + if ( pDisp->IsWithTool()) { + int nErr ; + if ( ! UpdateTool( bFirst, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + } + ++ m_nOpInd ; + // richiamo gestione evento inizio disposizione + if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // se ci sono movimenti manuali, aggiorno visualizzazione e breve pausa (200 ms) + if ( bSomeByHand) + Sleep( 200) ; + break ; + } + // altrimenti disposizione passiva + else { + // richiamo gestione evento appena prima di inizio disposizione + if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // cambio fase + m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; + ++ m_nOpInd ; + // richiamo gestione evento inizio e fine disposizione + if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) || + ! OnDispositionEnd()) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) + if ( nPhase != 1) { + ExeDraw() ; + Sleep( 200) ; + } + } + } + // passo alla operazione successiva + m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ManageOperationEnd( int& nStatus) +{ + bool bOk = false ; + // non c'è operazione in corso (solo prima disposizione senza lavorazioni) + if ( m_nOpId == GDB_ID_NULL) + bOk = true ; + // se altrimenti è una lavorazione + else if ( GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { + // richiamo gestione evento fine lavorazione + bOk = OnMachiningEnd() ; + } + // se altrimenti è una disposizione + else if ( GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { + // richiamo gestione evento fine disposizione + bOk = OnDispositionEnd() ; + } + // gestione stato + if ( ! bOk) + nStatus = CalcStatusOnError( 0) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::FindAndManagePathStart( int& nStatus) +{ + // se devo cercare il primo nella nuova operazione + if ( m_nCLPathId == GDB_ID_NULL) { + // aggiorno gli altri dati + int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; + m_nCLPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ; + m_nCLPathInd = 0 ; + m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + } + // altrimenti cerco il successivo nella stessa operazione + else { + // recupero un nuovo CLpath + while ( m_nEntId == GDB_ID_NULL) { + m_nCLPathId = m_pGeomDB->GetNextGroup( m_nCLPathId) ; + // se non ce ne sono altri, devo passare a una nuova lavorazione + if ( m_nCLPathId == GDB_ID_NULL) + break ; + m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; + m_nEntInd = 0 ; + m_dCoeff = 0 ; + } + } + // se trovato nuovo CLpath con entità, gestisco inizio percorso di lavoro + if ( m_nEntId != GDB_ID_NULL) { + ++ m_nCLPathInd ; + // recupero punti di inizio e fine percorso + Point3d ptStart ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_START, ptStart) ; + Point3d ptEnd ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_END, ptEnd) ; + // recupero versore estrusione associato al percorso (normale al piano di interpolazione) + Vector3d vtExtr ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_EXTR, vtExtr) ; + // recupero punti di minimo e massimo ingombro + Point3d ptMin, ptMax ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMIN, ptMin) ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMAX, ptMax) ; + // Recupero valori degli assi di minimo e massimo ingombro + DBLVECTOR vAxMin, vAxMax ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMIN, vAxMin) ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMAX, vAxMax) ; + // recupero massima elevazione + double dElev = 0 ; + m_pGeomDB->GetInfo( m_nCLPathId, KEY_ELEV, dElev) ; + // recupero il numero di eventi ausiliari di inizio + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + // reset numero eventi ausiliari di fine + m_nAuxEInd = 0 ; + m_nAuxETot = 0 ; + // richiamo gestione evento inizio percorso di lavoro + if ( ! OnPathStart( m_nCLPathId, m_nCLPathInd, m_nAuxSTot, ptStart, ptEnd, vtExtr, ptMin, ptMax, vAxMin, vAxMax, dElev)) { + nStatus = CalcStatusOnError( 0) ; + return false ; + } + } + // se altrimenti trovato nuovo CL path vuoto + else if ( m_nCLPathId != GDB_ID_NULL) { + // recupero il numero di eventi ausiliari di inizio + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) + m_nAuxSTot = 0 ; + m_nAuxSInd = 0 ; + // recupero il numero di eventi ausiliari di fine + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ManagePathEnd( int& nStatus) +{ + // recupero il numero di eventi ausiliari di fine + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) + m_nAuxETot = 0 ; + m_nAuxEInd = 0 ; + // richiamo gestione evento fine percorso di lavoro + bool bOk = OnPathEnd( m_nAuxETot) ; + // gestione stato + if ( ! bOk) + nStatus = CalcStatusOnError( 0) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ManagePathStartAux( int& nStatus) +{ + // aggiorno indice corrente + ++ m_nAuxSInd ; + // recupero i dati per l'evento corrente + string sAS ; + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS + ToString( m_nAuxSInd), sAS)) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // richiamo gestione evento ausiliario prima di inizio percorso di lavoro + int nErr ; + if ( ! OnPathStartAux( m_nAuxSInd, sAS, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + nStatus = MCH_SIM_END_STEP ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ManagePathEndAux( int& nStatus) +{ + // aggiorno indice corrente + ++ m_nAuxEInd ; + // recupero i dati per l'evento corrente + string sAE ; + if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE + ToString( m_nAuxEInd), sAE)) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // richiamo gestione evento ausiliario dopo fine percorso di lavoro + int nErr ; + if ( ! OnPathEndAux( m_nAuxEInd, sAE, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + nStatus = MCH_SIM_END_STEP ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ManageMove( int& nStatus) +{ + // Imposto lunghezza di movimento effettuata + double dCurrMove = 0 ; + while ( m_nEntId != GDB_ID_NULL) { + // eseguo movimento singolo + double dMove ; + if ( ! ManageSingleMove( nStatus, dMove)) + return false ; + dCurrMove += dMove ; + // se modalità play e fine entità e non raggiunta la lunghezza di movimento voluto + if ( m_nUiStatus == MCH_UISIM_PLAY && nStatus == MCH_SIM_END_STEP && dCurrMove < 0.75 * m_dStep) { + // recupero una nuova entità + m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; + m_dCoeff = 0 ; + } + else + break ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ManageSingleMove( int& nStatus, double& dMove) +{ + // Recupero posizione finale + const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; + if ( pCamData == nullptr) { + nStatus = MCH_SIM_ERR ; + return false ; + } + switch ( pCamData->GetAxesStatus()) { + case CamData::AS_OK : + break ; + case CamData::AS_OUTSTROKE : { + DBLVECTOR OutAxes = pCamData->GetAxesVal() ; + for ( size_t i = OutAxes.size() ; i < 5 ; ++ i) + OutAxes.emplace_back( 0) ; + DBLVECTOR vAng( OutAxes.begin() + 3, OutAxes.end()) ; + int nStat ; + m_pMachine->VerifyOutstroke( OutAxes[0], OutAxes[1], OutAxes[2], vAng, true, nStat) ; + nStatus = MCH_SIM_OUTSTROKE ; + return false ; } + case CamData::AS_DIR_ERR : + nStatus = MCH_SIM_DIR_ERR ; + return false ; + default : + nStatus = MCH_SIM_ERR ; + return false ; + } + DBLVECTOR AxesEnd = pCamData->GetAxesVal() ; + // Tipo di movimento + int nMoveType = pCamData->GetMoveType() ; + // Se inizio di nuova entità, mascheratura movimento + if ( m_nEntId != GDB_ID_NULL && m_dCoeff < EPS_ZERO) + m_nAxesMask = pCamData->GetAxesMask() ; + // Se movimento in rapido muovo solo gli assi abilitati dal mask + if ( nMoveType == 0) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + if ( ( m_nAxesMask & 1 << i) == 0) + AxesEnd[i] = m_AxesVal[i] ; + } + } + + // Se inizio di nuova entità + if ( m_nEntId != GDB_ID_NULL && m_dCoeff < EPS_ZERO) { + ++ m_nEntInd ; + const CamData* pNextCamData = GetCamData( m_pGeomDB->GetUserObj( m_pGeomDB->GetNext( m_nEntId))) ; + int nErr ; + if ( ! OnMoveStart( pCamData, pNextCamData, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + // Se movimento in rapido aggiorno quote degli assi disabilitati dal mask + if ( nMoveType == 0) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + if ( ( m_nAxesMask & 1 << i) == 0) + AxesEnd[i] = m_AxesVal[i] ; + } + } + } + + // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) + bool bOkI = true ; + PNTVECTOR vPtNoseI( m_VmTool.size()) ; + VCT3DVECTOR vVtDirI( m_VmTool.size()) ; + VCT3DVECTOR vVtAuxI( m_VmTool.size()) ; + for ( int i = 0 ; i < int( m_VmTool.size()) ; ++ i) + bOkI = GetHeadCurrPosDirAux( m_VmTool[i].sHead, m_VmTool[i].nExit, vPtNoseI[i], vVtDirI[i], vVtAuxI[i]) && bOkI ; + vector vFrVzmI( m_VmId.size()) ; + for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i) + bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ; + + // Dati per eventuale verifica di collisione + int nCdInd, nObjInd ; + bool bCollCheck = true ; + + // Eseguo movimento assi principali ed eventuali ausiliari + if ( m_bEnabAxes) { + // Calcolo distanza di movimento + double dSqDist = 0 ; + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { + // coefficiente moltiplicativo per differenziare assi lineari e rotanti + double dSqCoeff = ( m_AxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; + dSqDist += dSqCoeff * ( AxesEnd[i] - m_AxesVal[i]) * ( AxesEnd[i] - m_AxesVal[i]) ; + } + // Calcolo distanza di movimento eventuali assi ausiliari + double dSqDistAux = 0 ; + for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { + if ( m_AuxAxesLink[i] != 0) + continue ; + // coefficiente moltiplicativo per differenziare assi lineari e rotanti + double dSqCoeff = ( m_AuxAxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; + dSqDistAux += dSqCoeff * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) ; + } + // Considero il massimo delle due distanze + double dPrevCoeff = m_dCoeff ; + double dDist = sqrt( max( dSqDist, dSqDistAux)) ; + if ( dDist > EPS_SMALL) { + double dStep = min( ( nMoveType == 0 ? 2 : 1) * m_dStep, MAX_STEP) ; + int nStep = max( int( dDist / dStep), 1) ; + m_dCoeff += 1. / nStep ; + if ( m_dCoeff > 1) + m_dCoeff = 1 ; + } + else + m_dCoeff = 1 ; + dMove = ( m_dCoeff - dPrevCoeff) * dDist ; + + // Log per debug + if ( ExeGetDebugLevel() >= 10) { + string sOut = "MoveType=" + ToString( nMoveType) + " Coeff=" + ToString( m_dCoeff) ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + } + + // Eseguo movimento rapido o lineare (non arco) + if ( nMoveType != 2 && nMoveType != 3) { + // se attivo CollisionCheck approssimo movimento con più step + int nStep = 1 ; + if ( NeedCollisionCheck()) + nStep = max( int( dMove / COLL_STEP), 1) ; + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; + DBLVECTOR vDeltaVal( m_AxesName.size()) ; + // assegno posizioni finali + for ( int j = 0 ; j < int( m_AxesName.size()) ; ++ j) { + double dPrevVal ; + m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ; + double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; + m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; + vDeltaVal[j] = dVal - dPrevVal ; + } + // muovo eventuali assi ausiliari + for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { + double dVal = 0 ; + if ( m_AuxAxesLink[j] == 0) { + dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; + } + else { + m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ; + if ( m_AuxAxesLink[j] > 0) + dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ; + else + dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ; + } + m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; + } + // se abilitato e non è rapido o non c'è verifica collisioni, eseguo eventuale Vmill + if ( m_bEnableVm && ( nMoveType != 0 || ! NeedCollisionCheck())) { + for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + } + // eseguo eventuale collision check + bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + } + } + // Eseguo movimento su arco + else { + // dati dell'arco + Point3d ptCen = pCamData->GetAxesCen() ; + double dAngCen = pCamData->GetAxesAngCen() ; + double dRad = pCamData->GetAxesRad() ; + Vector3d vtN = pCamData->GetAxesNormDir() ; + double dDeltaN = ( Point3d( AxesEnd[0], AxesEnd[1], AxesEnd[2]) - ptCen) * vtN ; + double dDiffAng = ( m_dCoeff - dPrevCoeff) * dAngCen ; + Vector3d vtRot = Point3d( m_AxesVal[0], m_AxesVal[1], m_AxesVal[2]) - ptCen ; + vtRot.Rotate( vtN, dPrevCoeff * dAngCen) ; + // se attivi Vmill o CollisionCheck approssimo movimento con più step + int nStep = 1 ; + if ( ! m_VmId.empty() || NeedCollisionCheck()) { + const double MIN_LEN_STEP = 2. ; + const double MAX_LEN_STEP = 10. ; + double dLenStep = Clamp( 0.1 * m_dTDiam, MIN_LEN_STEP, MAX_LEN_STEP) ; + nStep = max( int( abs( dDiffAng * DEGTORAD * dRad) / dLenStep), 1) ; + const double ANG_STEP = 5. ; + if ( abs( dDiffAng) / nStep > ANG_STEP) + nStep = int( abs( dDiffAng) / ANG_STEP) ; + } + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; + DBLVECTOR vDeltaVal( m_AxesName.size()) ; + // assi lineari + vtRot.Rotate( vtN, dDiffAng / nStep) ; + double dPrevVal, dVal ; + m_pMachine->GetAxisPos( m_AxesName[0], dPrevVal) ; + dVal = ptCen.x + vtRot.x + dCurrCoeff * dDeltaN * vtN.x ; + m_pMachine->SetAxisPos( m_AxesName[0], dVal) ; + vDeltaVal[0] = dVal - dPrevVal ; + m_pMachine->GetAxisPos( m_AxesName[1], dPrevVal) ; + dVal = ptCen.y + vtRot.y + dCurrCoeff * dDeltaN * vtN.y ; + m_pMachine->SetAxisPos( m_AxesName[1], dVal) ; + vDeltaVal[1] = dVal - dPrevVal ; + m_pMachine->GetAxisPos( m_AxesName[2], dPrevVal) ; + dVal = ptCen.z + vtRot.z + dCurrCoeff * dDeltaN * vtN.z ; + m_pMachine->SetAxisPos( m_AxesName[2], dVal) ; + vDeltaVal[2] = dVal - dPrevVal ; + // assi rotanti + for ( int j = 3 ; j < int( m_AxesName.size()) ; ++ j) { + double dPrevVal ; m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ; + double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; + m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; + vDeltaVal[j] = dVal - dPrevVal ; + } + // eventuali assi ausiliari + for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { + double dVal = 0 ; + if ( m_AuxAxesLink[j] == 0) { + dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; + } + else { + m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ; + if ( m_AuxAxesLink[j] > 0) + dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ; + else + dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ; + } + m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; + } + // se abilitato, eseguo eventuale Vmill + for ( int j = 0 ; m_bEnableVm && j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + // eseguo eventuale collision check + bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + } + } + } + + // altrimenti eseguo movimento soli eventuali assi ausiliari + else { + // Calcolo distanza di movimento + double dSqDist = 0 ; + for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { + // coefficiente moltiplicativo per differenziare assi lineari e rotanti + double dSqCoeff = ( m_AuxAxesLinear[i] ? 1 : SQ_COEFF_ROT_MOVE) ; + dSqDist += dSqCoeff * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) * ( m_AuxAxesEnd[i] - m_AuxAxesVal[i]) ; + } + double dPrevCoeff = m_dCoeff ; + double dDist = sqrt( dSqDist) ; + if ( dDist > EPS_SMALL) { + double dStep = min( ( nMoveType == 0 ? 2 : 1) * m_dStep, MAX_STEP) ; + int nStep = max( int( dDist / dStep), 1) ; + m_dCoeff += 1. / nStep ; + if ( m_dCoeff > 1) + m_dCoeff = 1 ; + } + else + m_dCoeff = 1 ; + dMove = ( m_dCoeff - dPrevCoeff) * dDist ; + // se attivo CollisionCheck approssimo movimento con più step + int nStep = 1 ; + if ( NeedCollisionCheck()) + nStep = max( int( dMove / COLL_STEP), 1) ; + for ( int i = 1 ; i <= nStep ; ++ i) { + double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; + // muovo eventuali assi ausiliari + for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { + if ( m_AuxAxesLink[j] == 0) { + double dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; + m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; + } + } + // se abilitato e non è rapido o non c'è verifica collisioni, eseguo eventuale Vmill + if ( m_bEnableVm && ( nMoveType != 0 || ! NeedCollisionCheck())) { + for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + } + // eseguo eventuale collision check + bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + } + } + + // Se riscontrata collisione + if ( ! bCollCheck) { + // Richiamo funzione di convalida collisione + int nErr ; + if ( ! OnCollision( nCdInd, nObjInd, nErr)) { + nStatus = CalcStatusOnError( nErr) ; + // Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo + if ( m_dCoeff > COEFF_LIM) { + if ( m_bEnabAxes) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) + m_AxesVal[i] = AxesEnd[i] ; + } + // richiamo gestione evento fine entità, senza gestirne eventuali errori + int nErr ; + OnMoveEnd( nErr) ; + } + return false ; + } + } + + // Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo + if ( m_dCoeff > COEFF_LIM) { + if ( m_bEnabAxes) { + for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) + m_AxesVal[i] = AxesEnd[i] ; + } + nStatus = MCH_SIM_END_STEP ; + // richiamo gestione evento fine entità + int nErr ; + if ( ! OnMoveEnd( nErr)) { + nStatus = CalcStatusOnError( nErr) ; + return false ; + } + } + // Altrimenti sto muovendomi all'interno dell'entità + else + nStatus = MCH_SIM_OK ; + + return true ; +} + +//---------------------------------------------------------------------------- +int +SimulatorSP::CalcStatusOnError( int nErr) +{ + if ( Stopped()) + return MCH_SIM_STOP ; + else if ( nErr == ERR_OUTSTROKE) + return MCH_SIM_OUTSTROKE ; + else if ( nErr == ERR_COLLISION) + return MCH_SIM_COLLISION ; + else + return MCH_SIM_ERR ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA) +{ + int nHeadId = m_pMachine->GetHeadId( sHead) ; + int nExitId = m_pMachine->GetExitId( sHead, nExit) ; + if ( nHeadId == GDB_ID_NULL || nExitId == GDB_ID_NULL) + return false ; + Frame3d frExit ; m_pGeomDB->GetGroupGlobFrame( nExitId, frExit) ; + ptH = frExit.Orig() ; + vtH = frExit.VersZ() ; + vtA = V_NULL ; + int nDirAuxId = m_pGeomDB->GetFirstNameInGroup( nHeadId, MCH_AUX_VECT) ; + if ( nDirAuxId != GDB_ID_NULL) { + const IGeoVector3d* pGV = GetGeoVector3d( m_pGeomDB->GetGeoObj( nDirAuxId)) ; + if ( pGV != nullptr) { + Frame3d frHead ; m_pGeomDB->GetGroupGlobFrame( nHeadId, frHead) ; + vtA = pGV->GetVector() ; + vtA.ToGlob( frHead) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, + const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) +{ + // Recupero Zmap + IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( nVmId)) ; + if ( pVZM == nullptr) { + string sOut = " --> GetVolZmap (" + ToString( nVmId) +") Error <--" ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + return false ; + } + // Porto gli estremi nel riferimento opportuno dello Zmap + Point3d ptHiL = ptHi ; ptHiL.ToLoc( frVzmI) ; + Vector3d vtHiL = vtHi ; vtHiL.ToLoc( frVzmI) ; + Vector3d vtAiL = vtAi ; vtAiL.ToLoc( frVzmI) ; + Point3d ptHfL = ptHf ; ptHfL.ToLoc( frVzmF) ; + Vector3d vtHfL = vtHf ; vtHfL.ToLoc( frVzmF) ; + Vector3d vtAfL = vtAf ; vtAfL.ToLoc( frVzmF) ; + // Eventuali offset + ptHiL += dVmTdOffs * vtHiL + dVmAdOffs * vtAiL ; + ptHfL += dVmTdOffs * vtHfL + dVmAdOffs * vtAfL ; + // Log per debug + if ( ExeGetDebugLevel() >= 10) { + string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) + + " Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + + ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + } + // Se utensile che non lavora di testa + if ( ! m_bCutOnTip) { + // se movimento di testa (angolo movimento verso la testa oltre 5.8deg), non eseguo asportazione + Vector3d vtDirM = Media( vtHiL, vtHfL) ; + vtDirM.Normalize() ; + double dAxMove = ( ptHfL - ptHiL) * vtDirM ; + if ( dAxMove < -EPS_SMALL) { + double dMove = ( ptHfL - ptHiL).Len() ; + if ( dAxMove < -0.1 * abs( dMove)) + return true ; + } + } + // Eseguo + bool bOk = pVZM->MillingStep( nCurrTool, ptHiL, vtHiL, vtAiL, ptHfL, vtHfL, vtAfL) ; + if ( ! bOk) { + if ( ExeGetDebugLevel() < 10) { + string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) + + " Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) + + ") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ; + LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) + } + LOG_DBG_INFO( GetEMkLogger(), " --> MillingStep Error <--") + } + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) +{ + // se non ci sono oggetti da controllare o non ci sono grezzi o equivalenti, tutto bene + if ( ! NeedCollisionCheck()) + return true ; + // ciclo sui grezzi o equivalenti + for ( int i = 0 ; i < int( m_CdId.size()) ; ++ i) { + // se modo hidden è da saltare + int nMode ; + if ( m_pGeomDB->GetCalcMode( m_CdId[i], nMode) && nMode == GDB_MD_HIDDEN) + continue ; + // verifico se è il grezzo in lavorazione + bool bIsRaw = ( find( m_VmId.begin(), m_VmId.end(), m_CdId[i]) != m_VmId.end()) ; + // recupero solido o trimesh, se altro lo salto + const IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( m_CdId[i])) ; + const ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeomDB->GetGeoObj( m_CdId[i])) ; + if ( pVZM == nullptr && pSTM == nullptr) + continue ; + // recupero il riferimento + Frame3d frCd ; m_pGeomDB->GetGlobFrame( m_CdId[i], frCd) ; + // ciclo sugli oggetti con cui verificare + for ( int j = 0 ; j < int( m_CollObj.size()) ; ++ j) { + // se modo hidden è da saltare + int nMode ; + if ( m_pGeomDB->GetCalcMode( m_CollObj[j].nFrameId, nMode) && nMode == GDB_MD_HIDDEN) + continue ; + // verifico se è l'utensile attivo + string sHead ; m_pGeomDB->GetName( m_pGeomDB->GetParentId( m_CollObj[j].nFrameId), sHead) ; + string sExit ; m_pGeomDB->GetName( m_CollObj[j].nFrameId, sExit) ; + bool bIsTool = m_CollObj[j].bToolOn || + ( sHead == m_sHead && ( sExit == "_T" + ToString( m_nExit) || sExit == "_TT" + ToString( m_nExit))) ; + // se utensile attivo su grezzo in lavoro e non è rapido, salto + if ( bIsTool && bIsRaw && nMoveType != 0) + continue ; + // esecuzione controlli di collisione + bool bOk = true ; + // oggetti che richiedono frame associato (Box, Cylinder, Sphere, Cone) + if ( m_CollObj[j].nType != MCH_SIM_COB_POLY) { + // se riferimento non trovato, si salta + const IGeoFrame3d* pGeoFrame = GetGeoFrame3d( m_pGeomDB->GetGeoObj( m_CollObj[j].nFrameId)) ; + if ( pGeoFrame == nullptr) + continue ; + Frame3d frObj = pGeoFrame->GetFrame() ; + if ( ! m_CollObj[j].vtMove.IsSmall()) + frObj.Translate( m_CollObj[j].vtMove.x * frObj.VersX() + + m_CollObj[j].vtMove.y * frObj.VersY() + + m_CollObj[j].vtMove.z * frObj.VersZ()) ; + Frame3d frParent ; m_pGeomDB->GetGlobFrame( m_CollObj[j].nFrameId, frParent) ; + frObj.LocToLoc( frParent, frCd) ; + // controlli di collisione + if ( m_CollObj[j].nType == MCH_SIM_COB_BOX) { + Vector3d vtDiag( m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3) ; + if ( pVZM != nullptr) + bOk = ! pVZM->CDeBox( frObj, vtDiag, m_dSafeDist) ; + else + bOk = ! CDeBoxClosedSurfTm( frObj, vtDiag, *pSTM, m_dSafeDist) ; + } + else if ( m_CollObj[j].nType == MCH_SIM_COB_CYL) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeCylinder( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_dSafeDist) ; + else + bOk = ! CDeCylClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, *pSTM, m_dSafeDist) ; + } + else if ( m_CollObj[j].nType == MCH_SIM_COB_SPHE) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeSphere( frObj.Orig(), m_CollObj[j].dPar1, m_dSafeDist) ; + else + bOk = ! CDeSpheClosedSurfTm( frObj.Orig(), m_CollObj[j].dPar1, *pSTM, m_dSafeDist) ; + } + else if ( m_CollObj[j].nType == MCH_SIM_COB_CONE) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeConeFrustum( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3, m_dSafeDist) ; + else + bOk = ! CDeConeFrustumClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_CollObj[j].dPar3, *pSTM, m_dSafeDist) ; + } + } + // altrimenti poliedro + else { + SurfLocal SurfLoc( m_pGeomDB, m_CollObj[j].nFrameId, frCd) ; + const ISurfTriMesh* pStmLoc = GetSurfTriMesh( SurfLoc) ; + if ( pStmLoc != nullptr) { + if ( pVZM != nullptr) + bOk = ! pVZM->CDeSurfTm( *pStmLoc, m_dSafeDist) ; + else + bOk = ! CDeClosedSurfTmClosedSurfTm( *pStmLoc, *pSTM, m_dSafeDist) ; + } + else + bOk = false ; + } + // se trovata collisione + if ( ! bOk) { + nCdInd = i ; + nObjInd = j ; + return false ; + } + } + } + return true ; +} + +//---------------------------------------------------------------------------- +static int +FindCollisionMarkId( const IGeomDB* pGeomDB, int nCollId) +{ + int nCollParId = pGeomDB->GetParentId( nCollId) ; + string sCollParName = "COLLISION" ; + pGeomDB->GetName( nCollParId, sCollParName) ; + if ( sCollParName != "COLLISION") + return nCollParId ; + else { + int nCollGprId = pGeomDB->GetParentId( nCollParId) ; + int nCollSolId = pGeomDB->GetFirstNameInGroup( nCollGprId, "SOLID") ; + if ( nCollSolId != GDB_ID_NULL) + return nCollSolId ; + else + return nCollGprId ; + } +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::SetCollisionMark( int nCdInd, int nObjInd) +{ + if ( m_pGeomDB == nullptr) + return false ; + m_nCollMarkId.clear() ; + int nCdMarkId = FindCollisionMarkId( m_pGeomDB, m_CdId[nCdInd]) ; + m_pGeomDB->SetMark( nCdMarkId, GDB_MK_ON) ; + m_nCollMarkId.push_back( nCdMarkId) ; + int nCoMarkId = FindCollisionMarkId( m_pGeomDB, m_CollObj[nObjInd].nFrameId) ; + m_pGeomDB->SetMark( nCoMarkId, GDB_MK_ON_2) ; + m_nCollMarkId.push_back( nCoMarkId) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::ResetCollisionMark( void) +{ + if ( m_pGeomDB == nullptr) + return false ; + for ( auto nId : m_nCollMarkId) + m_pGeomDB->ResetMark( nId) ; + m_nCollMarkId.clear() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnInit( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_INIT)) + return true ; + // chiamo la funzione di ingresso nella simulazione + return m_pMachine->LuaCallFunction( ON_SIMUL_INIT) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnExit( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_EXIT)) + return true ; + // chiamo la funzione di uscita dalla simulazione + return m_pMachine->LuaCallFunction( ON_SIMUL_EXIT) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnProgramStart( bool bFirst) +{ + // assegno flag inizio simulazione + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIM1ST, bFirst) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_START)) + return true ; + // chiamo la funzione di inizio simulazione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_START) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnProgramEnd( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_END)) + return true ; + // chiamo la funzione di fine simulazione + return m_pMachine->LuaCallFunction( ON_SIMUL_END) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnDispositionStarting( int nOpId, int nOpInd, int nPhase, + const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) +{ + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; + // assegno nuovo indice di fase + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; + // assegno nome e valore riferimento della tavola corrente + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; + // assegno flag disposizione passiva + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; + // assegno flag disposizione con operazioni manuali + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_STARTING)) + return true ; + // chiamo la funzione di inizio disposizione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_STARTING) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnDispositionStart( int nOpId, int nOpInd, int nPhase, + const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) +{ + // assegno identificativo e indice disposizione + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; + // assegno nuovo indice di fase + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; + // assegno nome e valore riferimento della tavola corrente + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; + // assegno flag disposizione passiva + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; + // assegno flag disposizione con operazioni manuali + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_START)) + return true ; + // chiamo la funzione di inizio disposizione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_START) ; + // recupero i dati di ritorno + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnDispositionEnd( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_END)) + return true ; + // chiamo la funzione di fine disposizione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_END) ; + // recupero i dati di ritorno + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnToolSelect( const string& sTool, const string& sHead, int nExit, const string& sTcPos, + bool bFirst, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // reset oggetti per verifica collisione con grezzo + m_CollObj.clear() ; + // assegno il nome dell'utensile, la testa e l'uscita + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TOOL, sTool) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_HEAD, sHead) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXIT, nExit) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TCPOS, sTcPos)) + return false ; + // assegno il token e il nome degli assi + bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; + int nNumAxes = int( m_AxesName.size()) ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) { + if ( i <= nNumAxes) { + if ( ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisToken( i, bIsRobot), m_AxesToken[i-1]) || + ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisName( i, bIsRobot), m_AxesName[i-1])) + return false ; + } + else { + if ( ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisToken( i, bIsRobot)) || + ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisName( i, bIsRobot))) + return false ; + } + } + // assegno il flag di chiamata di utensile iniziale + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FIRST, bFirst)) + return false ; + // reset errore + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) + return false ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_SELECT)) + return true ; + // chiamo la funzione di selezione utensile + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_SELECT) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // recupero dati per verifica collisione + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SAFEDIST, m_dSafeDist) ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // recupero i dati di ritorno per assi ausiliari + ResetAuxAxes() ; + int nNumAuxAxes = 0 ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) + return ( bOk && nErr == 0) ; + m_AuxAxesName.reserve( nNumAuxAxes) ; + m_AuxAxesToken.reserve( nNumAuxAxes) ; + m_AuxAxesInvert.reserve( nNumAuxAxes) ; + m_AuxAxesOffset.reserve( nNumAuxAxes) ; + m_AuxAxesLinear.reserve( nNumAuxAxes) ; + m_AuxAxesVal.reserve( nNumAuxAxes) ; + m_AuxAxesEnd.reserve( nNumAuxAxes) ; + for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) { + string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; + string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ; + if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) && + m_pMachine->GetAxisToken( sName, sToken) && + m_pMachine->GetAxisInvert( sName, bInvert) && + m_pMachine->GetAxisOffset( sName, dOffset) && + m_pMachine->GetAxisType( sName, bLinear) && + m_pMachine->GetAxisPos( sName, dVal)) { + // se non è già negli assi principali, lo aggiungo + if ( find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) { + m_AuxAxesName.emplace_back( sName) ; + m_AuxAxesToken.emplace_back( sToken) ; + m_AuxAxesInvert.push_back( bInvert) ; + m_AuxAxesOffset.push_back( dOffset) ; + m_AuxAxesLinear.push_back( bLinear) ; + m_AuxAxesVal.emplace_back( dVal) ; + m_AuxAxesEnd.emplace_back( dVal) ; + m_AuxAxesLink.emplace_back( 0) ; + } + } + else { + bOk = false ; + nErr = ERR_TOOL_SEL ; + } + } + + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // assegno il prossimo utensile + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTOOL, sNextTool) ; + // assegno la prossima testa + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTHEAD, sNextHead) ; + // assegno la prossima uscita + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTEXIT, nNextExit) ; + // assegno l'eventuale prossima posizione nel TC + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTCPOS, sNextTcPos) ; + // reset errore + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_DESELECT)) + return bOk ; + // chiamo la funzione di deselezione utensile + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_DESELECT) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) +{ + // assegno identificativo e indice lavorazione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHID, nOpId) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHIND, nOpInd)) + return false ; + // assegno punti estremi dell'ingombro della lavorazione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMIN, ptMin) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMAX, ptMax)) + return false ; + // assegno punti estremi dell'ingombro degli assi della lavorazione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMIN, vAxMin) || + ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMAX, vAxMax)) + return false ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_START)) + return true ; + // chiamo la funzione di inizio disposizione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_START) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnMachiningEnd( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_END)) + return true ; + // chiamo la funzione di fine lavorazione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_END) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, + const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) +{ + // assegno identificativo e indice percorso di lavorazione + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHID, nClPathId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHIND, nClPathInd) ; + // assegno numero di dati ausiliari iniziali + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAS) ; + // assegno punti iniziale e finale e versore estrusione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_START, ptStart) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_END, ptEnd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXTR, vtExtr) ; + // assegno punti estremi dell'ingombro del percorso di lavorazione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMIN, ptMin) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMAX, ptMax) ; + // assegno punti estremi dell'ingombro degli assi della lavorazione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMIN, vAxMin) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMAX, vAxMax) ; + // assegno la massima elevazione + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ELEV, dElev) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START)) + return bOk ; + // chiamo la funzione di inizio percorso di lavorazione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnPathEnd( int nAE) +{ + // assegno numero di dati ausiliari finali + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAE) ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END)) + return bOk ; + // chiamo la funzione di fine percorso di lavorazione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnPathStartAux( int nInd, const string& sAS, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START_AUX)) + return true ; + // assegno indice, valore dato ausiliario e resetto errore + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAS) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // chiamo la funzione di evento ausiliario all'inizio del percorso + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START_AUX) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnPathEndAux( int nInd, const string& sAE, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END_AUX)) + return true ; + // assegno indice, valore dato ausiliario e resetto errore + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAE) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // chiamo la funzione di evento ausiliario alla fine del percorso + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END_AUX) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // recupero e assegno i dati + // dati generali e reset errore + bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEID, m_nEntId) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEIND, m_nEntInd) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVE, pCamData->GetMoveType()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MASK, pCamData->GetAxesMask()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG, pCamData->GetFlag()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG2, pCamData->GetFlag2()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INDEX, pCamData->GetIndex()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // valore degli assi all'inizio e alla fine del movimento + bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; + int nNumAxes = int( m_AxesName.size()) ; + const DBLVECTOR& AxesEnd = pCamData->GetAxesVal() ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) { + if ( i <= nNumAxes) { + bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot), m_AxesVal[i-1]) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot), AxesEnd[i-1]) ; + } + else { + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot)) ; + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot)) ; + } + } + // versori utensile, correzione e ausiliario alla fine del movimento + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TDIR, pCamData->GetToolDir()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_CDIR, pCamData->GetCorrDir()) ; + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ADIR, pCamData->GetBackAuxDir()) ; + // anticipazione di alcuni dati dell'eventuale movimento successivo dello stesso percorso + if ( pNextCamData != nullptr && pNextCamData->GetAxesStatus() == CamData::AS_OK) { + bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVESUCC, pNextCamData->GetMoveType()) ; + const DBLVECTOR& AxesNext = pNextCamData->GetAxesVal() ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) { + if ( i <= nNumAxes) + bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot), AxesNext[i-1]) ; + else + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ; + } + } + else { + bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_MOVESUCC) ; + for ( int i = 1 ; i <= MAX_AXES ; ++ i) + bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ; + } + // reset abilitazione assi attivi + bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_ENABAXES) ; + // reset numero assi ausiliari + bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_AUXAXES) ; + + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_START)) { + ResetAuxAxes() ; + return bOk ; + } + // chiamo la funzione + bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_START) ; + // con errore, esco + if ( ! bOk) { + ResetAuxAxes() ; + return false ; + } + + // verifico codice di errore + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + if ( nErr != 0) + return false ; + + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + + // reset assi ausiliari + ResetAuxAxes() ; + + // recupero i dati di ritorno + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_MASK, m_nAxesMask) ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ENABAXES, m_bEnabAxes)) + m_bEnabAxes = true ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SHOWAXES, m_bShowAxes)) + m_bShowAxes = m_bEnabAxes ; + int nNumAuxAxes = 0 ; + if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) + return true ; + m_AuxAxesName.reserve( nNumAuxAxes) ; + m_AuxAxesToken.reserve( nNumAuxAxes) ; + m_AuxAxesInvert.reserve( nNumAuxAxes) ; + m_AuxAxesOffset.reserve( nNumAuxAxes) ; + m_AuxAxesLinear.reserve( nNumAuxAxes) ; + m_AuxAxesVal.reserve( nNumAuxAxes) ; + m_AuxAxesEnd.reserve( nNumAuxAxes) ; + for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) { + string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; double dEnd ; string sLink ; + string sAuxAxVal = GLOB_VAR + GVAR_AN ; ReplaceString( sAuxAxVal, "N", ToString( i)) ; + string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ; + string sAuxAxMaster = GLOB_VAR + GVAR_ANM ; ReplaceString( sAuxAxMaster, "N", ToString( i)) ; + if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) && + m_pMachine->GetAxisToken( sName, sToken) && + m_pMachine->GetAxisInvert( sName, bInvert) && + m_pMachine->GetAxisOffset( sName, dOffset) && + m_pMachine->GetAxisType( sName, bLinear) && + m_pMachine->GetAxisPos( sName, dVal)) { + // se assi principali abilitati e da agganciare ad asse principale + if ( m_bEnabAxes && m_pMachine->LuaGetGlobVar( sAuxAxMaster, sLink)) { + bool bNeg = ( sLink.find( '-') != string::npos) ; + string sMainAxis = sLink ; ReplaceString( sMainAxis, "-", "") ; + int nInd = 0 ; + for ( int i = 0 ; nInd == 0 && i < int( m_AxesName.size()) ; ++ i) { + if ( m_AxesName[i] == sMainAxis) + nInd = i + 1 ; + } + // se trovato asse principale di riferimento + if ( nInd > 0) { + m_AuxAxesName.emplace_back( sName) ; + m_AuxAxesToken.emplace_back( sToken) ; + m_AuxAxesInvert.push_back( bInvert) ; + m_AuxAxesOffset.push_back( dOffset) ; + m_AuxAxesLinear.push_back( bLinear) ; + m_AuxAxesVal.emplace_back( 0) ; + m_AuxAxesEnd.emplace_back( 0) ; + m_AuxAxesLink.emplace_back( ( bNeg ? -nInd : nInd)) ; + } + } + // se altrimenti specificato valore finale del movimento + else if ( m_pMachine->LuaGetGlobVar( sAuxAxVal, dEnd)) { + // se assi principali disabilitati o non è tra questi, lo aggiungo + if ( ! m_bEnabAxes || find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) { + m_AuxAxesName.emplace_back( sName) ; + m_AuxAxesToken.emplace_back( sToken) ; + m_AuxAxesInvert.push_back( bInvert) ; + m_AuxAxesOffset.push_back( dOffset) ; + m_AuxAxesLinear.push_back( bLinear) ; + m_AuxAxesVal.emplace_back( dVal) ; + m_AuxAxesEnd.emplace_back( dEnd) ; + m_AuxAxesLink.emplace_back( 0) ; + if ( ! m_pMachine->VerifyOutstroke( sName, dEnd)) { + nErr = 1 ; + bOk = false ; + } + } + } + // altrimenti errore + else + bOk = false ; + } + else + bOk = false ; + } + + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnMoveEnd( int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_END)) + return true ; + // reset errore + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) + return false ; + // chiamo la funzione + bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_END) ; + // forzo aggiornamento posizione assi (possono essere stati mossi nello script) + UpdateAxesPos() ; + // verifico codice di errore + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + return ( bOk && nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnCollision( int nCdInd, int nObjInd, int& nErr) +{ + // reset stato di errore da script + nErr = 0 ; + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_COLLISION)) + return true ; + // reset stato di errore + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) + return false ; + // assegno identificativi grezzo e oggetto in collisione + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMVMID, m_CdId[nCdInd])) + return false ; + if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMCOBIND, m_CollObj[nObjInd].nInd)) + return false ; + // chiamo la funzione + if ( ! m_pMachine->LuaCallFunction( ON_SIMUL_COLLISION)) + return false ; + // verifico codice di errore + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + // l'errore standard di collisione è stato portato da 1 a 11 per non collidere con altri tipi di errori + if ( nErr == 1) { + nErr = ERR_COLLISION ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + } + // evidenzio le geometrie in collisione + if ( nErr == ERR_COLLISION) { + SetCollisionMark( nCdInd, nObjInd) ; + ExeDraw() ; + } + + return ( nErr == 0) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::OnResetMachine( void) +{ + // verifico esistenza funzione + if ( ! m_pMachine->LuaExistsFunction( ON_RESET_MACHINE)) + return true ; + // eseguo reset macchina + return m_pMachine->LuaCallFunction( ON_RESET_MACHINE) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) +{ + // verifiche sui parametri + if ( nInd <= 0 || nFrameId <= GDB_ID_NULL) + return false ; + switch ( nType) { + case MCH_SIM_COB_BOX : + if ( abs( dPar1) < EPS_SMALL || abs( dPar2) < EPS_SMALL || abs( dPar3) < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_CYL : + if ( dPar1 < EPS_SMALL || abs( dPar2) < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_SPHE : + if ( dPar1 < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_CONE : + if ( ( dPar1 < EPS_SMALL && dPar2 < EPS_SMALL) || dPar3 < EPS_SMALL) + return false ; + break ; + case MCH_SIM_COB_POLY : + if ( ! ExeSurfIsClosed( nFrameId)) + return false ; + break ; + default : + return false ; + } + // aggiungo al vettore + m_CollObj.emplace_back( nInd, bToolOn, nFrameId, nType, vtMove, dPar1, dPar2, dPar3) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::SetToolForVmill( const string& sTool, const string& sHead, int nExit, int nFlag, double dPar1, double dPar2, + const INTVECTOR& vVmill, bool bFirst) +{ + // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) + CmdLogOff cmdLogOff ; + // se vVmill vuoto, esco + if ( vVmill.empty()) + return true ; + // se utensile, testa o uscita non definiti, reset ed esco + if ( IsEmptyOrSpaces( sTool) || IsEmptyOrSpaces( sHead) || nExit < 1) { + ExeVolZmapResetTools( vVmill) ; + if ( bFirst) + m_bEnableVm = false ; + return false ; + } + // imposto utensile come corrente + string sOldTool ; m_pMchMgr->TdbGetCurrToolParam( TPA_NAME, sOldTool) ; + if ( sTool != sOldTool && ! m_pMchMgr->TdbSetCurrTool( sTool)) { + ExeVolZmapResetTools( vVmill) ; + if ( bFirst) + m_bEnableVm = false ; + return false ; + } + // recupero dati utensile + int nInd = 1 ; + int nType ; m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nType) ; + double dLen ; m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, dLen) ; + double dDiam ; m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, dDiam) ; + double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; + double dCornR ; m_pMchMgr->TdbGetCurrToolParam( TPA_CORNRAD, dCornR) ; + double dSideAng ; m_pMchMgr->TdbGetCurrToolParam( TPA_SIDEANG, dSideAng) ; + double dMaxMat ; m_pMchMgr->TdbGetCurrToolParam( TPA_MAXMAT, dMaxMat) ; + string sNotes ; m_pMchMgr->TdbGetCurrToolParam( TPA_USERNOTES, sNotes) ; + bool bAdditive = ( nFlag == 1) ; + // ricerca dell'outline e del diametro gambo + int nExitId = m_pMachine->GetExitId( sHead, nExit) ; + int nToolId = m_pGeomDB->GetFirstNameInGroup( nExitId, sTool) ; + int nOutlineId = m_pGeomDB->GetFirstNameInGroup( nToolId, "Outline") ; + double dMaxStemDiam = dDiam ; m_pGeomDB->GetInfo( nToolId, "D_STEM", dMaxStemDiam) ; + // imposto profilo utensile per Vmill + if ( bAdditive) + ExeVolZmapSetAdditiveTool( vVmill, sTool, dPar1, dPar2, 0, nInd, bFirst) ; + else if ( nOutlineId != GDB_ID_NULL) + ExeVolZmapSetGenTool( vVmill, sTool, nOutlineId, nInd, bFirst) ; + else if ( nType == TT_MORTISE_STD) + ExeVolZmapSetMortiserTool( vVmill, sTool, dLen, dDiam, dThick, dCornR, nInd, bFirst) ; + else if ( nType == TT_CHISEL_STD) + ExeVolZmapSetChiselTool( vVmill, sTool, dLen, dDiam, dDiam, nInd, bFirst) ; + else if ( nType == TT_SAW_STD || nType == TT_SAW_FLAT) + ExeVolZmapSetSawTool( vVmill, sTool, dLen, dDiam, dThick, 0, dCornR, nInd, bFirst) ; + else if ( nType == TT_WATERJET) + ExeVolZmapSetStdTool( vVmill, sTool, dLen + 50, dDiam, dCornR, dMaxMat, nInd, bFirst) ; + else if ( abs( dSideAng) < EPS_ANG_SMALL || abs( dThick) < EPS_SMALL) { + ExeVolZmapSetStdTool( vVmill, sTool, dLen, dDiam, dCornR, dMaxMat, nInd, bFirst) ; + } + else { + bool bExtra = ( dThick > 0) ; + double dTipLen = abs( dThick) ; + double dTotLen = ( bExtra ? dLen + dTipLen : dLen) ; + double dDelta ; + if ( dSideAng > 0) { + if ( dCornR < EPS_SMALL) + dDelta = 2 * dTipLen * tan( dSideAng * DEGTORAD) ; + else + dDelta = 2 * ( dCornR * cos( dSideAng * DEGTORAD) + ( dTipLen - dCornR + dCornR * sin( dSideAng * DEGTORAD)) * tan( dSideAng * DEGTORAD)) ; + } + else + dDelta = 2 * tan( dSideAng * DEGTORAD) * dTipLen ; + double dStemDiam = ( bExtra ? dDiam : dDiam + dDelta) ; + double dTipDiam = ( bExtra ? dDiam - dDelta : dDiam) ; + ExeVolZmapSetAdvTool( vVmill, sTool, dTotLen, dStemDiam, dTipLen, dTipDiam, dCornR, dMaxMat, nInd, bFirst) ; + } + // eventuali offset per Vmill (per adattare lo ZeroT macchina con quello di Zmap) + double dVmTdOffs = 0 ; + double dVmAdOffs = 0 ; + if ( nType == TT_MORTISE_STD) { + dVmTdOffs = 0 ; + dVmAdOffs = 0.5 * dThick ; + } + else if ( nType == TT_SAW_STD || nType == TT_SAW_FLAT) { + dVmTdOffs = ( ( dLen <= dThick) ? -dLen + dThick : 0) ; + dVmAdOffs = 0 ; + } + // inserisco in lista utensili per virtual milling + if ( bFirst) { + m_VmTool.resize( 1) ; + m_VmTool[0] = VmTool( sTool, sHead, nExit, dVmTdOffs, dVmAdOffs) ; + } + else + m_VmTool.emplace_back( sTool, sHead, nExit, dVmTdOffs, dVmAdOffs) ; + // ripristino eventuale diverso utensile corrente + if ( sTool != sOldTool) + m_pMchMgr->TdbSetCurrTool( sOldTool) ; + + if ( bFirst) + m_bEnableVm = true ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorSP::EnableToolsForVmill( bool bEnable) +{ + m_bEnableVm = bEnable ; + return true ; +} + +//---------------------------------------------------------------------------- +int +SimulatorSP::MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) +{ + // Salvo lo step di simulazione corrente + double dOrigStep = m_dStep ; + // Verifico ci siano assi da muovere + if ( vAxNaEpSt.empty()) + return SIM_AXMV_RES_ERR ; + // Tipo di cinematica + bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ; + // Numero assi da muovere + int nAxCount = int( vAxNaEpSt.size()) ; + // Posizioni iniziali + DBLVECTOR vPrev( nAxCount) ; + for ( int i = 0 ; i < nAxCount ; ++ i) { + if ( ! m_pMchMgr->GetAxisPos( vAxNaEpSt[i].sName, vPrev[i])) + return SIM_AXMV_RES_ERR ; + } + // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) + bool bExecVmill = (( nMoveType != 0 || ! NeedCollisionCheck()) && ! m_VmTool.empty() && ! m_VmId.empty()) ; + PNTVECTOR vPtNoseI ; + VCT3DVECTOR vVtDirI ; + VCT3DVECTOR vVtAuxI ; + vector vFrVzmI ; + if ( bExecVmill) { + vPtNoseI.resize( m_VmTool.size()) ; + vVtDirI.resize( m_VmTool.size()) ; + vVtAuxI.resize( m_VmTool.size()) ; + vFrVzmI.resize( m_VmId.size()) ; + bool bOkI = true ; + for ( int i = 0 ; i < int( m_VmTool.size()) ; ++ i) + bOkI = GetHeadCurrPosDirAux( m_VmTool[i].sHead, m_VmTool[i].nExit, vPtNoseI[i], vVtDirI[i], vVtAuxI[i]) && bOkI ; + for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i) + bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ; + } + // Determino gli step di movimento + static const int STEP_FEED = -1 ; + static const int STEP_RAPID = -2 ; + static const int STEP_RAPROT = -3 ; + static const int STEP_COLLROT = -4 ; + bool bViewAllFrames = true ; + int nStep = 1 ; + for ( int i = 0 ; i < nAxCount ; ++ i) { + double dMove = abs( vAxNaEpSt[i].dEndPos - vPrev[i]) ; + double dStep = vAxNaEpSt[i].dStep ; + if ( dStep < 0) { + if ( abs( dStep - STEP_FEED) < EPS_SMALL) + dStep = m_dStep ; + else if ( abs( dStep - STEP_RAPID) < EPS_SMALL) + dStep = 4 * m_dStep ; + else if ( abs( dStep - STEP_RAPROT) < EPS_SMALL) { + dStep = 0.4 * m_dStep ; + bViewAllFrames = ( bIsRobot ? true : false) ; + } + else { // STEP_COLLROT + dStep = min( 0.4 * m_dStep, 10.) ; + bViewAllFrames = ( bIsRobot ? true : false) ; + } + } + dStep = max( dStep, 1.) ; + int nAxStep = int( dMove / dStep) + 1 ; + nStep = max( nStep, nAxStep) ; + } + // Eseguo il movimento + for ( int i = 1 ; i <= nStep ; ++ i) { + // Muovo + bool bMoveOk = true ; + double dCoeff = double( i) / nStep ; + for ( int j = 0 ; j < nAxCount ; ++ j) { + bMoveOk = m_pMchMgr->SetAxisPos( vAxNaEpSt[j].sName, ( 1 - dCoeff) * vPrev[j] + dCoeff * vAxNaEpSt[j].dEndPos) && bMoveOk ; + } + // Se abilitato e richiesto, eseguo eventuale Vmill + if ( m_bEnableVm && bExecVmill) { + for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) { + Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; + bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ; + for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) { + Frame3d frVzmF ; + bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ; + ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs, + vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; + // se ultimo utensile, salvo riferimento per prossimo inizio + if ( j == int( m_VmTool.size()) - 1) + vFrVzmI[k] = frVzmF ; + } + // aggiorno prossimo inizio + vPtNoseI[j] = ptNoseF ; + vVtDirI[j] = vtDirF ; + vVtAuxI[j] = vtAuxF ; + } + } + // Aggiorno visualizzazione + if ( bViewAllFrames || ( i % 4) == 0 || i == nStep) + ExeDraw() ; + // Verifico collisioni + int nCdInd, nObjInd ; + bool bCollCheck = ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ; + if ( ! bCollCheck) { + // Richiamo funzione di convalida collisione + int nPrevErr ; + m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nPrevErr) ; + int nErr ; + if ( ! OnCollision( nCdInd, nObjInd, nErr) && nErr == ERR_COLLISION) { + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; + if ( ExeGetEnableUI()) { + // Box di messaggio : Collisione! AVVERTIMENTO + ExeMessageBox( ExeGetMsg( 5319), ExeGetMsg( 5315), MB_OK | MB_ICONWARNING) ; + // Gestione Pausa + m_nUiStatus = MCH_UISIM_PAUSE ; + while ( m_nUiStatus == MCH_UISIM_PAUSE) { + // -11 notifica al simulatore pausa dopo collisione + ExeProcessEvents( -11, 4) ; + } + } + } + else { + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nPrevErr) ; + } + } + // In caso di errore esco + if ( ! bMoveOk) + return SIM_AXMV_RES_ERR ; + // Gestione aggiornamenti... + if ( ExeGetEnableUI()) { + // Aggiornamento interfaccia + ExeProcessEvents( 0, 4) ; + while ( m_nUiStatus == MCH_UISIM_PAUSE) { + ExeProcessEvents( 0, 4) ; + } + // Gestione Stop + if ( m_nUiStatus == MCH_UISIM_STOP) + return SIM_AXMV_RES_STOP ; + // Se cambia lo step di simulazione in modo significativo ... + if ( abs( m_dStep - dOrigStep) > 10 || abs( ( m_dStep - dOrigStep) / ( m_dStep + dOrigStep)) > 0.2) { + double dRat = m_dStep / dOrigStep ; + for ( int j = 0 ; j < nAxCount ; ++ j) { + if ( vAxNaEpSt[j].dStep > 0) + const_cast( vAxNaEpSt[j].dStep) *= dRat ; + } + return MoveAxes( nMoveType, vAxNaEpSt) ; + } + } + } + + return SIM_AXMV_RES_OK ; +} diff --git a/SimulatorSP.h b/SimulatorSP.h new file mode 100644 index 0000000..21ce025 --- /dev/null +++ b/SimulatorSP.h @@ -0,0 +1,186 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2024 +//---------------------------------------------------------------------------- +// File : SimulatorSP.h Data : 16.01.23 Versione : 2.5a2 +// Contenuto : Dichiarazione della classe Simulator. +// +// +// +// Modifiche : 19.10.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "Simulator.h" +#include "CamData.h" + +class IGeomDB ; +class Machine ; +class PerformanceCounter ; + +//---------------------------------------------------------------------------- +ISimulator* CreateSimulatorSP( void) ; + +//---------------------------------------------------------------------------- +class SimulatorSP : public ISimulator +{ + public : + ~SimulatorSP( void) override ; + bool Init( MachMgr* pMchMgr) override ; + bool Start( bool bFirst) override ; + bool Move( int& nStatus) override ; + bool GoHome( void) override ; + bool SetStep( double dStep) override ; + bool SetUiStatus( int nUiStatus) override ; + bool GetAxisInfoPos( int nI, std::string& sName, std::string& sToken, bool& bLinear, double& dVal) const override ; + bool GetToolInfo( std::string& sName, double& dSpeed) const override ; + bool GetOperationInfo( std::string& sName, int& nType) const override ; + bool GetMoveInfo( int& nGmove, double& dFeed) const override ; + bool AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, + const Vector3d& vtMove, double dPar1, double dPar2, double dPar3) override ; + bool ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType) override ; + bool OnCollision( int nCdInd, int nObjInd, int& nErr) override ; + bool SetToolForVmill( const std::string& sTool, const std::string& sHead, int nExit, int nFlag, + double dPar1, double dPar2, const INTVECTOR& vVmill, bool bFirst) override ; + bool EnableToolsForVmill( bool bEnable) override ; + int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) override ; + + public : + SimulatorSP( void) ; + + private : + bool UpdateTool( bool bFirst, int& nErr) ; + bool UpdateAxes( void) ; + bool UpdateAxesPos( void) ; + bool ResetInterpolation( void) ; + bool ResetAxes( void) ; + bool ResetAuxAxes( void) ; + + private : + bool VerifySetup( void) ; + bool FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) ; + bool ManageOperationEnd( int& nStatus) ; + bool FindAndManagePathStart( int& nStatus) ; + bool ManagePathEnd( int& nStatus) ; + bool ManagePathStartAux( int& nStatus) ; + bool ManagePathEndAux( int& nStatus) ; + bool ManageMove( int& nStatus) ; + bool ManageSingleMove( int& nStatus, double& dMove) ; + int CalcStatusOnError( int nErr) ; + bool GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA) ; + bool ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, + const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) ; + bool NeedCollisionCheck( void) const + { return ( ! m_CollObj.empty() && ! m_CdId.empty()) ; } + bool Stopped( void) + { return ( m_nUiStatus == MCH_UISIM_STOP) ; } + bool SetCollisionMark( int nCdInd, int nObjInd) ; + bool ResetCollisionMark( void) ; + bool OnInit( void) ; + bool OnExit( void) ; + bool OnProgramStart( bool bFirst) ; + bool OnProgramEnd( void) ; + bool OnDispositionStarting( int nOpId, int nOpInd, int nPhase, + const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; + bool OnDispositionStart( int nOpId, int nOpInd, int nPhase, + const std::string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) ; + bool OnDispositionEnd( void) ; + bool OnToolSelect( const std::string& sTool, const std::string& sHead, int nExit, const std::string& sTcPos, bool bFirst, int& nErr) ; + bool OnToolDeselect( const std::string& sNextTool, const std::string& sNextHead, int nNextExit, const std::string& sNextTcPos, int& nErr) ; + bool OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) ; + bool OnMachiningEnd( void) ; + bool OnPathStartAux( int nInd, const std::string& sAS, int& nErr) ; + bool OnPathEndAux( int nInd, const std::string& sAE, int& nErr) ; + bool OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, + const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, + const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) ; + bool OnPathEnd( int nAE) ; + bool OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) ; + bool OnMoveEnd( int& nErr) ; + bool OnResetMachine( void) ; + + private : + struct CollObj { + int nInd ; + bool bToolOn ; + int nFrameId ; + int nType ; + Vector3d vtMove ; + double dPar1 ; + double dPar2 ; + double dPar3 ; + CollObj( void) : nInd( 0), bToolOn( false), nFrameId( -1), nType( 0), vtMove(), dPar1( 0), dPar2( 0), dPar3( 0) {} + CollObj( int nI, bool bTOn, int nF, int nT, const Vector3d& vtM, double dP1, double dP2, double dP3) + : nInd( nI), bToolOn( bTOn), nFrameId( nF), nType( nT), vtMove( vtM), dPar1( dP1), dPar2( dP2), dPar3( dP3) {} + } ; + typedef std::vector COBVECTOR ; + struct VmTool + { + std::string sName ; + std::string sHead ; + int nExit ; + double dTdOffs ; + double dAdOffs ; + VmTool( void) : nExit( 0), dTdOffs( 0), dAdOffs( 0) {} + VmTool( std::string sN, std::string sH, int nE, double dT, double dA) + : sName( sN), sHead( sH), nExit( nE), dTdOffs( dT), dAdOffs( dA) {} + } ; + typedef std::vector VMTVECTOR ; + enum { SIS_CREATED = 0, + SIS_INITIALIZED = 1, + SIS_READYTOSTART = 2, + SIS_READYTORUN = 3} ; + + private : + MachMgr* m_pMchMgr ; // puntatore al gestore di tutte le lavorazioni + IGeomDB* m_pGeomDB ; // puntatore al DB geometrico + Machine* m_pMachine ; // puntatore alla macchina + PerformanceCounter* m_pPerfCnt ; // timer per calcolo FPS + int m_nStatus ; // stato interno del simulatore (creato, inizializzato, pronto al movimento) + double m_dStep ; // lunghezza di riferimento per la velocità di simulazione + int m_nUiStatus ; // stato simulazione a livello utente + int m_nOpId ; // identificativo della operazione (lavoraz.) corrente + int m_nOpInd ; // contatore della operazione (lavoraz.) corrente + int m_nCLPathId ; // identificativo del percorso di lavoro corrente + int m_nCLPathInd ; // contatore del percorso di lavoro corrente nell'operazione + int m_nEntId ; // identificativo dell'entità corrente + int m_nEntInd ; // contatore dell'entità corrente nel percorso di lavoro + double m_dCoeff ; // coefficiente di esecuzione del movimento corrente (0...1) + int m_nAuxSTot ; // numero totale movimenti ausiliari di inizio percorso + int m_nAuxSInd ; // indice del movimento ausiliario di inizio percorso corrente + int m_nAuxETot ; // numero totale movimenti ausiliari di fine percorso + int m_nAuxEInd ; // indice del movimento ausiliario di fine percorso corrente + std::string m_sTool ; // nome dell'utensile corrente + std::string m_sHead ; // nome della testa corrente + int m_nExit ; // indice dell'uscita corrente + double m_dTDiam ; // diametro dell'utensile corrente + bool m_bCutOnTip ; // flag capacità di lavorare di testa dell'utensile corrente + bool m_bEnableVm ; // flag abilitazione Virtual Milling + INTVECTOR m_VmId ; // vettore identificativi Zmap per Virtual Milling + INTVECTOR m_CdId ; // vettore identificativi Zmap per Collision Detection + VMTVECTOR m_VmTool ; // vettore utensili attivi per virtual milling + COBVECTOR m_CollObj ; // vettore oggetti da testare per collisione con grezzo + double m_dSafeDist ; // distanza di sicurezza per verifica collisioni + INTVECTOR m_nCollMarkId ; // elenco oggetti marcati per visualizzare meglio la collisione rilevata + int m_nAxesMask ; // maschera a bit di abilitazione movimento assi (solo se rapido) + bool m_bEnabAxes ; // flag abilitazione movimento assi attivi + bool m_bShowAxes ; // flag visualizzazione assi attivi + STRVECTOR m_AxesName ; // nomi degli assi macchina attivi + STRVECTOR m_AxesToken ; // token degli assi macchina attivi + BOOLVECTOR m_AxesInvert ; // flag di asse con verso invertito degli assi macchina attivi + DBLVECTOR m_AxesOffset ; // valore di offset delgli assi macchina ttivi + BOOLVECTOR m_AxesLinear ; // flag di lineare degli assi macchina attivi + DBLVECTOR m_AxesVal ; // valori degli assi macchina all'inizio del movimento corrente + STRVECTOR m_AuxAxesName ; // nomi degli assi macchina ausiliari abilitati + STRVECTOR m_AuxAxesToken ; // token degli assi macchina ausiliari abilitati + BOOLVECTOR m_AuxAxesInvert ; // flag di asse con verso invertito degli assi macchina ausiliari abilitati + DBLVECTOR m_AuxAxesOffset ; // valore di offset degli assi macchina ausiliari abilitati + BOOLVECTOR m_AuxAxesLinear ; // flag di lineare degli assi macchina ausiliari abilitati + DBLVECTOR m_AuxAxesVal ; // valori degli assi macchina ausiliari all'inizio del movimento corrente + DBLVECTOR m_AuxAxesEnd ; // valori degli assi macchina ausiliari alla fine del movimento corrente + INTVECTOR m_AuxAxesLink ; // indice + 1 asse principale di aggancio (negativo valore opposto, 0 nessuno) +} ; From 431246b4724ae6ded129590a0e2a9fec19f1195d Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 9 Sep 2024 09:30:14 +0200 Subject: [PATCH 2/2] EgtMachKernel : - in svuotature chiuse migliorata scelta lato ottimale di inizio - altri sviluppi in SimulatorMP. --- MachMgr.h | 2 + MachMgrSimulation.cpp | 17 +- Machine.cpp | 2 +- Machine.h | 7 +- MachineLua.cpp | 34 +++- OutputConst.h | 1 + Pocketing.cpp | 2 +- Simulator.h | 1 + SimulatorMP.cpp | 381 +++++++++++++++++++++++++----------------- SimulatorMP.h | 23 ++- SimulatorSP.h | 6 +- 11 files changed, 303 insertions(+), 173 deletions(-) diff --git a/MachMgr.h b/MachMgr.h index a0de374..5e8dfe5 100644 --- a/MachMgr.h +++ b/MachMgr.h @@ -475,6 +475,8 @@ class MachMgr : public IMachMgr const INTVECTOR& vVmill, bool bFirst) ; bool SimEnableToolsForVmill( bool bEnable) ; int SimMoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) ; + bool SimSaveCmd( int nType, int nPar, const std::string& sPar) ; + // Machine bool GetHeadAbove( const std::string& sHead) const ; double GetAngDeltaMinForHome( void) const ; diff --git a/MachMgrSimulation.cpp b/MachMgrSimulation.cpp index d4679d2..b434abd 100644 --- a/MachMgrSimulation.cpp +++ b/MachMgrSimulation.cpp @@ -30,9 +30,9 @@ MachMgr::SimInit( void) delete m_pSimul ; if ( GetCurrMachine() == nullptr) return false ; - //if ( GetCurrMachine()->GetMultiProcess()) - // m_pSimul = CreateSimulatorMP() ; - //else + if ( GetCurrMachine()->GetMultiProcess( 2)) + m_pSimul = CreateSimulatorMP() ; + else m_pSimul = CreateSimulatorSP() ; if ( m_pSimul == nullptr) return false ; @@ -220,3 +220,14 @@ MachMgr::SimMoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) // lancio movimento assi return m_pSimul->MoveAxes( nMoveType, vAxNaEpSt) ; } + +//---------------------------------------------------------------------------- +bool +MachMgr::SimSaveCmd( int nType, int nPar, const string& sPar) +{ + // verifico simulatore + if ( m_pSimul == nullptr) + return false ; + // salvo il comando + return m_pSimul->SaveCmd( nType, nPar, sPar) ; +} diff --git a/Machine.cpp b/Machine.cpp index c07c7dd..f1d5e45 100644 --- a/Machine.cpp +++ b/Machine.cpp @@ -41,7 +41,7 @@ Machine::Machine( void) m_dExitMaxAdjust = EPS_SMALL ; m_dExitMaxRotAdj = 10 * EPS_ANG_SMALL ; m_dAngDeltaMinForHome = INFINITO ; - m_bMultiProcess = false ; + m_nMultiProcess = 0 ; m_nCalcTabId = GDB_ID_NULL ; m_nCalcHeadId = GDB_ID_NULL ; m_nCalcExitId = GDB_ID_NULL ; diff --git a/Machine.h b/Machine.h index 32bd835..6113d47 100644 --- a/Machine.h +++ b/Machine.h @@ -71,8 +71,8 @@ class Machine int GetHeadSelectType(const std::string& sHead) const ; double GetAngDeltaMinForHome( void) const { return m_dAngDeltaMinForHome ; } - bool GetMultiProcess( void) const - { return m_bMultiProcess ; } + bool GetMultiProcess( int nOpt = 1) const + { return ( m_nMultiProcess >= nOpt) ; } bool LoadTool( const std::string& sHead, int nExit, const std::string& sTool) ; bool GetLoadedTool( const std::string& sHead, int nExit, std::string& sTool) const ; bool UnloadTool( const std::string& sHead, int nExit) ; @@ -293,7 +293,7 @@ class Machine double m_dExitMaxAdjust ; // massimo aggiustamento uscita da geometria a descrizione cinematica double m_dExitMaxRotAdj ; // massima rotazione di aggiustamento uscita da geometria a descrizione cinematica double m_dAngDeltaMinForHome ; // minima differenza angolare da valore precedente per scegliere di stare vicino a home - bool m_bMultiProcess ; // flag di macchina multi-processo con stima speciale prima di generazione e simulazione ad hoc + int m_nMultiProcess ; // flag di macchina multi-processo con stima speciale prima di generazione e simulazione ad hoc INTVECTOR m_vLinkedRawParts ; // elenco dei grezzi agganciati a gruppi della macchina INTVECTOR m_vLinkedFixtures ; // elenco dei bloccaggi agganciati a gruppi della macchina INTVECTOR m_vLinkedParts ; // elenco dei pezzi agganciati a gruppi della macchina @@ -380,6 +380,7 @@ class Machine static int LuaEmtAddToolForVmill( lua_State* L) ; static int LuaEmtEnableToolsForVmill( lua_State* L) ; static int LuaEmtMoveAxes( lua_State* L) ; + static int LuaEmtSaveCmd( lua_State* L) ; } ; //---------------------------------------------------------------------------- diff --git a/MachineLua.cpp b/MachineLua.cpp index 5495554..b3151a5 100644 --- a/MachineLua.cpp +++ b/MachineLua.cpp @@ -146,6 +146,8 @@ Machine::LuaInit( const string& sMachineName) m_LuaMgr.RegisterFunction( "EmtEnableToolsForVmill", Machine::LuaEmtEnableToolsForVmill) ; // registro la funzione di movimento assi in simulazione m_LuaMgr.RegisterFunction( "EmtMoveAxes", Machine::LuaEmtMoveAxes) ; + // registro la funzione di salvataggio comandi in simulazione MP + m_LuaMgr.RegisterFunction( "EmtSaveCmd", Machine::LuaEmtSaveCmd) ; return true ; } @@ -345,9 +347,9 @@ Machine::LuaEmtGeneral( lua_State* L) // lettura eventuale campo 'AngDeltaForHome' dalla tabella (default INFINITO) double dAngDeltaMinForHome = INFINITO ; LuaGetTabFieldParam( L, 1, FLD_ANGDELTAMINFORHOME, dAngDeltaMinForHome) ; - // lettura eventuale campo 'MultiProcess' dalla tabella (default false) - bool bMultiProcess = false ; - LuaGetTabFieldParam( L, 1, FLD_MULTIPROCESS, bMultiProcess) ; + // lettura eventuale campo 'MultiProcess' dalla tabella (0=no, 1=si, 2=si con simulazione MP) + int nMultiProcess = 0 ; + LuaGetTabFieldParam( L, 1, FLD_MULTIPROCESS, nMultiProcess) ; LuaClearStack( L) ; // info @@ -398,7 +400,7 @@ Machine::LuaEmtGeneral( lua_State* L) m_pMchLua->m_dAngDeltaMinForHome = dAngDeltaMinForHome ; // imposto flag per macchina multiprocesso - m_pMchLua->m_bMultiProcess = bMultiProcess ; + m_pMchLua->m_nMultiProcess = nMultiProcess ; return 0 ; } @@ -1512,7 +1514,7 @@ int Machine::LuaEmtEnableToolsForVmill( lua_State* L) { // 1 parametro : bEnable - bool bEnable ; + bool bEnable = false ; LuaGetParam( L, 1, bEnable) ; LuaClearStack( L) ; // verifico ci sia una macchina attiva @@ -1560,3 +1562,25 @@ Machine::LuaEmtMoveAxes( lua_State* L) } return 2 ; } + +//---------------------------------------------------------------------------- +int +Machine::LuaEmtSaveCmd( lua_State* L) +{ + // parametri : nType, + int nType = 0 ; + LuaGetParam( L, 1, nType) ; + int nPar = 0 ; + LuaGetParam( L, 2, nPar) ; + string sPar ; + LuaGetParam( L, 3, sPar) ; + LuaClearStack( L) ; + // verifico ci sia una macchina attiva + if ( m_pMchLua == nullptr) + return luaL_error( L, " Unknown Machine") ; + // salvo il comando + bool bOk = ( m_pMchLua->m_pMchMgr != nullptr && m_pMchLua->m_pMchMgr->SimSaveCmd( nType, nPar, sPar)) ; + // assegno risultato + LuaSetParam( L, bOk) ; + return 1 ; +} diff --git a/OutputConst.h b/OutputConst.h index 97ba635..1ee6854 100644 --- a/OutputConst.h +++ b/OutputConst.h @@ -184,6 +184,7 @@ static const std::string GVAR_SIMUISTAT = ".SIMUISTAT" ; // (num) stato sim static const std::string GVAR_SAFEDIST = ".SAFEDIST" ; // (num) distanza di sicurezza per verifica di collisione static const std::string GVAR_SIMVMID = ".SIMVMID" ; // (int) identificativo grezzo Vmill in collisione static const std::string GVAR_SIMCOBIND = ".SIMCOBIND" ; // (int) indice oggetto in collisione +static const std::string GVAR_MPSIM = ".MPSIM" ; // (bool) flag simulazione multiprocesso // Funzioni generazione static const std::string ON_START = "OnStart" ; static const std::string ON_END = "OnEnd" ; diff --git a/Pocketing.cpp b/Pocketing.cpp index ee2f079..0c22ab8 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -5744,7 +5744,7 @@ Pocketing::AdjustContourStart( ICurveComposite* pCompo) pCrv = pCompo->GetNextCurve() ; } // se non trovato o troppo corto, cerco il tratto generico più lungo - if ( nMax < 0 || dLenMax < 2 * m_TParams.m_dDiam) { + if ( nMax < 0 || dLenMax < 1.25 * m_TParams.m_dDiam) { i = 0 ; pCrv = pCompo->GetFirstCurve() ; while ( pCrv != nullptr) { diff --git a/Simulator.h b/Simulator.h index 854d00e..d2704e3 100644 --- a/Simulator.h +++ b/Simulator.h @@ -59,4 +59,5 @@ class __declspec( novtable) ISimulator double dPar1, double dPar2, const INTVECTOR& vVmill, bool bFirst) = 0 ; virtual bool EnableToolsForVmill( bool bEnable) = 0 ; virtual int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) = 0 ; + virtual bool SaveCmd( int nType, int nPar, const std::string& sPar) = 0 ; } ; diff --git a/SimulatorMP.cpp b/SimulatorMP.cpp index 5899225..6df9161 100644 --- a/SimulatorMP.cpp +++ b/SimulatorMP.cpp @@ -50,6 +50,7 @@ static const double COLL_STEP = 10. ; static const double SQ_COEFF_ROT_MOVE = 100. ; static const double COEFF_LIM = 0.999 ; static const double SAFEDIST_STD = 5.0 ; +static const int ERR_NONE = 0 ; static const int ERR_OUTSTROKE = 1 ; static const int ERR_COLLISION = 11 ; static const int ERR_TOOL_SEL = 21 ; @@ -78,6 +79,7 @@ SimulatorMP::SimulatorMP( void) m_nEntId = GDB_ID_NULL ; m_nEntInd = 0 ; m_dCoeff = 0 ; + m_bChangedTool = false ; m_nAuxSTot = 0 ; m_nAuxSInd = 0 ; m_nAuxETot = 0 ; @@ -127,6 +129,9 @@ SimulatorMP::Init( MachMgr* pMchMgr) m_pMachine = m_pMchMgr->GetCurrMachine() ; m_pPerfCnt = new PerformanceCounter ; m_nStatus = SIS_INITIALIZED ; + if ( ExeGetDebugLevel() >= 1) + LOG_INFO( GetEMkLogger(), " * SimulatorMP *") + return true ; } @@ -159,6 +164,7 @@ SimulatorMP::Start( bool bFirst) m_nExit = 0 ; m_dTDiam = 0 ; m_bCutOnTip = false ; + m_bChangedTool = false ; ResetInterpolation() ; ResetAxes() ; ResetAuxAxes() ; @@ -180,6 +186,7 @@ SimulatorMP::Start( bool bFirst) m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_VER, GetEMkVer()) ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MACHNAME, m_pMachine->GetMachineName()) ; + m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MPSIM, true) ; // Se appena entrati in simulazione if ( m_nStatus == SIS_INITIALIZED) { @@ -194,7 +201,7 @@ SimulatorMP::Start( bool bFirst) // Arrivo alla preparazione per la prima lavorazione int nStatus ; - if ( ! FindAndManageOperationStart( true, bFirst, nStatus) && nStatus != MCH_SIM_STOP) + if ( ! FindAndManageOperationStart( true, bFirst, m_bChangedTool, nStatus) && nStatus != MCH_SIM_STOP) bOk = false ; // se sono ancora su disposizione if ( m_pMchMgr->GetOperationType( m_nOpId) == OPER_DISP) { @@ -312,14 +319,16 @@ SimulatorMP::Move( int& nStatus) return false ; } - // Se arrivato alla fine di una operazione - if ( m_nCLPathId == GDB_ID_NULL) { + // Se arrivato alla fine di una operazione o appena scaricato utensile + if ( m_nCLPathId == GDB_ID_NULL || m_bChangedTool) { // gestione fine operazione - if ( ! ManageOperationEnd( nStatus)) + if ( m_nCLPathId == GDB_ID_NULL && ! ManageOperationEnd( nStatus)) return false ; // ricerca e gestione nuova operazione - if ( ! FindAndManageOperationStart( false, false, nStatus)) + if ( ! FindAndManageOperationStart( false, false, m_bChangedTool, nStatus)) return false ; + if ( m_bChangedTool) + return true ; // se non ce ne sono altre, sono alla fine if ( m_nOpId == GDB_ID_NULL) { OnProgramEnd() ; @@ -489,111 +498,126 @@ SimulatorMP::GoHome( void) //---------------------------------------------------------------------------- bool -SimulatorMP::UpdateTool( bool bFirst, int& nErr) +SimulatorMP::UpdateMachiningTool( bool bFirst, bool& bDeselected, int& nErr) { - // reset stato di errore da script - nErr = 0 ; - // Recupero l'utensile della lavorazione corrente + // Reset stato + nErr = ERR_NONE ; + + // Recupero la lavorazione corrente Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pMch != nullptr) { - // recupero nome e dati nuovo utensile - string sTuuid, sTool ; - if ( ! pMch->GetParam( MPA_TUUID, sTuuid) || - ! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool)) - return false ; - string sTcPos ; string sHead ; int nExit ; - if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) { - if ( m_pMchMgr->TdbSetCurrTool( sTool)) { - m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ; - m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ; - m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ; - } - // ripristino l'utensile corrente - m_pMchMgr->TdbSetCurrTool( m_sTool) ; + if ( pMch == nullptr) + return false ; + + // Recupero nome e dati nuovo utensile + string sTuuid, sTool ; + if ( ! pMch->GetParam( MPA_TUUID, sTuuid) || + ! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool)) + return false ; + string sTcPos ; string sHead ; int nExit ; + if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) { + if ( m_pMchMgr->TdbSetCurrTool( sTool)) { + m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ; + m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ; + m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ; } - // verifico se cambierà - bool bDiffTool = ( sTool != m_sTool) ; - // se cambierà ed esiste il corrente, lo scarico - if ( bDiffTool && ! m_sTool.empty()) { - // eventuale lancio script per scarico utensile - int nCurrErr ; - if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - } - // se prima volta, pulisco la testa - if ( bFirst) - m_pMchMgr->ResetHeadSet( sHead) ; - // recupero la lavorazione corrente e imposto la nuova - int nCurrMchId = m_pMchMgr->GetCurrMachining() ; - m_pMchMgr->SetCurrMachining( m_nOpId) ; - // carico l'utensile (e lo rendo corrente) - if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) - return false ; - m_sTool = sTool ; - m_sHead = sHead ; - m_nExit = nExit ; - m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; - double dTipFeed = 0 ; - m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; - m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; - // ripristino la lavorazione corrente - m_pMchMgr->SetCurrMachining( nCurrMchId) ; - // aggiorno gli assi macchina - if ( ! UpdateAxes()) - return false ; - // se cambiato oppure prima volta, lancio lo script di selezione - if ( bDiffTool || bFirst) { - int nCurrErr ; - if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - } - return ( nErr == 0) ; + // ripristino l'utensile corrente + m_pMchMgr->TdbSetCurrTool( m_sTool) ; } - // Provo con una disposizione - Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; - if ( pDisp != nullptr) { - // recupero i dati - string sTool ; string sHead ; int nExit ; string sTcPos ; - pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ; - // se esiste utensile corrente e cambierà, lo scarico - if ( ! m_sTool.empty() && sTool != m_sTool) { - // eventuale lancio script per scarico utensile - int nCurrErr ; - if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; - if ( nCurrErr != ERR_COLLISION) - return false ; - } - } - // carico l'utensile - if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) - return false ; - m_sTool = sTool ; - m_sHead = sHead ; - m_nExit = nExit ; - m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; - double dTipFeed = 0 ; - m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; - m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; - // aggiorno gli assi macchina - if ( ! UpdateAxes()) - return false ; - // eventuale lancio script + // verifico se cambierà + bool bDiffTool = ( sTool != m_sTool) ; + // se cambierà ed esiste il corrente, lo scarico + if ( bDiffTool && ! m_sTool.empty() && ! bDeselected) { + // eventuale lancio script per scarico utensile int nCurrErr ; - if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { - nErr = ( nErr != 0 ? nErr : nCurrErr) ; + if ( OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { + bDeselected = true ; + return true ; + } + else { + nErr = ( nErr != ERR_NONE ? nErr : nCurrErr) ; if ( nCurrErr != ERR_COLLISION) return false ; } - return ( nErr == 0) ; } - return false ; + bDeselected = false ; + // se prima volta, pulisco la testa + if ( bFirst) + m_pMchMgr->ResetHeadSet( sHead) ; + // recupero la lavorazione corrente e imposto la nuova + int nCurrMchId = m_pMchMgr->GetCurrMachining() ; + m_pMchMgr->SetCurrMachining( m_nOpId) ; + // carico l'utensile (e lo rendo corrente) + if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) + return false ; + m_sTool = sTool ; + m_sHead = sHead ; + m_nExit = nExit ; + m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; + double dTipFeed = 0 ; + m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; + m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; + // ripristino la lavorazione corrente + m_pMchMgr->SetCurrMachining( nCurrMchId) ; + // aggiorno gli assi macchina + if ( ! UpdateAxes()) + return false ; + // se cambiato oppure prima volta, lancio lo script di selezione + if ( bDiffTool || bFirst) { + int nCurrErr ; + if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { + nErr = ( nErr != ERR_NONE ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + return ( nErr == ERR_NONE) ; +} + +//---------------------------------------------------------------------------- +bool +SimulatorMP::UpdateDispositionTool( bool bFirst, int& nErr) +{ + // Reset stato di errore da script + nErr = ERR_NONE ; + // Recupero la disposizione + Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; + if ( pDisp == nullptr) + return false ; + + // Recupero i dati + string sTool ; string sHead ; int nExit ; string sTcPos ; + pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ; + // se esiste utensile corrente e cambierà, lo scarico + if ( ! m_sTool.empty() && sTool != m_sTool) { + // eventuale lancio script per scarico utensile + int nCurrErr ; + if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { + nErr = ( nErr != ERR_NONE ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + } + // carico l'utensile + if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit)) + return false ; + m_sTool = sTool ; + m_sHead = sHead ; + m_nExit = nExit ; + m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ; + double dTipFeed = 0 ; + m_pMchMgr->TdbGetCurrToolParam( TPA_TIPFEED, dTipFeed) ; + m_bCutOnTip = ( dTipFeed > EPS_MACH_LEN_PAR) ; + // aggiorno gli assi macchina + if ( ! UpdateAxes()) + return false ; + // eventuale lancio script + int nCurrErr ; + if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, nCurrErr)) { + nErr = ( nErr != ERR_NONE ? nErr : nCurrErr) ; + if ( nCurrErr != ERR_COLLISION) + return false ; + } + return ( nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -680,18 +704,20 @@ SimulatorMP::ResetAuxAxes( void) //---------------------------------------------------------------------------- bool -SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) +SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, bool& bChangedTool, int& nStatus) { // verifico parametri if ( ! bStart) bFirst = false ; // recupero la nuova operazione - if ( bStart) { - m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; - m_nOpInd = 0 ; + if ( ! bChangedTool) { + if ( bStart) { + m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; + m_nOpInd = 0 ; + } + else + m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; } - else - m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; // ciclo sulle successive operazioni while ( m_nOpId != GDB_ID_NULL) { // se lavorazione valida @@ -700,12 +726,14 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus bool bOk = true ; // aggiorno utensile e assi conseguenti int nErr ; - if ( ! UpdateTool( bFirst, nErr)) { + if ( ! UpdateMachiningTool( bFirst, bChangedTool, nErr)) { string sOut = "Err=" + ToString( nErr) ; LOG_INFO( GetEMkLogger(), sOut.c_str()) nStatus = CalcStatusOnError( nErr) ; - bOk = false ; + return false ; } + if ( bChangedTool) + return true ; ++ m_nOpInd ; // imposto la lavorazione come corrente m_pMchMgr->SetCurrMachining( m_nOpId) ; @@ -719,12 +747,10 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus m_pGeomDB->GetInfo( nClId, KEY_MAXMAX, vAxMax) ; // richiamo gestione evento inizio lavorazione if ( ! OnMachiningStart( m_nOpId, m_nOpInd, ptMin, ptMax, vAxMin, vAxMax)) { - nStatus = CalcStatusOnError( 0) ; - bOk = false ; - } - if ( ! bOk) + nStatus = CalcStatusOnError( ERR_NONE) ; return false ; - break ; + } + return true ; } // se disposizione con cambio di fase Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; @@ -746,7 +772,7 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus if ( ! bEmpty) { // richiamo gestione evento appena prima di inizio disposizione if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // cambio fase @@ -754,7 +780,7 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus // se previsto, aggiorno utensile e assi conseguenti if ( pDisp->IsWithTool()) { int nErr ; - if ( ! UpdateTool( bFirst, nErr)) { + if ( ! UpdateDispositionTool( bFirst, nErr)) { nStatus = CalcStatusOnError( nErr) ; return false ; } @@ -762,7 +788,7 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus ++ m_nOpInd ; // richiamo gestione evento inizio disposizione if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // se ci sono movimenti manuali, aggiorno visualizzazione e breve pausa (200 ms) @@ -774,7 +800,7 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus else { // richiamo gestione evento appena prima di inizio disposizione if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand)) { - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // cambio fase @@ -783,7 +809,7 @@ SimulatorMP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus // richiamo gestione evento inizio e fine disposizione if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) || ! OnDispositionEnd()) { - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) @@ -819,7 +845,7 @@ SimulatorMP::ManageOperationEnd( int& nStatus) } // gestione stato if ( ! bOk) - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return bOk ; } @@ -881,7 +907,7 @@ SimulatorMP::FindAndManagePathStart( int& nStatus) m_nAuxETot = 0 ; // richiamo gestione evento inizio percorso di lavoro if ( ! OnPathStart( m_nCLPathId, m_nCLPathInd, m_nAuxSTot, ptStart, ptEnd, vtExtr, ptMin, ptMax, vAxMin, vAxMax, dElev)) { - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } } @@ -912,7 +938,7 @@ SimulatorMP::ManagePathEnd( int& nStatus) bool bOk = OnPathEnd( m_nAuxETot) ; // gestione stato if ( ! bOk) - nStatus = CalcStatusOnError( 0) ; + nStatus = CalcStatusOnError( ERR_NONE) ; return bOk ; } @@ -1381,8 +1407,8 @@ SimulatorMP::GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& //---------------------------------------------------------------------------- bool SimulatorMP::ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs, - const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, - const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) + const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, + const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) { // Recupero Zmap IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( nVmId)) ; @@ -1709,7 +1735,7 @@ SimulatorMP::OnToolSelect( const string& sTool, const string& sHead, int nExit, bool bFirst, int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // reset oggetti per verifica collisione con grezzo m_CollObj.clear() ; // assegno il nome dell'utensile, la testa e l'uscita @@ -1755,7 +1781,7 @@ SimulatorMP::OnToolSelect( const string& sTool, const string& sHead, int nExit, ResetAuxAxes() ; int nNumAuxAxes = 0 ; if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0) - return ( bOk && nErr == 0) ; + return ( bOk && nErr == ERR_NONE) ; m_AuxAxesName.reserve( nNumAuxAxes) ; m_AuxAxesToken.reserve( nNumAuxAxes) ; m_AuxAxesInvert.reserve( nNumAuxAxes) ; @@ -1790,7 +1816,7 @@ SimulatorMP::OnToolSelect( const string& sTool, const string& sHead, int nExit, } } - return ( bOk && nErr == 0) ; + return ( bOk && nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -1798,7 +1824,7 @@ bool SimulatorMP::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos, int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // assegno il prossimo utensile bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTOOL, sNextTool) ; // assegno la prossima testa @@ -1818,7 +1844,7 @@ SimulatorMP::OnToolDeselect( const string& sNextTool, const string& sNextHead, i UpdateAxesPos() ; // verifico codice di errore bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; + return ( bOk && nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -1916,7 +1942,7 @@ bool SimulatorMP::OnPathStartAux( int nInd, const string& sAS, int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START_AUX)) return true ; @@ -1930,7 +1956,7 @@ SimulatorMP::OnPathStartAux( int nInd, const string& sAS, int& nErr) UpdateAxesPos() ; // verifico codice di errore bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; + return ( bOk && nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -1938,7 +1964,7 @@ bool SimulatorMP::OnPathEndAux( int nInd, const string& sAE, int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END_AUX)) return true ; @@ -1952,7 +1978,7 @@ SimulatorMP::OnPathEndAux( int nInd, const string& sAE, int& nErr) UpdateAxesPos() ; // verifico codice di errore bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; + return ( bOk && nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -1960,7 +1986,7 @@ bool SimulatorMP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // recupero e assegno i dati // dati generali e reset errore bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEID, m_nEntId) ; @@ -2025,7 +2051,7 @@ SimulatorMP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, // verifico codice di errore m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - if ( nErr != 0) + if ( nErr != ERR_NONE) return false ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) @@ -2095,7 +2121,7 @@ SimulatorMP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, m_AuxAxesEnd.emplace_back( dEnd) ; m_AuxAxesLink.emplace_back( 0) ; if ( ! m_pMachine->VerifyOutstroke( sName, dEnd)) { - nErr = 1 ; + nErr = ERR_OUTSTROKE ; bOk = false ; } } @@ -2116,7 +2142,7 @@ bool SimulatorMP::OnMoveEnd( int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_END)) return true ; @@ -2129,7 +2155,7 @@ SimulatorMP::OnMoveEnd( int& nErr) UpdateAxesPos() ; // verifico codice di errore m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; - return ( bOk && nErr == 0) ; + return ( bOk && nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -2137,7 +2163,7 @@ bool SimulatorMP::OnCollision( int nCdInd, int nObjInd, int& nErr) { // reset stato di errore da script - nErr = 0 ; + nErr = ERR_NONE ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_COLLISION)) return true ; @@ -2165,7 +2191,7 @@ SimulatorMP::OnCollision( int nCdInd, int nObjInd, int& nErr) ExeDraw() ; } - return ( nErr == 0) ; + return ( nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- @@ -2218,7 +2244,7 @@ SimulatorMP::AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType, c //---------------------------------------------------------------------------- bool SimulatorMP::SetToolForVmill( const string& sTool, const string& sHead, int nExit, int nFlag, double dPar1, double dPar2, - const INTVECTOR& vVmill, bool bFirst) + const INTVECTOR& vVmill, bool bFirst) { // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) CmdLogOff cmdLogOff ; @@ -2332,9 +2358,9 @@ SimulatorMP::MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) if ( vAxNaEpSt.empty()) return SIM_AXMV_RES_ERR ; // Salvo i dati di movimento - m_CmdData.emplace_back( 1, nMoveType, vAxNaEpSt) ; + m_CmdData.emplace_back( nMoveType, vAxNaEpSt) ; // Log dati - if ( ExeGetDebugLevel() >= 5) { + if ( ExeGetDebugLevel() >= 4) { string sOut = "Save=SimulMoveAxes," + ToString( nMoveType) ; for ( int i = 0 ; i < int( vAxNaEpSt.size()) ; ++ i) sOut += "," + vAxNaEpSt[i].sName + @@ -2346,6 +2372,20 @@ SimulatorMP::MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) return SIM_AXMV_RES_OK ; } +//---------------------------------------------------------------------------- +bool +SimulatorMP::SaveCmd( int nType, int nPar, const string& sPar) +{ + // Salvo il comando + m_CmdData.emplace_back( nType, nPar, sPar) ; + // Log dati + if ( ExeGetDebugLevel() >= 4) { + string sOut = "Save=SimulSaveCmd," + ToString( nType) + "," + ToString( nPar) + "," + sPar ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) + } + return false ; +} + //---------------------------------------------------------------------------- bool SimulatorMP::ExecCmdData( int& nStatus) @@ -2354,7 +2394,7 @@ SimulatorMP::ExecCmdData( int& nStatus) auto& CmdCurr = m_CmdData[m_nCmdInd] ; // Stampe di debug - if ( ExeGetDebugLevel() >= 5) { + if ( ExeGetDebugLevel() >= 4) { if ( CmdCurr.nType == 1) { string sOut = "Cmd=SimulMoveAxes," + ToString( CmdCurr.nMoveType) ; for ( int i = 0 ; i < int( CmdCurr.vAxNaEpSt.size()) ; ++ i) @@ -2363,9 +2403,13 @@ SimulatorMP::ExecCmdData( int& nStatus) "," + ToString( CmdCurr.vAxNaEpSt[i].dStep, 3) ; LOG_INFO( GetEMkLogger(), sOut.c_str()) } + else { + string sOut = "Cmd=SimulSaveCmd," + ToString( CmdCurr.nType) + "," + ToString( CmdCurr.nPar) + "," + CmdCurr.sPar ; + LOG_INFO( GetEMkLogger(), sOut.c_str()) + } } - // Eseguo + // Eseguo movimento assi if ( CmdCurr.nType == 1) { // Numero assi da muovere int nAxCount = int( CmdCurr.vAxNaEpSt.size()) ; @@ -2378,7 +2422,7 @@ SimulatorMP::ExecCmdData( int& nStatus) // Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill) bool bExecVmill = (( CmdCurr.nMoveType != 0 || ! NeedCollisionCheck()) && ! m_VmTool.empty() && ! m_VmId.empty()) ; PNTVECTOR vPtNoseI ; - VCT3DVECTOR vVtDirI ; + VCT3DVECTOR vVtDirI ; VCT3DVECTOR vVtAuxI ; vector vFrVzmI ; if ( bExecVmill) { @@ -2461,14 +2505,51 @@ SimulatorMP::ExecCmdData( int& nStatus) UpdateAxesPos() ; return false ; } + UpdateAxesPos() ; + // Aggiorno dati interpolazione + if ( m_dCmdCoeff > COEFF_LIM) { + m_nCmdInd += 1 ; + m_dCmdCoeff = 0 ; + } } - UpdateAxesPos() ; - - // Aggiorno dati interpolazione - if ( m_dCmdCoeff > COEFF_LIM) { + // eseguo impostazione stato + else if ( CmdCurr.nType == 2) { + // imposto + if ( ! m_pGeomDB->SetStatus( CmdCurr.nPar, ( CmdCurr.sPar == "ON" ? GDB_ST_ON : GDB_ST_OFF))) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // Aggiorno indice comandi eseguiti m_nCmdInd += 1 ; m_dCmdCoeff = 0 ; } + // eseguo impostazione modo + else if ( CmdCurr.nType == 3) { + // imposto + if ( ! m_pGeomDB->SetMode( CmdCurr.nPar, ( CmdCurr.sPar == "STD" ? GDB_MD_STD : GDB_MD_HIDDEN))) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // Aggiorno indice comandi eseguiti + m_nCmdInd += 1 ; + m_dCmdCoeff = 0 ; + } + // eseguo chiamata funzione + else if ( CmdCurr.nType == 5) { + // chiamo la funzione + if ( ! m_pMachine->LuaCallFunction( CmdCurr.sPar)) { + nStatus = MCH_SIM_ERR ; + return false ; + } + // Aggiorno indice comandi eseguiti + m_nCmdInd += 1 ; + m_dCmdCoeff = 0 ; + } + // altrimenti errore + else { + nStatus = MCH_SIM_ERR ; + return false ; + } return true ; } diff --git a/SimulatorMP.h b/SimulatorMP.h index 6ea5048..b768ddd 100644 --- a/SimulatorMP.h +++ b/SimulatorMP.h @@ -45,13 +45,15 @@ class SimulatorMP : public ISimulator bool SetToolForVmill( const std::string& sTool, const std::string& sHead, int nExit, int nFlag, double dPar1, double dPar2, const INTVECTOR& vVmill, bool bFirst) override ; bool EnableToolsForVmill( bool bEnable) override ; - int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) override ; + int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) override ; + bool SaveCmd( int nType, int nPar, const std::string& sPar) override ; public : SimulatorMP( void) ; private : - bool UpdateTool( bool bFirst, int& nErr) ; + bool UpdateMachiningTool( bool bFirst, bool& bDeselect, int& nErr) ; + bool UpdateDispositionTool( bool bFirst, int& nErr) ; bool UpdateAxes( void) ; bool UpdateAxesPos( void) ; bool ResetInterpolation( void) ; @@ -60,7 +62,7 @@ class SimulatorMP : public ISimulator private : bool VerifySetup( void) ; - bool FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) ; + bool FindAndManageOperationStart( bool bStart, bool bFirst, bool& bChangedTool, int& nStatus) ; bool ManageOperationEnd( int& nStatus) ; bool FindAndManagePathStart( int& nStatus) ; bool ManagePathEnd( int& nStatus) ; @@ -139,12 +141,16 @@ class SimulatorMP : public ISimulator private : struct CmdData { - int nType ; - int nMoveType ; - SAMVECTOR vAxNaEpSt ; + int nType ; + int nMoveType ; + SAMVECTOR vAxNaEpSt ; + int nPar ; + std::string sPar ; CmdData( void) : nType(0) {} - CmdData( int nT, int nM, const SAMVECTOR& vAx) - : nType( nT), nMoveType( nM), vAxNaEpSt( vAx) {} + CmdData( int nM, const SAMVECTOR& vAx) + : nType( 1), nMoveType( nM), vAxNaEpSt( vAx) {} + CmdData( int nT, int nP, const std::string& sP) + : nType( nT), nPar( nP), sPar( sP) {} } ; typedef std::vector CMDVECTOR ; @@ -163,6 +169,7 @@ class SimulatorMP : public ISimulator int m_nEntId ; // identificativo dell'entità corrente int m_nEntInd ; // contatore dell'entità corrente nel percorso di lavoro double m_dCoeff ; // coefficiente di esecuzione del movimento corrente (0...1) + bool m_bChangedTool ; // flag di utensile appena scaricato int m_nAuxSTot ; // numero totale movimenti ausiliari di inizio percorso int m_nAuxSInd ; // indice del movimento ausiliario di inizio percorso corrente int m_nAuxETot ; // numero totale movimenti ausiliari di fine percorso diff --git a/SimulatorSP.h b/SimulatorSP.h index 21ce025..e67af91 100644 --- a/SimulatorSP.h +++ b/SimulatorSP.h @@ -46,6 +46,8 @@ class SimulatorSP : public ISimulator double dPar1, double dPar2, const INTVECTOR& vVmill, bool bFirst) override ; bool EnableToolsForVmill( bool bEnable) override ; int MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt) override ; + bool SaveCmd( int nType, int nPar, const std::string& sPar) override + { return false ; } public : SimulatorSP( void) ; @@ -74,9 +76,9 @@ class SimulatorSP : public ISimulator const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI, const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF) ; bool NeedCollisionCheck( void) const - { return ( ! m_CollObj.empty() && ! m_CdId.empty()) ; } + { return ( ! m_CollObj.empty() && ! m_CdId.empty()) ; } bool Stopped( void) - { return ( m_nUiStatus == MCH_UISIM_STOP) ; } + { return ( m_nUiStatus == MCH_UISIM_STOP) ; } bool SetCollisionMark( int nCdInd, int nObjInd) ; bool ResetCollisionMark( void) ; bool OnInit( void) ;