//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : Simulator.cpp Data : 04.01.17 Versione : 1.6x5 // Contenuto : Implementazione della classe Simulator. // // // // Modifiche : 19.10.15 DS Creazione modulo. // 26.02.16 DS Aggiunta gestione archi. // 04.01.17 DS Riorganizzazione codice. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Simulator.h" #include "MachMgr.h" #include "Disposition.h" #include "Machining.h" #include "MachiningConst.h" #include "OutputConst.h" #include "DllMain.h" #include "/EgtDev/Include/EGkCDeBoxClosedSurfTm.h" #include "/EgtDev/Include/EGkCDeCylClosedSurfTm.h" #include "/EgtDev/Include/EGkCDeSpheClosedSurfTm.h" #include "/EgtDev/Include/EGkVolZmap.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EXeConst.h" #include "/EgtDev/Include/EMkToolConst.h" #include "/EgtDev/Include/EMkOperationConst.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EgtNumUtils.h" using namespace std ; //------------------------------ Errors -------------------------------------- // 1001 = "Error with setup : xxx" //---------------------------------------------------------------------------- static const double MIN_STEP = 1.0 ; static const double MAX_STEP = 100.0 ; static const double MID_STEP = 50.0 ; static const double COEFF_LIM = 0.999 ; static const double SAFEDIST_STD = 5.0 ; //---------------------------------------------------------------------------- Simulator::Simulator( void) { m_pMchMgr = nullptr ; m_pGeomDB = nullptr ; m_pMachine = nullptr ; m_pPerfCnt = nullptr ; m_dStep = MID_STEP ; m_nUiStatus = MCH_UISIM_NULL ; m_nOpId = GDB_ID_NULL ; m_nOpInd = 0 ; m_nCLPathId = GDB_ID_NULL ; m_nCLPathInd = 0 ; m_nEntId = GDB_ID_NULL ; m_nEntInd = 0 ; m_dCoeff = 0 ; m_nAuxSTot = 0 ; m_nAuxSInd = 0 ; m_nAuxETot = 0 ; m_nAuxEInd = 0 ; m_nExit = 0 ; m_dTDiam = 0 ; m_dVmTdOffs = 0 ; m_dVmAdOffs = 0 ; m_dSafeDist = SAFEDIST_STD ; m_bEnabAxes = true ; m_bShowAxes = true ; m_AxesName.reserve( 8) ; m_AxesToken.reserve( 8) ; m_AxesLinear.reserve( 8) ; m_AxesVal.reserve( 8) ; } //---------------------------------------------------------------------------- Simulator::~Simulator( void) { // porto la macchina in posizione home GoHome() ; // rimuovo tavola variabili globali m_pMachine->LuaResetGlobVar( GLOB_VAR) ; // rimuovo performance counter if ( m_pPerfCnt != nullptr) { delete m_pPerfCnt ; m_pPerfCnt = nullptr ; } } //---------------------------------------------------------------------------- bool Simulator::Init( MachMgr* pMchMgr) { // verifico ambiente if ( pMchMgr == nullptr || pMchMgr->GetContextId() == 0 || pMchMgr->GetGeomDB() == nullptr || pMchMgr->GetCurrMachine() == nullptr) return false ; m_pMchMgr = pMchMgr ; m_pGeomDB = m_pMchMgr->GetGeomDB() ; m_pMachine = m_pMchMgr->GetCurrMachine() ; m_pPerfCnt = new PerformanceCounter ; return true ; } //---------------------------------------------------------------------------- bool Simulator::Start( bool bFirst) { // Verifico ci sia una macchinata corrente if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr || m_pMachine == nullptr || m_pMchMgr->GetCurrMachGroup() == GDB_ID_NULL) return false ; m_pMchMgr->ResetLastError() ; m_pMchMgr->ResetWarnings() ; // Forzo aggiornamento attrezzaggio della macchinata bool bOk = m_pMchMgr->UpdateCurrSetup() ; // Se avvio vero, verifico attrezzaggio if ( bFirst && ! VerifySetup()) bOk = false ; // Reset utensile, interpolazione e assi correnti m_sTool.clear() ; m_sHead.clear() ; m_nExit = 0 ; m_dTDiam = 0 ; ResetInterpolation() ; ResetAxes() ; ResetAuxAxes() ; // porto la macchina in home if ( ! GoHome()) bOk = false ; // Verifico la disposizione iniziale della macchinata m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; m_nOpInd = 1 ; if ( m_pMchMgr->GetOperationType( m_nOpId) != OPER_DISP) bOk = false ; // Definisco tabella variabili globali if ( ! m_pMachine->LuaCreateGlobTable( GLOB_VAR)) bOk = false ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INCHES, ! ExeUiUnitsAreMM()) ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_VER, GetEMkVer()) ; // Richiamo funzione su avvio simulazione if ( ! OnStart( bFirst)) bOk = false ; // Arrivo alla preparazione per la prima lavorazione int nStatus ; if ( ! FindAndManageOperationStart( true, bFirst, nStatus)) bOk = false ; // Reset timer if ( m_pPerfCnt != nullptr) m_pPerfCnt->Start() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::VerifySetup( void) { // se attrezzaggio non definito, nulla da verificare if ( ! m_pMchMgr->GetCurrSetupMgr().Exists()) return true ; // lancio la verifica STRVECTOR vsErr ; if ( m_pMchMgr->VerifyCurrSetup( vsErr)) return true ; // gestisco errore string sErr = "Error with setup :" ; for ( const auto& sTmp : vsErr) sErr += " " + sTmp ; m_pMchMgr->SetLastError( 1001, sErr) ; return false ; } //---------------------------------------------------------------------------- bool Simulator::ResetInterpolation( void) { m_nOpId = GDB_ID_NULL ; m_nOpInd = 0 ; m_nCLPathId = GDB_ID_NULL ; m_nCLPathInd = 0 ; m_nEntId = GDB_ID_NULL ; m_nEntInd = 0 ; m_dCoeff = 0 ; m_nAuxSTot = 0 ; m_nAuxSInd = 0 ; m_nAuxETot = 0 ; m_nAuxEInd = 0 ; m_VmId.clear() ; m_CdId.clear() ; m_dVmTdOffs = 0 ; m_dVmAdOffs = 0 ; m_dSafeDist = SAFEDIST_STD ; m_bEnabAxes = true ; m_bShowAxes = true ; return true ; } //---------------------------------------------------------------------------- bool Simulator::Move( int& nStatus) { // Verifiche if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr) { nStatus = MCH_SIM_ERR ; return false ; } // Recupero tempo impiegato (calcolo + visualizzazione precedenti) if ( m_pPerfCnt != nullptr && ExeGetDebugLevel() >= 5) { double dElapsed = m_pPerfCnt->Stop() ; string sOut = "Elapsed=" + ToString( dElapsed, 1) ; LOG_DBG_INFO( GetEMkLogger(), sOut.c_str()) m_pPerfCnt->Start() ; } // Se arrivato alla fine dell'interpolazione if ( m_dCoeff > COEFF_LIM) { // recupero una nuova entità m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; m_dCoeff = 0 ; } // Se appena arrivato alla fine di un percorso di lavoro if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd == 0 && m_nCLPathInd > 0) { // gestione fine percorso di lavoro if ( ! ManagePathEnd( nStatus)) return false ; } // Se alla fine del percorso dopo esecuzione azioni ausiliarie if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd >= m_nAuxETot) { // ricerca e gestione inizio percorso di lavoro if ( ! FindAndManagePathStart( nStatus)) return false ; } // Se arrivato alla fine di una operazione if ( m_nCLPathId == GDB_ID_NULL) { // gestione fine operazione if ( ! ManageOperationEnd( nStatus)) return false ; // ricerca e gestione nuova operazione if ( ! FindAndManageOperationStart( false, false, nStatus)) return false ; // se non ce ne sono altre, sono alla fine if ( m_nOpId == GDB_ID_NULL) { OnEnd() ; nStatus = MCH_SIM_END ; return false ; } // ricerca e gestione inizio percorso di lavoro if ( ! FindAndManagePathStart( nStatus)) return false ; } // Se sto eseguendo i movimenti ausiliari di inizio percorso if ( m_nAuxSInd < m_nAuxSTot) return ManagePathStartAux( nStatus) ; // Se sto eseguendo i movimenti ausiliari di fine percorso if ( m_nAuxEInd < m_nAuxETot) return ManagePathEndAux( nStatus) ; // Gestione movimento assi return ManageMove( nStatus) ; } //---------------------------------------------------------------------------- bool Simulator::GetAxisInfoPos( int nI, string& sName, string& sToken, bool& bLinear, double& dVal) const { // Verifiche if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // numero assi di calcolo e ausiliari int nAxisCount = ( m_bShowAxes ? int( m_AxesName.size()) : 0) ; int nAuxAxisCount = int( m_AuxAxesName.size()) ; // recupero i dati dell'asse if ( nI < 0 || nI >= nAxisCount + nAuxAxisCount) return false ; // se asse principale if ( nI < nAxisCount) { sName = m_AxesName[nI] ; sToken = m_AxesToken[nI] ; bLinear = m_AxesLinear[nI] ; } // altrimenti asse ausiliario else { sName = m_AuxAxesName[ nI - nAxisCount] ; sToken = m_AuxAxesToken[ nI - nAxisCount] ; bLinear = m_AuxAxesLinear[ nI - nAxisCount] ; } // recupero la posizione if ( ! m_pMchMgr->GetAxisPos( sName, dVal)) return false ; // verifico se da invertire if ( nI < nAxisCount) { if ( m_AxesInvert[nI]) dVal = - dVal ; } else { if ( m_AuxAxesInvert[nI - nAxisCount]) dVal = - dVal ; } return true ; } //---------------------------------------------------------------------------- bool Simulator::GetToolInfo( string& sName, double& dSpeed) const { // Inizializzo i parametri di ritorno sName.clear() ; dSpeed = 0 ; // Verifiche if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // Assegno il nome dell'utensile sName = m_sTool ; if ( sName.empty()) return true ; // Recupero speed const Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; return ( pMch != nullptr && pMch->GetParam( MPA_SPEED, dSpeed)) ; } //---------------------------------------------------------------------------- bool Simulator::GetOperationInfo( string& sName, int& nType) const { // Inizializzo i parametri di ritorno sName.clear() ; nType = OPER_NULL ; // Verifiche if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // Recupero il tipo Operation* pOpe = GetOperation( m_pGeomDB->GetUserObj( m_nOpId)) ; if ( pOpe == nullptr) return false ; nType = pOpe->GetType() ; // Recupero il nome return m_pGeomDB->GetName( m_nOpId, sName) ; } //---------------------------------------------------------------------------- bool Simulator::GetMoveInfo( int& nGmove, double& dFeed) const { // Verifiche if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr) return false ; // Recupero il movimento corrente const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; if ( pCamData == nullptr) return false ; // Assegno feed dFeed = pCamData->GetFeed() ; // Assegno tipo di movimento nGmove = pCamData->GetMoveType() ; return true ; } //---------------------------------------------------------------------------- bool Simulator::SetStep( double dStep) { m_dStep = Clamp( dStep, MIN_STEP, MAX_STEP) ; // imposto step per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ; return true ; } //---------------------------------------------------------------------------- bool Simulator::SetUiStatus( int nUiStatus) { m_nUiStatus = nUiStatus ; // imposto stato utente del simulatore per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale) m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMUISTAT, m_nUiStatus) ; return true ; } //---------------------------------------------------------------------------- bool Simulator::GoHome( void) { // controllo validità stato if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr) return false ; // reset stato macchina OnResetMachine() ; // porto la macchina in home m_pMchMgr->ResetAllAxesPos() ; // assegno valori home degli assi macchina attivi return m_pMchMgr->GetAllCurrAxesHomePos( m_AxesVal) ; } //---------------------------------------------------------------------------- bool Simulator::UpdateTool( bool bFirst) { // Recupero l'utensile della lavorazione corrente Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; if ( pMch != nullptr) { // recupero nome e dati nuovo utensile string sTuuid, sTool ; if ( ! pMch->GetParam( MPA_TUUID, sTuuid) || ! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool)) return false ; string sTcPos ; string sHead ; int nExit ; if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) { if ( m_pMchMgr->TdbSetCurrTool( sTool)) { m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ; m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ; m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ; } // ripristino l'utensile corrente m_pMchMgr->TdbSetCurrTool( m_sTool) ; } // se cambierà ed esiste il corrente, lo scarico if ( sTool != m_sTool && ! m_sTool.empty()) { // eventuale lancio script per scarico utensile if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos)) return false ; } // se cambiato oppure prima volta, attivo l'utensile della lavorazione if ( sTool != m_sTool || bFirst) { // se prima volta, pulisco la testa if ( bFirst) m_pMchMgr->ResetHeadSet( sHead) ; // 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) ; // aggiorno gli assi macchina if ( ! UpdateAxes()) return false ; // eventuali offset per Vmill (per adattare lo ZeroT macchina con quello di Zmap) int nToolType ; m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nToolType) ; if ( nToolType == TT_MORTISE_STD) { double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; m_dVmTdOffs = 0 ; m_dVmAdOffs = 0.5 * dThick ; } else if ( nToolType == TT_SAW_STD || nToolType == TT_SAW_FLAT) { double dLen ; m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, dLen) ; double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ; m_dVmTdOffs = ( ( dLen <= dThick) ? -dLen + dThick : 0) ; m_dVmAdOffs = 0 ; } else { m_dVmTdOffs = 0 ; m_dVmAdOffs = 0 ; } // eventuale lancio script if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst)) return false ; } return true ; } // Provo con una disposizione Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; if ( pDisp != nullptr) { // recupero i dati string sTool ; string sHead ; int nExit ; string sTcPos ; pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ; // se esiste utensile corrente e cambierà, lo scarico if ( ! m_sTool.empty() && sTool != m_sTool) { // eventuale lancio script per scarico utensile if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos)) 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) ; // aggiorno gli assi macchina if ( ! UpdateAxes()) return false ; // eventuale lancio script if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst)) return false ; return true ; } return false ; } //---------------------------------------------------------------------------- bool Simulator::UpdateAxes( void) { ResetAxes() ; // Macchina corrente Machine* pMachine = m_pMchMgr->GetCurrMachine() ; if ( pMachine == nullptr) return false ; // Carico i nomi e i token degli assi macchina attivi if ( ! pMachine->GetAllCurrAxesName( m_AxesName) || ! pMachine->GetAllCurrAxesToken( m_AxesToken)) return false ; // Aggiorno flag invertito, il tipo e la 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) ; bool bLinear ; m_pMachine->GetAxisType( m_AxesName[i], bLinear) ; m_AxesLinear.push_back( bLinear) ; double dVal ; m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; m_AxesVal.emplace_back( dVal) ; } return true ; } //---------------------------------------------------------------------------- bool Simulator::UpdateAxesPos( void) { // Macchina corrente Machine* pMachine = m_pMchMgr->GetCurrMachine() ; if ( pMachine == nullptr) return false ; // Aggiorno la posizione corrente degli assi macchina attivi m_AxesVal.clear() ; for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { double dVal ; m_pMachine->GetAxisPos( m_AxesName[i], dVal) ; m_AxesVal.emplace_back( dVal) ; } return true ; } //---------------------------------------------------------------------------- bool Simulator::ResetAxes( void) { // pulisco dati assi m_AxesName.clear() ; m_AxesToken.clear() ; m_AxesInvert.clear() ; m_AxesLinear.clear() ; m_AxesVal.clear() ; return true ; } //---------------------------------------------------------------------------- bool Simulator::ResetAuxAxes( void) { // pulisco dati assi ausiliari m_AuxAxesName.clear() ; m_AuxAxesToken.clear() ; m_AuxAxesInvert.clear() ; m_AuxAxesLinear.clear() ; m_AuxAxesVal.clear() ; m_AuxAxesEnd.clear() ; // abilito assi principali m_bEnabAxes = true ; m_bShowAxes = true ; return true ; } //---------------------------------------------------------------------------- bool Simulator::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus) { // verifico parametri if ( ! bStart) bFirst = false ; // recupero la nuova operazione if ( bStart) { m_nOpId = m_pMchMgr->GetFirstActiveOperation() ; m_nOpInd = 0 ; } else m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; // ciclo sulle successive operazioni while ( m_nOpId != GDB_ID_NULL) { // se lavorazione valida Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ; if ( pMch != nullptr && ! pMch->IsEmpty()) { // aggiorno utensile e assi conseguenti if ( ! UpdateTool( bFirst)) { nStatus = CalcStatusOnError( 0) ; return false ; } ++ m_nOpInd ; // imposto la lavorazione come corrente m_pMchMgr->SetCurrMachining( m_nOpId) ; // recupero punti di minimo e massimo ingombro int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; Point3d ptMin, ptMax ; m_pGeomDB->GetInfo( nClId, KEY_MMIN, ptMin) ; m_pGeomDB->GetInfo( nClId, KEY_MMAX, ptMax) ; DBLVECTOR vAxMin, vAxMax ; m_pGeomDB->GetInfo( nClId, KEY_MAXMIN, vAxMin) ; m_pGeomDB->GetInfo( nClId, KEY_MAXMAX, vAxMax) ; // richiamo gestione evento inizio lavorazione if ( ! OnMachiningStart( m_nOpId, m_nOpInd, ptMin, ptMax, vAxMin, vAxMax)) { nStatus = CalcStatusOnError( 0) ; return false ; } break ; } // se disposizione con cambio di fase Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ; if ( pDisp != nullptr) { // in alcuni casi la disposizione non è inizializzata pDisp->Init( m_pMchMgr) ; // recupero dati tavola string sTable ; pDisp->GetTable( sTable) ; Point3d ptOri1 ; pDisp->GetTableRef1( ptOri1) ; // recupero la fase della disposizione int nPhase = pDisp->GetPhase() ; // recupero se con movimenti autonomi bool bEmpty = pDisp->IsEmpty() ; // recupero flag disposizione con movimenti manuali bool bSomeByHand = pDisp->GetSomeByHand() ; // se con movimenti autonomi if ( ! bEmpty) { // richiamo gestione evento appena prima di inizio disposizione if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { nStatus = CalcStatusOnError( 0) ; return false ; } // cambio fase m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; // aggiorno utensile e assi conseguenti if ( ! UpdateTool( bFirst)) { nStatus = CalcStatusOnError( 0) ; return false ; } ++ m_nOpInd ; // richiamo gestione evento inizio disposizione if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) { nStatus = CalcStatusOnError( 0) ; return false ; } // se ci sono movimenti manuali, aggiorno visualizzazione e breve pausa (200 ms) if ( bSomeByHand) Sleep( 200) ; break ; } // altrimenti disposizione passiva else { // richiamo gestione evento appena prima di inizio disposizione if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand)) { nStatus = CalcStatusOnError( 0) ; return false ; } // cambio fase m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ; ++ m_nOpInd ; // richiamo gestione evento inizio e fine disposizione if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) || ! OnDispositionEnd()) { nStatus = CalcStatusOnError( 0) ; return false ; } // se non è inizio, aggiorno visualizzazione e breve pausa (200 ms) if ( nPhase != 1) { ExeDraw() ; Sleep( 200) ; } } } // passo alla operazione successiva m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ; } return true ; } //---------------------------------------------------------------------------- bool Simulator::ManageOperationEnd( int& nStatus) { bool bOk = false ; // non c'è operazione in corso (solo prima disposizione senza lavorazioni) if ( m_nOpId == GDB_ID_NULL) bOk = true ; // se altrimenti è una lavorazione else if ( GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { // richiamo gestione evento fine lavorazione bOk = OnMachiningEnd() ; } // se altrimenti è una disposizione else if ( GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) { // richiamo gestione evento fine disposizione bOk = OnDispositionEnd() ; } // gestione stato if ( ! bOk) nStatus = CalcStatusOnError( 0) ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::FindAndManagePathStart( int& nStatus) { // se devo cercare il primo nella nuova operazione if ( m_nCLPathId == GDB_ID_NULL) { // aggiorno gli altri dati int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ; m_nCLPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ; m_nCLPathInd = 0 ; m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; m_nEntInd = 0 ; m_dCoeff = 0 ; } // altrimenti cerco il successivo nella stessa operazione else { // recupero un nuovo CLpath while ( m_nEntId == GDB_ID_NULL) { m_nCLPathId = m_pGeomDB->GetNextGroup( m_nCLPathId) ; // se non ce ne sono altri, devo passare a una nuova lavorazione if ( m_nCLPathId == GDB_ID_NULL) break ; m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ; m_nEntInd = 0 ; m_dCoeff = 0 ; } } // se trovato nuovo CLpath con entità, gestisco inizio percorso di lavoro if ( m_nEntId != GDB_ID_NULL) { ++ m_nCLPathInd ; // recupero punti di inizio e fine percorso Point3d ptStart ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_START, ptStart) ; Point3d ptEnd ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_END, ptEnd) ; // recupero versore estrusione associato al percorso (normale al piano di interpolazione) Vector3d vtExtr ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_EXTR, vtExtr) ; // recupero punti di minimo e massimo ingombro Point3d ptMin, ptMax ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMIN, ptMin) ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_PMAX, ptMax) ; // Recupero valori degli assi di minimo e massimo ingombro DBLVECTOR vAxMin, vAxMax ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMIN, vAxMin) ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_PAXMAX, vAxMax) ; // recupero massima elevazione double dElev = 0 ; m_pGeomDB->GetInfo( m_nCLPathId, KEY_ELEV, dElev) ; // recupero il numero di eventi ausiliari di inizio if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot)) m_nAuxSTot = 0 ; m_nAuxSInd = 0 ; // reset numero eventi ausiliari di fine m_nAuxEInd = 0 ; m_nAuxETot = 0 ; // richiamo gestione evento inizio percorso di lavoro if ( ! OnPathStart( m_nCLPathId, m_nCLPathInd, m_nAuxSTot, ptStart, ptEnd, vtExtr, ptMin, ptMax, vAxMin, vAxMax, dElev)) { nStatus = CalcStatusOnError( 0) ; return false ; } } // se altrimenti trovato nuovo CL path vuoto else if ( m_nCLPathId != GDB_ID_NULL) { // non ci possono essere eventi ausiliari di inizio m_nAuxSTot = 0 ; m_nAuxSInd = 0 ; // recupero il numero di eventi ausiliari di fine if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) m_nAuxETot = 0 ; m_nAuxEInd = 0 ; } return true ; } //---------------------------------------------------------------------------- bool Simulator::ManagePathEnd( int& nStatus) { // recupero il numero di eventi ausiliari di fine if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot)) m_nAuxETot = 0 ; m_nAuxEInd = 0 ; // richiamo gestione evento fine percorso di lavoro bool bOk = OnPathEnd( m_nAuxETot) ; // gestione stato if ( ! bOk) nStatus = CalcStatusOnError( 0) ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::ManagePathStartAux( int& nStatus) { // aggiorno indice corrente ++ m_nAuxSInd ; // recupero i dati per l'evento corrente string sAS ; if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS + ToString( m_nAuxSInd), sAS)) { nStatus = MCH_SIM_ERR ; return false ; } // richiamo gestione evento ausiliario prima di inizio percorso di lavoro int nErr ; if ( ! OnPathStartAux( m_nAuxSInd, sAS, nErr)) { nStatus = CalcStatusOnError( nErr) ; return false ; } nStatus = MCH_SIM_END_STEP ; return true ; } //---------------------------------------------------------------------------- bool Simulator::ManagePathEndAux( int& nStatus) { // aggiorno indice corrente ++ m_nAuxEInd ; // recupero i dati per l'evento corrente string sAE ; if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE + ToString( m_nAuxEInd), sAE)) { nStatus = MCH_SIM_ERR ; return false ; } // richiamo gestione evento ausiliario dopo fine percorso di lavoro int nErr ; if ( ! OnPathEndAux( m_nAuxEInd, sAE, nErr)) { nStatus = CalcStatusOnError( nErr) ; return false ; } nStatus = MCH_SIM_END_STEP ; return true ; } //---------------------------------------------------------------------------- bool Simulator::ManageMove( int& nStatus) { // Imposto lunghezza di movimento effettuata double dCurrMove = 0 ; while ( m_nEntId != GDB_ID_NULL) { // eseguo movimento singolo double dMove ; if ( ! ManageSingleMove( nStatus, dMove)) return false ; dCurrMove += dMove ; // se modalità play e fine entità e non raggiunta la lunghezza di movimento voluto if ( m_nUiStatus == MCH_UISIM_PLAY && nStatus == MCH_SIM_END_STEP && dCurrMove < 0.75 * m_dStep) { // recupero una nuova entità m_nEntId = m_pGeomDB->GetNext( m_nEntId) ; m_dCoeff = 0 ; } else break ; } return true ; } //---------------------------------------------------------------------------- bool Simulator::ManageSingleMove( int& nStatus, double& dMove) { // Recupero posizione finale const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ; if ( pCamData == nullptr) { nStatus = MCH_SIM_ERR ; return false ; } switch ( pCamData->GetAxesStatus()) { case CamData::AS_OK : break ; case CamData::AS_OUTSTROKE : { DBLVECTOR OutAxes = pCamData->GetAxesVal() ; for ( size_t i = OutAxes.size() ; i < 5 ; ++ i) OutAxes.emplace_back( 0) ; DBLVECTOR vAng( OutAxes.begin() + 3, OutAxes.end()) ; int nStat ; m_pMachine->VerifyOutstroke( OutAxes[0], OutAxes[1], OutAxes[2], vAng, true, nStat) ; nStatus = MCH_SIM_OUTSTROKE ; return false ; } case CamData::AS_DIR_ERR : nStatus = MCH_SIM_DIR_ERR ; return false ; default : nStatus = MCH_SIM_ERR ; return false ; } DBLVECTOR AxesEnd = pCamData->GetAxesVal() ; // Tipo di movimento int nMoveType = pCamData->GetMoveType() ; // Se movimento in rapido muovo solo gli assi abilitati dal mask if ( nMoveType == 0) { for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) { if ( ( pCamData->GetAxesMask() & 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 ; int nErr ; if ( ! OnMoveStart( pCamData, 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 ( ( pCamData->GetAxesMask() & 1 << i) == 0) AxesEnd[i] = m_AxesVal[i] ; } } } // Dati per eventuale verifica di collisione int nCdInd, nObjInd ; bool bCollCheck = true ; 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 (primi 3) e rotanti (altri) double dSqCoeff = (( i < 3) ? 1 : 100) ; dSqDist += dSqCoeff * ( AxesEnd[i] - m_AxesVal[i]) * ( AxesEnd[i] - m_AxesVal[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 = int( max( dDist / dStep, 1.)) ; m_dCoeff += 1. / nStep ; if ( m_dCoeff > 1) m_dCoeff = 1 ; } else m_dCoeff = 1 ; dMove = ( m_dCoeff - dPrevCoeff) * dDist ; // Posizione e direzione attuali dell'utensile e riferimento attuale del pezzo (per Vmill) Point3d ptNoseI ; Vector3d vtDirI ; Vector3d vtAuxI ; bool bOkI = GetHeadCurrPosDirAux( ptNoseI, vtDirI, vtAuxI) ; 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 ; // Eseguo movimento rapido o lineare if ( nMoveType != 2 && nMoveType != 3) { // se attivo CollisionCheck approssimo movimento con più step int nStep = 1 ; if ( NeedCollisionCheck()) { const double LEN_STEP = 20. ; nStep = max( int( dDist / LEN_STEP), 1) ; } for ( int i = 1 ; i <= nStep ; ++ i) { double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; // assegno posizioni finali for ( int j = 0 ; j < int( m_AxesName.size()) ; ++ j) { double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; } // muovo eventuali assi ausiliari for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { double dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; } // eseguo eventuale collision check bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd) ; } // eseguo eventuale Vmill Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; bool bOkF = GetHeadCurrPosDirAux( ptNoseF, vtDirF, vtAuxF) ; for ( int j = 0 ; j < int( m_VmId.size()) ; ++ j) { Frame3d frVzmF ; bOkF = m_pGeomDB->GetGlobFrame( m_VmId[j], frVzmF) && bOkF ; ExecLineVmill( m_VmId[j], ptNoseI, vtDirI, vtAuxI, vFrVzmI[j], ptNoseF, vtDirF, vtAuxF, frVzmF) ; } } // Eseguo movimento su arco else { // dati dell'arco Point3d ptCen = pCamData->GetAxesCen() ; double dAngCen = pCamData->GetAxesAngCen() ; double dRad = pCamData->GetAxesRad() ; Vector3d vtN = pCamData->GetAxesNormDir() ; double dDeltaN = ( Point3d( AxesEnd[0], AxesEnd[1], AxesEnd[2]) - ptCen) * vtN ; double dDiffAng = ( m_dCoeff - dPrevCoeff) * dAngCen ; Vector3d vtRot = Point3d( m_AxesVal[0], m_AxesVal[1], m_AxesVal[2]) - ptCen ; vtRot.Rotate( vtN, dPrevCoeff * dAngCen) ; // se attivi Vmill o CollisionCheck approssimo movimento con più step int nStep = 1 ; if ( ! m_VmId.empty() || NeedCollisionCheck()) { const double MIN_LEN_STEP = 2. ; const double MAX_LEN_STEP = 10. ; double dLenStep = Clamp( 0.1 * m_dTDiam, MIN_LEN_STEP, MAX_LEN_STEP) ; nStep = max( int( abs( dDiffAng * DEGTORAD * dRad) / dLenStep), 1) ; const double ANG_STEP = 5. ; if ( abs( dDiffAng) / nStep > ANG_STEP) nStep = int( abs( dDiffAng) / ANG_STEP) ; } for ( int i = 1 ; i <= nStep ; ++ i) { double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ; // assi lineari vtRot.Rotate( vtN, dDiffAng / nStep) ; m_pMachine->SetAxisPos( m_AxesName[0], ptCen.x + vtRot.x + dCurrCoeff * dDeltaN * vtN.x) ; m_pMachine->SetAxisPos( m_AxesName[1], ptCen.y + vtRot.y + dCurrCoeff * dDeltaN * vtN.y) ; m_pMachine->SetAxisPos( m_AxesName[2], ptCen.z + vtRot.z + dCurrCoeff * dDeltaN * vtN.z) ; // assi rotanti for ( int j = 3 ; j < int( m_AxesName.size()) ; ++ j) { double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ; m_pMachine->SetAxisPos( m_AxesName[j], dVal) ; } // eventuali assi ausiliari for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) { double dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ; m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ; } // eseguo eventuale Vmill Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ; bool bOkF = GetHeadCurrPosDirAux( 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], ptNoseI, vtDirI, vtAuxI, vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ; // salvo riferimento per prossimo inizio vFrVzmI[k] = frVzmF ; } // eseguo eventuale collision check bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd) ; // aggiorno prossimo inizio ptNoseI = ptNoseF ; vtDirI = vtDirF ; } } } 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 : 100) ; 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) { int nStep = int( max( dDist / ( ( nMoveType == 0 ? 4 : 1) * m_dStep), 1.)) ; m_dCoeff += 1. / nStep ; if ( m_dCoeff > 1) m_dCoeff = 1 ; } else m_dCoeff = 1 ; dMove = ( m_dCoeff - dPrevCoeff) * dDist ; // Muovo eventuali assi ausiliari for ( int i = 0 ; i < int( m_AuxAxesName.size()) ; ++ i) { double dVal = m_AuxAxesVal[i] * ( 1 - m_dCoeff) + m_AuxAxesEnd[i] * m_dCoeff ; m_pMachine->SetAxisPos( m_AuxAxesName[i], dVal) ; } // eseguo eventuale collision check bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd) ; } // 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 if ( m_dCoeff > COEFF_LIM && m_bEnabAxes) { for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) m_AxesVal[i] = AxesEnd[i] ; } 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à if ( ! OnMoveEnd()) { nStatus = CalcStatusOnError( 0) ; return false ; } } // Altrimenti sto muovendomi all'interno dell'entità else nStatus = MCH_SIM_OK ; return true ; } //---------------------------------------------------------------------------- int Simulator::CalcStatusOnError( int nErr) { if ( Stopped()) return MCH_SIM_STOP ; else if ( nErr == 1) return MCH_SIM_OUTSTROKE ; else if ( nErr == 11) return MCH_SIM_COLLISION ; else return MCH_SIM_ERR ; } //---------------------------------------------------------------------------- bool Simulator::GetHeadCurrPosDirAux( Point3d& ptH, Vector3d& vtH, Vector3d& vtA) { // ci devono essere almeno i tre assi lineari if ( m_AxesName.size() < 3) return false ; // recupero le posizioni degli assi lineari DBLVECTOR vLinAx( 3) ; for ( size_t i = 0 ; i < 3 ; ++ i) m_pMachine->GetAxisPos( m_AxesName[i], vLinAx[i]) ; // recupero le posizioni degli eventuali assi rotanti DBLVECTOR vRotAx( m_AxesName.size() - 3) ; for ( size_t i = 3 ; i < m_AxesName.size() ; ++ i) m_pMachine->GetAxisPos( m_AxesName[i], vRotAx[i-3]) ; // determino posizione e orientamento della testa m_pMachine->GetNoseFromPositions( vLinAx[0], vLinAx[1], vLinAx[2], vRotAx, ptH) ; m_pMachine->GetToolDirFromAngles( vRotAx, vtH) ; m_pMachine->GetAuxDirFromAngles( vRotAx, vtA) ; return true ; } //---------------------------------------------------------------------------- bool Simulator::ExecLineVmill( int nVmId, 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) 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 += m_dVmTdOffs * vtHiL + m_dVmAdOffs * vtAiL ; ptHfL += m_dVmTdOffs * vtHfL + m_dVmAdOffs * vtAfL ; // Log per debug if ( ExeGetDebugLevel() >= 10) { string sOut = "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()) } // Eseguo return pVZM->MillingStep( ptHiL, vtHiL, vtAiL, ptHfL, vtHfL, vtAfL) ; } //---------------------------------------------------------------------------- bool Simulator::ExecCollisionCheck( int& nCdInd, int& nObjInd) { // se non ci sono oggetti da controllare o non ci sono grezzi o equivalenti, tutto bene if ( ! NeedCollisionCheck()) return true ; // ciclo sui grezzi o equivalenti for ( int i = 0 ; i < int( m_CdId.size()) ; ++ i) { // se modo hidden è da saltare int nMode ; if ( m_pGeomDB->GetCalcMode( m_CdId[i], nMode) && nMode == GDB_MD_HIDDEN) continue ; // verifico se è il grezzo in lavorazione bool bIsRaw = ( find( m_VmId.begin(), m_VmId.end(), m_CdId[i]) != m_VmId.end()) ; // recupero solido o trimesh, se altro lo salto const IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( m_CdId[i])) ; const ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeomDB->GetGeoObj( m_CdId[i])) ; if ( pVZM == nullptr && pSTM == nullptr) continue ; // recupero il riferimento Frame3d frCd ; m_pGeomDB->GetGlobFrame( m_CdId[i], frCd) ; // ciclo sugli oggetti con cui verificare for ( int j = 0 ; j < int( m_CollObj.size()) ; ++ j) { // se modo hidden è da saltare int nMode ; if ( m_pGeomDB->GetCalcMode( m_CollObj[j].nFrameId, nMode) && nMode == GDB_MD_HIDDEN) continue ; // verifico se è l'utensile attivo string sHead ; m_pGeomDB->GetName( m_pGeomDB->GetParentId( m_CollObj[j].nFrameId), sHead) ; string sExit ; m_pGeomDB->GetName( m_CollObj[j].nFrameId, sExit) ; bool bIsTool = ( sHead == m_sHead && ( sExit == string( "_T") + ToString( m_nExit) || sExit == string( "_TT") + ToString( m_nExit))) ; // se utensile attivo su grezzo in lavoro, salto if ( bIsTool && bIsRaw) continue ; // se riferimento non trovato, si salta const IGeoFrame3d* pGeoFrame = GetGeoFrame3d( m_pGeomDB->GetGeoObj( m_CollObj[j].nFrameId)) ; if ( pGeoFrame == nullptr) continue ; // esecuzione controlli di collisione bool bOk = true ; Frame3d frObj = pGeoFrame->GetFrame() ; Frame3d frParent ; m_pGeomDB->GetGlobFrame( m_CollObj[j].nFrameId, frParent) ; frObj.LocToLoc( frParent, frCd) ; 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->AvoidBox( frObj, vtDiag, m_dSafeDist) ; else bOk = ! CDeBoxClosedSurfTm( frObj, vtDiag, m_dSafeDist, *pSTM) ; } else if ( m_CollObj[j].nType == MCH_SIM_COB_CYL) { if ( pVZM != nullptr) bOk = pVZM->AvoidCylinder( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_dSafeDist) ; else bOk = ! CDeCylClosedSurfTm( frObj, m_CollObj[j].dPar1, m_CollObj[j].dPar2, m_dSafeDist, *pSTM) ; } else if ( m_CollObj[j].nType == MCH_SIM_COB_SPHE) { if ( pVZM != nullptr) bOk = pVZM->AvoidSphere( frObj.Orig(), m_CollObj[j].dPar1, m_dSafeDist) ; else bOk = ! CDeSpheClosedSurfTm( frObj.Orig(), m_CollObj[j].dPar1, m_dSafeDist, *pSTM) ; } if ( ! bOk) { nCdInd = i ; nObjInd = j ; return false ; } } } return true ; } //---------------------------------------------------------------------------- bool Simulator::OnStart( bool bFirst) { // assegno flag inizio simulazione bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIM1ST, bFirst) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_START)) return true ; // chiamo la funzione di inizio simulazione bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_START) ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnEnd( void) { // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_END)) return true ; // chiamo la funzione di fine simulazione return m_pMachine->LuaCallFunction( ON_SIMUL_END) ; } //---------------------------------------------------------------------------- bool Simulator::OnDispositionStarting( int nOpId, int nOpInd, int nPhase, const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) { bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; // assegno nuovo indice di fase bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; // assegno nome e valore riferimento della tavola corrente bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; // assegno flag disposizione passiva bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; // assegno flag disposizione con operazioni manuali bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_STARTING)) return true ; // chiamo la funzione di inizio disposizione bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_STARTING) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnDispositionStart( int nOpId, int nOpInd, int nPhase, const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand) { // assegno identificativo e indice disposizione bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ; // assegno nuovo indice di fase bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ; // assegno nome e valore riferimento della tavola corrente bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ; // assegno flag disposizione passiva bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ; // assegno flag disposizione con operazioni manuali bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_START)) return true ; // chiamo la funzione di inizio disposizione bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_START) ; // recupero i dati di ritorno m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnDispositionEnd( void) { // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_END)) return true ; // chiamo la funzione di fine disposizione bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_END) ; // recupero i dati di ritorno m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ; m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnToolSelect( const string& sTool, const string& sHead, int nExit, const string& sTcPos, bool bFirst) { // reset oggetti per verifica collisione con grezzo m_CollObj.clear() ; // assegno il nome dell'utensile, la testa e l'uscita if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TOOL, sTool) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_HEAD, sHead) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXIT, nExit) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TCPOS, sTcPos)) return false ; // assegno il token e il nome degli assi int nNumAxes = int( m_AxesName.size()) ; for ( int i = 1 ; i <= MAX_AXES ; ++ i) { if ( i <= nNumAxes) { if ( ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisToken(i), m_AxesToken[i-1]) || ! m_pMachine->LuaSetGlobVar( GetGlobVarAxisName(i), m_AxesName[i-1])) return false ; } else { if ( ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisToken(i)) || ! m_pMachine->LuaResetGlobVar( GetGlobVarAxisName(i))) return false ; } } // assegno il flag di chiamata di utensile iniziale if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FIRST, bFirst)) return false ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_SELECT)) return true ; // chiamo la funzione di selezione utensile bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_SELECT) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; // recupero distanza di sicurezza per verifica collisione m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SAFEDIST, m_dSafeDist) ; // recupero i dati di ritorno per assi ausiliari ResetAuxAxes() ; 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_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 ; 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->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_AuxAxesLinear.push_back( bLinear) ; m_AuxAxesVal.emplace_back( dVal) ; m_AuxAxesEnd.emplace_back( dVal) ; } } else bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos) { // 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) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_DESELECT)) return bOk ; // chiamo la funzione di deselezione utensile bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_DESELECT) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax, const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax) { // assegno identificativo e indice lavorazione if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHID, nOpId) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHIND, nOpInd)) return false ; // assegno punti estremi dell'ingombro della lavorazione if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMIN, ptMin) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMAX, ptMax)) return false ; // assegno punti estremi dell'ingombro degli assi della lavorazione if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMIN, vAxMin) || ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMAX, vAxMax)) return false ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_START)) return true ; // chiamo la funzione di inizio disposizione bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_START) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnMachiningEnd( void) { // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_END)) return true ; // chiamo la funzione di fine lavorazione bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_END) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnPathStart( int nClPathId, int nClPathInd, int nAS, const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtExtr, const Point3d& ptMin, const Point3d& ptMax, const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax, double dElev) { // assegno identificativo e indice percorso di lavorazione bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHID, nClPathId) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PATHIND, nClPathInd) ; // assegno numero di dati ausiliari iniziali bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAS) ; // assegno punti iniziale e finale e versore estrusione bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_START, ptStart) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_END, ptEnd) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXTR, vtExtr) ; // assegno punti estremi dell'ingombro del percorso di lavorazione bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMIN, ptMin) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PMAX, ptMax) ; // assegno punti estremi dell'ingombro degli assi della lavorazione bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMIN, vAxMin) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PAXMAX, vAxMax) ; // assegno la massima elevazione bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ELEV, dElev) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START)) return bOk ; // chiamo la funzione di inizio percorso di lavorazione bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnPathEnd( int nAE) { // assegno numero di dati ausiliari finali bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAE) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END)) return bOk ; // chiamo la funzione di fine percorso di lavorazione bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnPathStartAux( int nInd, const string& sAS, int& nErr) { // reset stato di errore da script nErr = 0 ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START_AUX)) return true ; // assegno indice, valore dato ausiliario e resetto errore bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAS) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; // chiamo la funzione di evento ausiliario all'inizio del percorso bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START_AUX) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; // verifico codice di errore bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; return ( bOk && nErr == 0) ; } //---------------------------------------------------------------------------- bool Simulator::OnPathEndAux( int nInd, const string& sAE, int& nErr) { // reset stato di errore da script nErr = 0 ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END_AUX)) return true ; // assegno indice, valore dato ausiliario e resetto errore bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAE) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; // chiamo la funzione di evento ausiliario alla fine del percorso bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END_AUX) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; // verifico codice di errore bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; return ( bOk && nErr == 0) ; } //---------------------------------------------------------------------------- bool Simulator::OnMoveStart( const CamData* pCamData, int& nErr) { // reset stato di errore da script nErr = 0 ; // recupero e assegno i dati // dati generali e reset errore bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEID, m_nEntId) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEIND, m_nEntInd) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVE, pCamData->GetMoveType()) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_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 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), m_AxesVal[i-1]) ; bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisValue( i), AxesEnd[i-1]) ; } else { bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisPrev( i)) ; bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisValue( i)) ; } } // 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()) ; // reset abilitazione assi attivi bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_ENABAXES) ; // reset numero assi ausiliari bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_AUXAXES) ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_START)) { ResetAuxAxes() ; return bOk ; } // chiamo la funzione bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_START) ; // con errore, esco if ( ! bOk) { ResetAuxAxes() ; return false ; } // verifico codice di errore m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; if ( nErr != 0) return false ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; // reset assi ausiliari ResetAuxAxes() ; // recupero i dati di ritorno 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_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 ; bool bLinear ; double dVal ; double dEnd ; string sAuxAxVal = GLOB_VAR + GVAR_AN ; ReplaceString( sAuxAxVal, "N", ToString( i)) ; 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->GetAxisType( sName, bLinear) && m_pMachine->GetAxisPos( sName, dVal) && 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_AuxAxesLinear.push_back( bLinear) ; m_AuxAxesVal.emplace_back( dVal) ; m_AuxAxesEnd.emplace_back( dEnd) ; if ( ! m_pMachine->VerifyOutstroke( sName, dEnd)) { nErr = 1 ; bOk = false ; } } } else bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnMoveEnd( void) { // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_END)) return true ; // chiamo la funzione bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_END) ; // forzo aggiornamento posizione assi (possono essere stati mossi nello script) UpdateAxesPos() ; return bOk ; } //---------------------------------------------------------------------------- bool Simulator::OnCollision( int nCdInd, int nObjInd, int& nErr) { // reset stato di errore da script nErr = 0 ; // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_COLLISION)) return true ; // reset stato di errore if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr)) return false ; // assegno identificativi grezzo e oggetto in collisione if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMVMID, m_CdId[nCdInd])) return false ; if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMCOBIND, m_CollObj[nObjInd].nInd)) return false ; // chiamo la funzione if ( ! m_pMachine->LuaCallFunction( ON_SIMUL_COLLISION)) return false ; // verifico codice di errore m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ; // l'errore standard di collisione è stato portato da 1 a 11 per non collidere con altri tipi di errori if ( nErr == 1) nErr = 11 ; return ( nErr == 0) ; } //---------------------------------------------------------------------------- bool Simulator::OnResetMachine( void) { // verifico esistenza funzione if ( ! m_pMachine->LuaExistsFunction( ON_RESET_MACHINE)) return true ; // eseguo reset macchina return m_pMachine->LuaCallFunction( ON_RESET_MACHINE) ; } //---------------------------------------------------------------------------- bool Simulator::AddCollisionObj( int nInd, int nFrameId, int nType, 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 ( abs( dPar1) < EPS_SMALL || abs( dPar2) < EPS_SMALL) return false ; break ; case MCH_SIM_COB_SPHE : if ( abs( dPar1) < EPS_SMALL) return false ; break ; default : return false ; } // aggiungo al vettore m_CollObj.emplace_back( nInd, nFrameId, nType, dPar1, dPar2, dPar3) ; return true ; }