//---------------------------------------------------------------------------- // 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/EGnFileUtils.h" #include "/EgtDev/Include/EGnGetKeyData.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtKeyCodes.h" #include "/EgtDev/Include/SELkKeyProc.h" using namespace std ; //------------------------------ Errors -------------------------------------- // 1001 = "Error with setup : xxx" //---------------------------------------------------------------------------- static const double MIN_STEP = 1.0 ; static const double MID_STEP = 50.0 ; static const double MAX_STEP = 500.0 ; static const double COLL_STEP = 10. ; static const double MAX_COLL_STEP = 100. ; 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 ; //---------------------------------------------------------------------------- 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_nChangeTool = 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 ; if ( ExeGetDebugLevel() >= 1) LOG_INFO( GetEMkLogger(), " * SimulatorMP *") 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() ; // Se appena entrati, verifico abilitazioni if ( m_nStatus == SIS_INITIALIZED) { // Controllo della licenza unsigned int nOpt1, nOpt2 ; int nOptExpDays ; int nRet = GetEGnKeyOptions( KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nOpt1, nOpt2, nOptExpDays) ; if ( ! GetEMkNetHwKey()) nRet = GetKeyOptions( GetEMkKey(), KEY_BASELIB_PROD, KEY_BASELIB_VER, KEY_BASELIB_LEV, nOpt1, nOpt2, nOptExpDays) ; // Verifica della abilitazione bool bMinTime = false ; if ( nOptExpDays >= GetMinDay()) bMinTime = true ; bool bCurrTime = false ; if ( nOptExpDays >= GetCurrDay()) bCurrTime = true ; bool bKey = false ; if ( nRet == KEY_OK) bKey = true ; bool bAdvMach = false ; if ( ( nOpt1 & KEYOPT_EMK_ADV) != 0) bAdvMach = true ; if ( ! bMinTime || ! bCurrTime || ! bKey) { m_pMchMgr->SetLastError( 1000, "NC_OFF") ; std::string sErr = "Warning on Key (MKC/KYO)" ; LOG_ERROR( GetEMkLogger(), sErr.c_str()) ; return false ; } if ( ! bAdvMach) { int nOpId = m_pMchMgr->GetFirstActiveOperation() ; while ( nOpId != GDB_ID_NULL) { int nType = m_pMchMgr->GetOperationType( nOpId) ; if ( nType == OPER_SURFROUGHING || nType == OPER_SURFFINISHING || nType == OPER_FIVEAXISMILLING) { m_pMchMgr->SetLastError( 1001, "ADVANCED_MACH_OFF") ; std::string sErr = "Warning on Key (MKC/AMO)" ; LOG_ERROR( GetEMkLogger(), sErr.c_str()) ; return false ; } nOpId = m_pMchMgr->GetNextActiveOperation( nOpId) ; } } } 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 ; // Eseguo stima speciale string sTemp ; if ( ExeGetCurrFilePath( sTemp)) { // direttorio string sDir = GetDirectory( sTemp) ; ReplaceString( sDir, "/", "\\") ; // nome string sName = GetFileTitleEgt( sTemp) ; // nome macchinata string sMGrp = m_pMchMgr->GetMachGroupName( m_pMchMgr->GetCurrMachGroup()) ; // path completa m_sSpecEstim = sDir + "\\" + sName + "_" + sMGrp + ".sest" ; } else { ExeGetTempDir( sTemp) ; m_sSpecEstim = sTemp + "\\Simul.sest" ; } EraseFile( m_sSpecEstim) ; if ( ! m_pMchMgr->Estimate( m_sSpecEstim, "")) bOk = false ; } // Reset utensile, interpolazione e assi correnti m_sTool.clear() ; m_sHead.clear() ; m_nExit = 0 ; m_dTDiam = 0 ; m_bCutOnTip = false ; m_nChangeTool = 0 ; ResetInterpolation() ; ResetAxes() ; ResetAuxAxes() ; // porto la macchina in home if ( ! GoHome()) bOk = false ; // Verifico la disposizione iniziale della macchinata m_nOpInd = 0 ; m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; 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()) ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MPSIM, true) ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MPSEST, m_sSpecEstim) ; // Se appena entrati in simulazione if ( m_nStatus == SIS_INITIALIZED) { m_vOperId.clear() ; 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, m_nChangeTool, 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 ; if ( ! ExecAllCmdData( 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( 1002, 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() >= 8) { 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 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 appena arrivato alla fine di un percorso di lavoro (verifico anche completamento dei comandi aux di start per path vuote) if ( m_nChangeTool == 0 && 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_nChangeTool == 0 && 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 o appena scaricato utensile if ( m_nCLPathId == GDB_ID_NULL || m_nChangeTool != 0) { // gestione fine operazione if ( m_nChangeTool == 0 && m_nCLPathId == GDB_ID_NULL && ! ManageOperationEnd( nStatus)) return false ; // ricerca e gestione nuova operazione if ( ! FindAndManageOperationStart( false, false, m_nChangeTool, nStatus)) return false ; if ( m_nChangeTool != 0) return true ; // se non ce ne sono altre, sono alla fine if ( m_nOpId == GDB_ID_NULL) { OnProgramEnd() ; ExecAllCmdData( nStatus) ; 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) ; // Se ci sono comandi da eseguire if ( ! m_CmdData.empty()) return true ; // 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::UpdateMachiningTool( bool bFirst, int& nChangeTool, int& nErr) { // Reset stato nErr = ERR_NONE ; // Recupero la lavorazione corrente Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; 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) ; } // 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() && nChangeTool == 0) { // eventuale lancio script per scarico utensile int nCurrErr ; if ( OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) { nChangeTool = 1 ; return true ; } else { nErr = ( nErr != ERR_NONE ? 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) && nChangeTool != 2) { bool bFloating = m_pMachine->IsCurrToolFloating() ; int nCurrErr ; if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, bFloating, nCurrErr)) { nErr = ( nErr != ERR_NONE ? nErr : nCurrErr) ; if ( nCurrErr != ERR_COLLISION) return false ; } nChangeTool = 2 ; return ( nErr == ERR_NONE) ; } nChangeTool = 0 ; 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, false, nCurrErr)) { nErr = ( nErr != ERR_NONE ? nErr : nCurrErr) ; if ( nCurrErr != ERR_COLLISION) return false ; } return ( nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- 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& nChangeTool, int& nStatus) { // verifico parametri if ( ! bStart) bFirst = false ; // recupero la nuova operazione if ( nChangeTool == 0) { if ( bStart) { m_nOpInd = 0 ; m_nOpId = ( m_nOpInd < int( m_vOperId.size()) ? m_vOperId[m_nOpInd] : GDB_ID_NULL) ; } else { ++ m_nOpInd ; m_nOpId = ( m_nOpInd < int( m_vOperId.size()) ? m_vOperId[m_nOpInd] : GDB_ID_NULL) ; } } // 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()) { // aggiorno utensile e assi conseguenti int nErr ; if ( ! UpdateMachiningTool( bFirst, nChangeTool, nErr)) { string sOut = "Err=" + ToString( nErr) ; LOG_INFO( GetEMkLogger(), sOut.c_str()) nStatus = CalcStatusOnError( nErr) ; return false ; } if ( nChangeTool != 0) return true ; // 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( ERR_NONE) ; return false ; } return true ; } // 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 - 1, nPhase, sTable, ptOri1, false, bSomeByHand)) { nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // cambio fase m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; // se previsto, aggiorno utensile e assi conseguenti if ( pDisp->IsWithTool()) { int nErr ; if ( ! UpdateDispositionTool( bFirst, nErr)) { nStatus = CalcStatusOnError( nErr) ; return false ; } } // richiamo gestione evento inizio disposizione if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { nStatus = CalcStatusOnError( ERR_NONE) ; 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 - 1, nPhase, sTable, ptOri1, true, bSomeByHand)) { nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // cambio fase m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; // richiamo gestione evento inizio e fine disposizione if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) || ! OnDispositionEnd()) { nStatus = CalcStatusOnError( ERR_NONE) ; return false ; } // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) if ( nPhase != 1) { ExeDraw() ; Sleep( 200) ; } } } // passo alla operazione successiva ++ m_nOpInd ; m_nOpId = ( m_nOpInd < int( m_vOperId.size()) ? m_vOperId[m_nOpInd] : GDB_ID_NULL) ; //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( ERR_NONE) ; 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 ; // verifico se Path in doppio int nDBLPathId = GDB_ID_NULL ; int nDBLId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_DBL) ; if ( nDBLId != GDB_ID_NULL) { string sCLPathName ; m_pGeomDB->GetName( m_nCLPathId, sCLPathName) ; nDBLPathId = m_pGeomDB->GetFirstNameInGroup( nDBLId, sCLPathName) ; } // 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 eventuale attivazione uscite (gruppi a forare) INTVECTOR vActiveExit ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_DRACEX, vActiveExit) ; // 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, nDBLPathId, m_nAuxSTot, ptStart, ptEnd, vtExtr, ptMin, ptMax, vAxMin, vAxMax, dElev, vActiveExit)) { nStatus = CalcStatusOnError( ERR_NONE) ; 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( ERR_NONE) ; 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) { // Per default movimento nullo dMove = 0 ; // 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() ; if ( ! m_pMchMgr->GetCurrIsRobot()) { 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) ; } else { int nStat ; m_pMachine->VerifyOutstroke( 0, 0, 0, OutAxes, 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() ; // Controllo che il numero di valori corrisponda con quello degli assi int nEndsCnt = int( AxesEnd.size()) ; int nAxesCnt = int( m_AxesName.size()) ; if ( nEndsCnt != nAxesCnt) { nStatus = MCH_SIM_ERR ; m_pMchMgr->SetLastError( 1003, "Error : mismatch between the number of values and of axes") ; string sOut = "Error : " + ToString( nEndsCnt) + " values vs " + ToString( nAxesCnt) + " axes" ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) return false ; } // 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] ; } } // Se comandi in sospeso, esco if ( ! m_CmdData.empty()) { m_dCoeff = 2 * EPS_ZERO ; return true ; } } // 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 RAD_LIM = 20 ; const double ANG_STEP = 5 ; if ( dRad > RAD_LIM && 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) ; // recupero il nome string sCdName ; m_pGeomDB->GetName( m_CdId[i], sCdName) ; // 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 ; // se contiene info con nome da saltare, verifico se è il caso string sCollSkip ; if ( m_pGeomDB->GetInfo( m_CollObj[j].nFrameId, "CollSkip", sCollSkip) && sCollSkip == sCdName) 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) ; // COLLISION* per parti generiche di macchina, BASE e MOBILE per fixtures if ( sCollParName.rfind( "COLLISION", 0) != 0 && sCollParName != "BASE" && sCollParName != "MOBILE") 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::CallFunction( const string& sFun, bool bSetRecord, bool bSetModifiedOff) { // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( sFun)) return true ; // se richiesto, imposto modalità registrazione if ( bSetRecord && ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_RECORD, true)) return false ; // eventuale log di inizio esecuzione if ( ExeGetDebugLevel() >= 6) { string sOut = "** " + sFun ; LOG_INFO( GetEMkLogger(), sOut.c_str()) } // chiamo la funzione bool bOk = m_pMachine->LuaCallFunction( sFun, bSetModifiedOff) ; // se necessario, annullo stato registrazione if ( bSetRecord && ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_RECORD, false)) return false ; // restituisco stato esecuzione return bOk ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnInit( void) { // chiamo la funzione di ingresso nella simulazione bool bOk = CallFunction( ON_SIMUL_INIT) ; // recupero i dati di ritorno bOk = m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_OPERID, m_vOperId) && bOk ; return bOk ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnExit( void) { // chiamo la funzione di uscita dalla simulazione return CallFunction( ON_SIMUL_EXIT) ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnProgramStart( bool bFirst) { // assegno flag inizio simulazione bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIM1ST, bFirst) ; // chiamo la funzione di inizio simulazione bOk = bOk && CallFunction( ON_SIMUL_START) ; return bOk ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnProgramEnd( void) { // chiamo la funzione di fine simulazione return CallFunction( 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) ; // chiamo la funzione di inizio disposizione bOk = bOk && CallFunction( 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) ; // chiamo la funzione di inizio disposizione bOk = bOk && CallFunction( 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) { // chiamo la funzione di fine disposizione bool bOk = CallFunction( 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, bool bFloating, int& nErr) { // reset stato di errore da script nErr = ERR_NONE ; // 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) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TFLOAT, bFloating)) 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 ; // chiamo la funzione di selezione utensile bool bOk = CallFunction( ON_SIMUL_TOOL_SELECT, true) ; // 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 eventuali dati di ritorno per assi ausiliari bOk = ReadAuxAxesData( nErr) && bOk ; return ( bOk && nErr == ERR_NONE) ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos, int& nErr) { // reset stato di errore da script nErr = ERR_NONE ; // 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 && CallFunction( ON_SIMUL_TOOL_DESELECT, true) ; // 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 == ERR_NONE) ; } //---------------------------------------------------------------------------- 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 ; // chiamo la funzione di inizio lavorazione bool bOk = CallFunction( ON_SIMUL_MACHINING_START, true) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnMachiningEnd( void) { // chiamo la funzione di fine lavorazione bool bOk = CallFunction( ON_SIMUL_MACHINING_END, true) ; // reset eventuale Path in double bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_DBLPATHID) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnPathStart( int nClPathId, int nClPathInd, int nDBLPathId, 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, const INTVECTOR& vActiveExit) { // 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 identificativo percorso di lavorazione in doppio if ( nDBLPathId == GDB_ID_NULL) bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_DBLPATHID) ; else bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DBLPATHID, nDBLPathId) ; // 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) ; // assegno uscite attive per gruppi a forare bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DRACEX, vActiveExit) ; // chiamo la funzione di inizio percorso di lavorazione bOk = bOk && CallFunction( ON_SIMUL_PATH_START, true) ; // 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) ; // chiamo la funzione di fine percorso di lavorazione bOk = bOk && CallFunction( ON_SIMUL_PATH_END, true) ; // 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 = ERR_NONE ; // 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 && CallFunction( ON_SIMUL_PATH_START_AUX, true) ; // 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 == ERR_NONE) ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnPathEndAux( int nInd, const string& sAE, int& nErr) { // reset stato di errore da script nErr = ERR_NONE ; // 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 && CallFunction( ON_SIMUL_PATH_END_AUX, true) ; // 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 == ERR_NONE) ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr) { // reset stato di errore da script nErr = ERR_NONE ; // 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) ; // chiamo la funzione bOk = bOk && CallFunction( ON_SIMUL_MOVE_START, true) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; // reset assi ausiliari ResetAuxAxes() ; // verifico codice di errore bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; // con errore, esco if ( ! bOk || nErr != ERR_NONE) return false ; // 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 j = 0 ; nInd == 0 && j < ssize( m_AxesName) ; ++ j) { if ( m_AxesName[j] == sMainAxis) nInd = j + 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 = ERR_OUTSTROKE ; bOk = false ; } } } // altrimenti errore else { bOk = false ; string sErr = " Error in OnMoveStart : Wrong Move AuxAxis " + ToString( i) ; LOG_ERROR( GetEMkLogger(), sErr.c_str()) } } else { bOk = false ; string sErr = " Error in OnMoveStart : Wrong Name AuxAxis " + ToString( i) ; LOG_ERROR( GetEMkLogger(), sErr.c_str()) } } return bOk ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnMoveEnd( int& nErr) { // reset stato di errore da script nErr = ERR_NONE ; // reset errore if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) return false ; // chiamo la funzione bool bOk = CallFunction( ON_SIMUL_MOVE_END, true) ; // 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 == ERR_NONE) ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnCollision( int nCdInd, int nObjInd, int& nErr) { // reset stato di errore da script nErr = ERR_NONE ; // 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 ( ! CallFunction( 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 == ERR_NONE) ; } //---------------------------------------------------------------------------- bool SimulatorMP::OnResetMachine( void) { // eseguo reset macchina return CallFunction( ON_RESET_MACHINE) ; } //---------------------------------------------------------------------------- bool SimulatorMP::ReadAuxAxesData( int& nErr) { bool bOk = true ; // 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 == ERR_NONE) ; 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 == ERR_NONE) ; } //---------------------------------------------------------------------------- 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::RemoveCollisionObj( int nFrameId) { erase_if( m_CollObj, [nFrameId]( CollObj Item) { return ( Item.nFrameId == nFrameId) ; }) ; return true ; } //---------------------------------------------------------------------------- bool SimulatorMP::GetCollisionObj( int nPos, int& nInd, bool& bToolOn, int& nFrameId, int& nType, Vector3d& vtMove, double& dPar1, double& dPar2, double& dPar3) { // posizione nel vettore non valida if ( nPos < 0 || nPos >= ssize( m_CollObj)) return false ; // assegno i dati nInd = m_CollObj[nPos].nInd ; bToolOn = m_CollObj[nPos].bToolOn ; nFrameId = m_CollObj[nPos].nFrameId ; nType = m_CollObj[nPos].nType ; vtMove = m_CollObj[nPos].vtMove ; dPar1 = m_CollObj[nPos].dPar1 ; dPar2 = m_CollObj[nPos].dPar2 ; dPar3 = m_CollObj[nPos].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) ; // verifico se additivo bool bAdditive = ( nFlag == 1) ; // se flottante, il primo parametro è l'offset di lunghezza if ( nFlag == 2) dLen += dPar1 ; // 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( nMoveType, vAxNaEpSt) ; // Log dati if ( ExeGetDebugLevel() >= 6) { 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::SaveCmd( int nType, int nPar, const string& sPar, const string& sPar2) { // Salvo il comando m_CmdData.emplace_back( nType, nPar, sPar, sPar2) ; // Log dati if ( ExeGetDebugLevel() >= 6) { string sOut = "Save=SimulCmd," + ToString( nType) + "," + ToString( nPar) + "," + sPar ; if ( ! IsEmptyOrSpaces( sPar2)) sOut += "," + sPar2 ; LOG_INFO( GetEMkLogger(), sOut.c_str()) } return false ; } //---------------------------------------------------------------------------- bool SimulatorMP::ExecCmdData( int& nStatus) { // Comando corrente auto& CmdCurr = m_CmdData[m_nCmdInd] ; // Stampe di debug if ( ExeGetDebugLevel() >= 6) { if ( CmdCurr.nType == 1) { if ( m_dCmdCoeff < EPS_ZERO) { string sOut = "Exec=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()) } } else { string sOut = "Exec=SimulCmd," + ToString( CmdCurr.nType) + "," + ToString( CmdCurr.nPar) + "," + CmdCurr.sPar ; if ( ! IsEmptyOrSpaces( CmdCurr.sPar2)) sOut += "," + CmdCurr.sPar2 ; LOG_INFO( GetEMkLogger(), sOut.c_str()) } } // Eseguo movimento assi 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 ; double dMaxStep = ( NeedCollisionCheck() ? MAX_COLL_STEP : MAX_STEP) ; 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 = Clamp( dStep, MIN_STEP, dMaxStep) ; 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 ; } } // 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 assegnazione di variabile globale else if ( CmdCurr.nType == 4) { bool bOk = false ; switch ( CmdCurr.nPar) { case 0 : bOk = m_pMachine->LuaResetGlobVar( CmdCurr.sPar) ; break ; case 1 : { bool bVal = ( CmdCurr.sPar2 == "1") ; bOk = m_pMachine->LuaSetGlobVar( CmdCurr.sPar, bVal) ; } break ; case 2 : { int nVal = 0 ; FromString( CmdCurr.sPar2, nVal) ; bOk = m_pMachine->LuaSetGlobVar( CmdCurr.sPar, nVal) ; } break ; case 3 : { double dVal = 0 ; FromString( CmdCurr.sPar2, dVal) ; bOk = m_pMachine->LuaSetGlobVar( CmdCurr.sPar, dVal) ; } break ; case 4 : bOk = m_pMachine->LuaSetGlobVar( CmdCurr.sPar, CmdCurr.sPar2) ; break ; } if ( ! bOk) { 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 ; } // recupero dati per verifica collisione m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SAFEDIST, m_dSafeDist) ; m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; // recupero eventuali dati di ritorno per assi ausiliari int nErr = ERR_NONE ; if ( ! ReadAuxAxesData( nErr)) { nStatus = MCH_SIM_ERR ; return false ; } // Aggiorno indice comandi eseguiti m_nCmdInd += 1 ; m_dCmdCoeff = 0 ; } // altrimenti errore else { nStatus = MCH_SIM_ERR ; LOG_DBG_INFO( GetEMkLogger(), " --> ExecCmdData nType Error <--") return false ; } 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 ; }