f7251bf3bd
- in simulazione Trace sta sull'uscita della testa se nel suo gruppo si mette la info OnExit=1.
2698 lines
105 KiB
C++
2698 lines
105 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2024
|
|
//----------------------------------------------------------------------------
|
|
// File : SimulatorSP.cpp Data : 01.09.24 Versione : 2.6i1
|
|
// Contenuto : Implementazione della classe SimulatorSP.
|
|
// Simulatore singolo processo.
|
|
//
|
|
//
|
|
// Modifiche : 19.10.15 DS Creazione modulo.
|
|
// 26.02.16 DS Aggiunta gestione archi.
|
|
// 04.01.17 DS Riorganizzazione codice.
|
|
// 01.09.24 DS Rinominato.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "SimulatorSP.h"
|
|
#include "MachMgr.h"
|
|
#include "Disposition.h"
|
|
#include "Machining.h"
|
|
#include "MachiningConst.h"
|
|
#include "OutputConst.h"
|
|
#include "DllMain.h"
|
|
#include "/EgtDev/Include/EGkCDeBoxClosedSurfTm.h"
|
|
#include "/EgtDev/Include/EGkCDeCylClosedSurfTm.h"
|
|
#include "/EgtDev/Include/EGkCDeSpheClosedSurfTm.h"
|
|
#include "/EgtDev/Include/EGkCDeConeFrustumClosedSurfTm.h"
|
|
#include "/EgtDev/Include/EGkCDeClosedSurfTmClosedSurfTm.h"
|
|
#include "/EgtDev/Include/EGkVolZmap.h"
|
|
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include "/EgtDev/Include/EGkSurfLocal.h"
|
|
#include "/EgtDev/Include/EXeCmdLogOff.h"
|
|
#include "/EgtDev/Include/EXeSetModifiedOff.h"
|
|
#include "/EgtDev/Include/EXeConst.h"
|
|
#include "/EgtDev/Include/EMkToolConst.h"
|
|
#include "/EgtDev/Include/EMkOperationConst.h"
|
|
#include "/EgtDev/Include/EGnGetKeyData.h"
|
|
#include "/EgtDev/Include/EgtPerfCounter.h"
|
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
|
#include "/EgtDev/Include/EgtIniFile.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_OUTSTROKE = 1 ;
|
|
static const int ERR_COLLISION = 11 ;
|
|
static const int ERR_TOOL_SEL = 21 ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
ISimulator*
|
|
CreateSimulatorSP( void)
|
|
{
|
|
return static_cast<ISimulator*> ( new( nothrow) SimulatorSP) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SimulatorSP::SimulatorSP( void)
|
|
{
|
|
m_pMchMgr = nullptr ;
|
|
m_pGeomDB = nullptr ;
|
|
m_pMachine = nullptr ;
|
|
m_pPerfCnt = nullptr ;
|
|
m_nStatus = SIS_CREATED ;
|
|
m_dStep = MID_STEP ;
|
|
m_nUiStatus = MCH_UISIM_NULL ;
|
|
m_nOpId = GDB_ID_NULL ;
|
|
m_nOpInd = 0 ;
|
|
m_nCLPathId = GDB_ID_NULL ;
|
|
m_nCLPathInd = 0 ;
|
|
m_nEntId = GDB_ID_NULL ;
|
|
m_nEntInd = 0 ;
|
|
m_dCoeff = 0 ;
|
|
m_nAuxSTot = 0 ;
|
|
m_nAuxSInd = 0 ;
|
|
m_nAuxETot = 0 ;
|
|
m_nAuxEInd = 0 ;
|
|
m_nExit = 0 ;
|
|
m_dTDiam = 0 ;
|
|
m_dTLen = 0 ;
|
|
m_bCutOnTip = false ;
|
|
m_bEnableVm = false ;
|
|
m_dSafeDist = SAFEDIST_STD ;
|
|
m_bEnableTrace = false ;
|
|
m_nTraceGroup = GDB_ID_NULL ;
|
|
m_nCurrTrace = GDB_ID_NULL ;
|
|
m_nAxesMask = 0 ;
|
|
m_bEnabAxes = true ;
|
|
m_bShowAxes = true ;
|
|
m_AxesName.reserve( 8) ;
|
|
m_AxesToken.reserve( 8) ;
|
|
m_AxesLinear.reserve( 8) ;
|
|
m_AxesVal.reserve( 8) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
SimulatorSP::~SimulatorSP( void)
|
|
{
|
|
// porto la macchina in posizione home
|
|
GoHome() ;
|
|
// gestione evento uscita dal simulatore
|
|
OnExit() ;
|
|
// rimuovo tavola variabili globali
|
|
m_pMachine->LuaResetGlobVar( GLOB_VAR) ;
|
|
// rimuovo performance counter
|
|
if ( m_pPerfCnt != nullptr) {
|
|
delete m_pPerfCnt ;
|
|
m_pPerfCnt = nullptr ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::Init( MachMgr* pMchMgr)
|
|
{
|
|
// verifico ambiente
|
|
if ( pMchMgr == nullptr || pMchMgr->GetContextId() == 0 ||
|
|
pMchMgr->GetGeomDB() == nullptr || pMchMgr->GetCurrMachine() == nullptr)
|
|
return false ;
|
|
m_pMchMgr = pMchMgr ;
|
|
m_pGeomDB = m_pMchMgr->GetGeomDB() ;
|
|
m_pMachine = m_pMchMgr->GetCurrMachine() ;
|
|
m_pPerfCnt = new PerformanceCounter ;
|
|
m_nStatus = SIS_INITIALIZED ;
|
|
if ( ExeGetDebugLevel() >= 1)
|
|
LOG_INFO( GetEMkLogger(), " * SimulatorSP *")
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::Start( bool bFirst)
|
|
{
|
|
// Verifico ci sia una macchinata corrente
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr || m_pMachine == nullptr ||
|
|
m_pMchMgr->GetCurrMachGroup() == GDB_ID_NULL)
|
|
return false ;
|
|
m_pMchMgr->ResetLastError() ;
|
|
m_pMchMgr->ResetWarnings() ;
|
|
|
|
// 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 ;
|
|
}
|
|
|
|
// Reset utensile, interpolazione e assi correnti
|
|
m_sTool.clear() ;
|
|
m_sHead.clear() ;
|
|
m_nExit = 0 ;
|
|
m_dTDiam = 0 ;
|
|
m_dTLen = 0 ;
|
|
m_bCutOnTip = false ;
|
|
m_nCurrTrace = GDB_ID_NULL ;
|
|
ResetInterpolation() ;
|
|
ResetAxes() ;
|
|
ResetAuxAxes() ;
|
|
|
|
// porto la macchina in home
|
|
if ( ! GoHome())
|
|
bOk = false ;
|
|
|
|
// Verifico la disposizione iniziale della macchinata
|
|
m_nOpId = m_pMchMgr->GetFirstActiveOperation() ;
|
|
m_nOpInd = 1 ;
|
|
if ( m_pMchMgr->GetOperationType( m_nOpId) != OPER_DISP)
|
|
bOk = false ;
|
|
|
|
// Definisco tabella variabili globali
|
|
if ( ! m_pMachine->LuaCreateGlobTable( GLOB_VAR))
|
|
bOk = false ;
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INCHES, ! ExeUiUnitsAreMM()) ;
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ;
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_VER, GetEMkVer()) ;
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MACHNAME, m_pMachine->GetMachineName()) ;
|
|
|
|
// Se appena entrati in simulazione
|
|
if ( m_nStatus == SIS_INITIALIZED) {
|
|
if ( ! OnInit())
|
|
bOk = false ;
|
|
m_nStatus = SIS_READYTOSTART ;
|
|
}
|
|
|
|
// Richiamo funzione per evento avvio simulazione
|
|
if ( ! OnProgramStart( bFirst))
|
|
bOk = false ;
|
|
|
|
// Arrivo alla preparazione per la prima lavorazione
|
|
int nStatus ;
|
|
if ( ! FindAndManageOperationStart( true, bFirst, nStatus) && nStatus != MCH_SIM_STOP)
|
|
bOk = false ;
|
|
// se sono ancora su disposizione
|
|
if ( m_pMchMgr->GetOperationType( m_nOpId) == OPER_DISP) {
|
|
// ricerca e gestione inizio percorso di lavoro
|
|
if ( ! FindAndManagePathStart( nStatus))
|
|
return false ;
|
|
// eventuali comandi ausiliari di inizio percorso
|
|
while ( m_nAuxSInd < m_nAuxSTot) {
|
|
if ( ! ManagePathStartAux( nStatus))
|
|
return false ;
|
|
}
|
|
// aggiornamento assi per eventuali teste caricate
|
|
UpdateAxes() ;
|
|
}
|
|
|
|
// Reset timer
|
|
if ( m_pPerfCnt != nullptr)
|
|
m_pPerfCnt->Start() ;
|
|
|
|
// Imposto lo stato interno
|
|
m_nStatus = ( bOk ? SIS_READYTORUN : SIS_READYTOSTART) ;
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::VerifySetup( void)
|
|
{
|
|
// se attrezzaggio non definito, nulla da verificare
|
|
if ( ! m_pMchMgr->GetCurrSetupMgr().Exists())
|
|
return true ;
|
|
|
|
// lancio la verifica
|
|
STRVECTOR vsErr ;
|
|
if ( m_pMchMgr->VerifyCurrSetup( vsErr))
|
|
return true ;
|
|
|
|
// gestisco errore
|
|
string sErr = "Error with setup :" ;
|
|
for ( const auto& sTmp : vsErr)
|
|
sErr += " " + sTmp ;
|
|
m_pMchMgr->SetLastError( 1002, sErr) ;
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ResetInterpolation( void)
|
|
{
|
|
m_nOpId = GDB_ID_NULL ;
|
|
m_nOpInd = 0 ;
|
|
m_nCLPathId = GDB_ID_NULL ;
|
|
m_nCLPathInd = 0 ;
|
|
m_nEntId = GDB_ID_NULL ;
|
|
m_nEntInd = 0 ;
|
|
m_dCoeff = 0 ;
|
|
m_nAuxSTot = 0 ;
|
|
m_nAuxSInd = 0 ;
|
|
m_nAuxETot = 0 ;
|
|
m_nAuxEInd = 0 ;
|
|
m_VmId.clear() ;
|
|
m_CdId.clear() ;
|
|
m_VmTool.clear() ;
|
|
m_CollObj.clear() ;
|
|
m_dSafeDist = SAFEDIST_STD ;
|
|
m_nAxesMask = 0 ;
|
|
m_bEnabAxes = true ;
|
|
m_bShowAxes = true ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::Move( int& nStatus)
|
|
{
|
|
// Verifiche
|
|
if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr || m_nStatus != SIS_READYTORUN) {
|
|
nStatus = MCH_SIM_ERR ;
|
|
return false ;
|
|
}
|
|
|
|
// Recupero tempo impiegato (calcolo + visualizzazione precedenti)
|
|
if ( m_pPerfCnt != nullptr && ExeGetDebugLevel() >= 5) {
|
|
double dElapsed = m_pPerfCnt->Stop() ;
|
|
string sOut = "Elapsed=" + ToString( dElapsed, 1) ;
|
|
LOG_DBG_INFO( GetEMkLogger(), sOut.c_str())
|
|
m_pPerfCnt->Start() ;
|
|
}
|
|
|
|
// reset visualizzazione collisioni
|
|
ResetCollisionMark() ;
|
|
|
|
// Se arrivato alla fine dell'interpolazione
|
|
if ( m_dCoeff > COEFF_LIM) {
|
|
// recupero una nuova entità
|
|
m_nEntId = m_pGeomDB->GetNext( m_nEntId) ;
|
|
m_dCoeff = 0 ;
|
|
}
|
|
|
|
// Se appena arrivato alla fine di un percorso di lavoro (verifico anche completamento dei comandi aux di start per path vuote)
|
|
if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd == 0 && m_nCLPathInd > 0 && m_nAuxSInd >= m_nAuxSTot) {
|
|
// gestione fine percorso di lavoro
|
|
if ( ! ManagePathEnd( nStatus))
|
|
return false ;
|
|
}
|
|
|
|
// Se alla fine del percorso dopo esecuzione azioni ausiliarie (verifico anche completamento dei comandi aux di start per path vuote)
|
|
if ( m_nEntId == GDB_ID_NULL && m_nAuxEInd >= m_nAuxETot && m_nAuxSInd >= m_nAuxSTot) {
|
|
// ricerca e gestione inizio percorso di lavoro
|
|
if ( ! FindAndManagePathStart( nStatus))
|
|
return false ;
|
|
}
|
|
|
|
// Se arrivato alla fine di una operazione
|
|
if ( m_nCLPathId == GDB_ID_NULL) {
|
|
// gestione fine operazione
|
|
if ( ! ManageOperationEnd( nStatus))
|
|
return false ;
|
|
// ricerca e gestione nuova operazione
|
|
if ( ! FindAndManageOperationStart( false, false, nStatus))
|
|
return false ;
|
|
// se non ce ne sono altre, sono alla fine
|
|
if ( m_nOpId == GDB_ID_NULL) {
|
|
OnProgramEnd() ;
|
|
nStatus = MCH_SIM_END ;
|
|
return false ;
|
|
}
|
|
// ricerca e gestione inizio percorso di lavoro
|
|
if ( ! FindAndManagePathStart( nStatus))
|
|
return false ;
|
|
}
|
|
|
|
// Se sto eseguendo i movimenti ausiliari di inizio percorso
|
|
if ( m_nAuxSInd < m_nAuxSTot)
|
|
return ManagePathStartAux( nStatus) ;
|
|
|
|
// Se sto eseguendo i movimenti ausiliari di fine percorso
|
|
if ( m_nAuxEInd < m_nAuxETot)
|
|
return ManagePathEndAux( nStatus) ;
|
|
|
|
// Gestione movimento assi
|
|
return ManageMove( nStatus) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::GetAxisInfoPos( int nI, string& sName, string& sToken, bool& bLinear, double& dVal) const
|
|
{
|
|
// Verifiche
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// numero assi di calcolo e ausiliari
|
|
int nAxisCount = ( m_bShowAxes ? int( m_AxesName.size()) : 0) ;
|
|
int nAuxAxisCount = int( m_AuxAxesName.size()) ;
|
|
// recupero i dati dell'asse
|
|
if ( nI < 0 || nI >= nAxisCount + nAuxAxisCount)
|
|
return false ;
|
|
// se asse principale
|
|
if ( nI < nAxisCount) {
|
|
sName = m_AxesName[nI] ;
|
|
sToken = m_AxesToken[nI] ;
|
|
bLinear = m_AxesLinear[nI] ;
|
|
}
|
|
// altrimenti asse ausiliario
|
|
else {
|
|
sName = m_AuxAxesName[ nI - nAxisCount] ;
|
|
sToken = m_AuxAxesToken[ nI - nAxisCount] ;
|
|
bLinear = m_AuxAxesLinear[ nI - nAxisCount] ;
|
|
}
|
|
// recupero la posizione
|
|
if ( ! m_pMchMgr->GetAxisPos( sName, dVal))
|
|
return false ;
|
|
// verifico se da invertire o offsettare
|
|
if ( nI < nAxisCount) {
|
|
if ( m_AxesInvert[nI])
|
|
dVal = - dVal ;
|
|
dVal += m_AxesOffset[nI] ;
|
|
}
|
|
else {
|
|
if ( m_AuxAxesInvert[nI - nAxisCount])
|
|
dVal = - dVal ;
|
|
dVal += m_AxesOffset[nI - nAxisCount] ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::GetToolInfo( string& sName, double& dSpeed) const
|
|
{
|
|
// Inizializzo i parametri di ritorno
|
|
sName.clear() ;
|
|
dSpeed = 0 ;
|
|
// Verifiche
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// Assegno il nome dell'utensile
|
|
sName = m_sTool ;
|
|
if ( sName.empty())
|
|
return true ;
|
|
// Recupero speed
|
|
const Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ;
|
|
return ( pMch != nullptr && pMch->GetParam( MPA_SPEED, dSpeed)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::GetOperationInfo( string& sName, int& nType) const
|
|
{
|
|
// Inizializzo i parametri di ritorno
|
|
sName.clear() ;
|
|
nType = OPER_NULL ;
|
|
// Verifiche
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// Recupero il tipo
|
|
Operation* pOpe = GetOperation( m_pGeomDB->GetUserObj( m_nOpId)) ;
|
|
if ( pOpe == nullptr)
|
|
return false ;
|
|
nType = pOpe->GetType() ;
|
|
// Recupero il nome
|
|
return m_pGeomDB->GetName( m_nOpId, sName) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::GetMoveInfo( int& nGmove, double& dFeed) const
|
|
{
|
|
// Verifiche
|
|
if ( m_pMchMgr == nullptr || m_pGeomDB == nullptr)
|
|
return false ;
|
|
// Recupero il movimento corrente
|
|
const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ;
|
|
if ( pCamData == nullptr)
|
|
return false ;
|
|
// Assegno feed
|
|
dFeed = pCamData->GetFeed() ;
|
|
// Assegno tipo di movimento
|
|
nGmove = pCamData->GetMoveType() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::SetStep( double dStep)
|
|
{
|
|
m_dStep = Clamp( dStep, MIN_STEP, MAX_STEP) ;
|
|
// imposto step per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale)
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMSTEP, m_dStep) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::SetUiStatus( int nUiStatus)
|
|
{
|
|
m_nUiStatus = nUiStatus ;
|
|
// imposto stato utente del simulatore per movimenti gestiti nelle macro di simulazione ( con ripristino macchina Lua originale)
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMUISTAT, m_nUiStatus) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::GoHome( void)
|
|
{
|
|
// controllo validità stato
|
|
if ( m_pGeomDB == nullptr || m_pMchMgr == nullptr || m_pMachine == nullptr)
|
|
return false ;
|
|
// reset visualizzazione collisioni
|
|
ResetCollisionMark() ;
|
|
// reset stato macchina
|
|
OnResetMachine() ;
|
|
// porto la macchina in home
|
|
m_pMchMgr->ResetAllAxesPos() ;
|
|
// assegno valori home degli assi macchina attivi
|
|
return m_pMchMgr->GetAllCurrAxesHomePos( m_AxesVal) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::UpdateTool( bool bFirst, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// Recupero l'utensile della lavorazione corrente
|
|
Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ;
|
|
if ( pMch != nullptr) {
|
|
// recupero nome e dati nuovo utensile
|
|
string sTuuid, sTool ;
|
|
if ( ! pMch->GetParam( MPA_TUUID, sTuuid) ||
|
|
! m_pMchMgr->TdbGetToolFromUUID( sTuuid, sTool))
|
|
return false ;
|
|
string sTcPos ; string sHead ; int nExit ;
|
|
if ( ! m_pMchMgr->GetCurrSetupMgr().GetToolData( sTool, sTcPos, sHead, nExit)) {
|
|
if ( m_pMchMgr->TdbSetCurrTool( sTool)) {
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_TCPOS, sTcPos) ;
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_HEAD, sHead) ;
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_EXIT, nExit) ;
|
|
}
|
|
// ripristino l'utensile corrente
|
|
m_pMchMgr->TdbSetCurrTool( m_sTool) ;
|
|
}
|
|
// verifico se cambierà
|
|
bool bDiffTool = ( sTool != m_sTool) ;
|
|
// se cambierà ed esiste il corrente, lo scarico
|
|
if ( bDiffTool && ! m_sTool.empty()) {
|
|
// eventuale lancio script per scarico utensile
|
|
int nCurrErr ;
|
|
if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) {
|
|
nErr = ( nErr != 0 ? nErr : nCurrErr) ;
|
|
if ( nCurrErr != ERR_COLLISION)
|
|
return false ;
|
|
}
|
|
}
|
|
// se prima volta, pulisco la testa
|
|
if ( bFirst)
|
|
m_pMchMgr->ResetHeadSet( sHead) ;
|
|
// recupero la lavorazione corrente e imposto la nuova
|
|
int nCurrMchId = m_pMchMgr->GetCurrMachining() ;
|
|
m_pMchMgr->SetCurrMachining( m_nOpId) ;
|
|
// carico l'utensile (e lo rendo corrente)
|
|
if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit))
|
|
return false ;
|
|
m_sTool = sTool ;
|
|
m_sHead = sHead ;
|
|
m_nExit = nExit ;
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ;
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, m_dTLen) ;
|
|
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) {
|
|
bool bFloating = m_pMachine->IsCurrToolFloating() ;
|
|
int nCurrErr ;
|
|
if ( ! OnToolSelect( m_sTool, sHead, nExit, sTcPos, bFirst, bFloating, nCurrErr)) {
|
|
nErr = ( nErr != 0 ? nErr : nCurrErr) ;
|
|
if ( nCurrErr != ERR_COLLISION)
|
|
return false ;
|
|
}
|
|
}
|
|
return ( nErr == 0) ;
|
|
}
|
|
// Provo con una disposizione
|
|
Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ;
|
|
if ( pDisp != nullptr) {
|
|
// recupero i dati
|
|
string sTool ; string sHead ; int nExit ; string sTcPos ;
|
|
pDisp->GetToolData( sTool, sHead, nExit, sTcPos) ;
|
|
// se esiste utensile corrente e cambierà, lo scarico
|
|
if ( ! m_sTool.empty() && sTool != m_sTool) {
|
|
// eventuale lancio script per scarico utensile
|
|
int nCurrErr ;
|
|
if ( ! OnToolDeselect( sTool, sHead, nExit, sTcPos, nCurrErr)) {
|
|
nErr = ( nErr != 0 ? nErr : nCurrErr) ;
|
|
if ( nCurrErr != ERR_COLLISION)
|
|
return false ;
|
|
}
|
|
}
|
|
// carico l'utensile
|
|
if ( ! m_pMchMgr->SetCalcTool( sTool, sHead, nExit))
|
|
return false ;
|
|
m_sTool = sTool ;
|
|
m_sHead = sHead ;
|
|
m_nExit = nExit ;
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, m_dTDiam) ;
|
|
m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, m_dTLen) ;
|
|
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 != 0 ? nErr : nCurrErr) ;
|
|
if ( nCurrErr != ERR_COLLISION)
|
|
return false ;
|
|
}
|
|
return ( nErr == 0) ;
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::UpdateAxes( void)
|
|
{
|
|
ResetAxes() ;
|
|
// Macchina corrente
|
|
Machine* pMachine = m_pMchMgr->GetCurrMachine() ;
|
|
if ( pMachine == nullptr)
|
|
return false ;
|
|
// Carico i nomi e i token degli assi macchina attivi
|
|
if ( ! pMachine->GetAllCurrAxesNames( m_AxesName) ||
|
|
! pMachine->GetAllCurrAxesTokens( m_AxesToken))
|
|
return false ;
|
|
// Aggiorno flag di invertito, offset, tipo e posizione corrente degli assi macchina attivi
|
|
for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) {
|
|
bool bInvert ;
|
|
m_pMachine->GetAxisInvert( m_AxesName[i], bInvert) ;
|
|
m_AxesInvert.push_back( bInvert) ;
|
|
double dOffset ;
|
|
m_pMachine->GetAxisOffset( m_AxesName[i], dOffset) ;
|
|
m_AxesOffset.push_back( dOffset) ;
|
|
bool bLinear ;
|
|
m_pMachine->GetAxisType( m_AxesName[i], bLinear) ;
|
|
m_AxesLinear.push_back( bLinear) ;
|
|
double dVal ;
|
|
m_pMachine->GetAxisPos( m_AxesName[i], dVal) ;
|
|
m_AxesVal.emplace_back( dVal) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::UpdateAxesPos( void)
|
|
{
|
|
// Macchina corrente
|
|
Machine* pMachine = m_pMchMgr->GetCurrMachine() ;
|
|
if ( pMachine == nullptr)
|
|
return false ;
|
|
// Aggiorno la posizione corrente degli assi macchina attivi
|
|
m_AxesVal.clear() ;
|
|
for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i) {
|
|
double dVal ;
|
|
m_pMachine->GetAxisPos( m_AxesName[i], dVal) ;
|
|
m_AxesVal.emplace_back( dVal) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ResetAxes( void)
|
|
{
|
|
// pulisco dati assi
|
|
m_AxesName.clear() ;
|
|
m_AxesToken.clear() ;
|
|
m_AxesInvert.clear() ;
|
|
m_AxesLinear.clear() ;
|
|
m_AxesVal.clear() ;
|
|
m_nAxesMask = 0 ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ResetAuxAxes( void)
|
|
{
|
|
// pulisco dati assi ausiliari
|
|
m_AuxAxesName.clear() ;
|
|
m_AuxAxesToken.clear() ;
|
|
m_AuxAxesInvert.clear() ;
|
|
m_AuxAxesOffset.clear() ;
|
|
m_AuxAxesLinear.clear() ;
|
|
m_AuxAxesVal.clear() ;
|
|
m_AuxAxesEnd.clear() ;
|
|
m_AuxAxesLink.clear() ;
|
|
// abilito assi principali
|
|
m_bEnabAxes = true ;
|
|
m_bShowAxes = true ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::FindAndManageOperationStart( bool bStart, bool bFirst, int& nStatus)
|
|
{
|
|
// verifico parametri
|
|
if ( ! bStart)
|
|
bFirst = false ;
|
|
// recupero la nuova operazione
|
|
if ( bStart) {
|
|
m_nOpId = m_pMchMgr->GetFirstActiveOperation( true) ;
|
|
m_nOpInd = 0 ;
|
|
}
|
|
else
|
|
m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId, true) ;
|
|
// ciclo sulle successive operazioni
|
|
while ( m_nOpId != GDB_ID_NULL) {
|
|
// se lavorazione valida
|
|
Machining* pMch = GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) ;
|
|
if ( pMch != nullptr && ! pMch->IsEmpty()) {
|
|
bool bOk = true ;
|
|
// aggiorno utensile e assi conseguenti
|
|
int nErr ;
|
|
if ( ! UpdateTool( bFirst, nErr)) {
|
|
string sOut = "Err=" + ToString( nErr) ;
|
|
LOG_INFO( GetEMkLogger(), sOut.c_str())
|
|
nStatus = CalcStatusOnError( nErr) ;
|
|
bOk = false ;
|
|
}
|
|
++ m_nOpInd ;
|
|
// imposto la lavorazione come corrente
|
|
m_pMchMgr->SetCurrMachining( m_nOpId) ;
|
|
// recupero punti di minimo e massimo ingombro
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ;
|
|
Point3d ptMin, ptMax ;
|
|
m_pGeomDB->GetInfo( nClId, KEY_MMIN, ptMin) ;
|
|
m_pGeomDB->GetInfo( nClId, KEY_MMAX, ptMax) ;
|
|
DBLVECTOR vAxMin, vAxMax ;
|
|
m_pGeomDB->GetInfo( nClId, KEY_MAXMIN, vAxMin) ;
|
|
m_pGeomDB->GetInfo( nClId, KEY_MAXMAX, vAxMax) ;
|
|
// richiamo gestione evento inizio lavorazione
|
|
if ( ! OnMachiningStart( m_nOpId, m_nOpInd, ptMin, ptMax, vAxMin, vAxMax)) {
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
bOk = false ;
|
|
}
|
|
if ( ! bOk)
|
|
return false ;
|
|
break ;
|
|
}
|
|
// se disposizione con cambio di fase
|
|
Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) ;
|
|
if ( pDisp != nullptr) {
|
|
// in alcuni casi la disposizione non è inizializzata
|
|
pDisp->Init( m_pMchMgr) ;
|
|
// recupero dati tavola
|
|
string sTable ;
|
|
pDisp->GetTable( sTable) ;
|
|
Point3d ptOri1 ;
|
|
pDisp->GetTableRef1( ptOri1) ;
|
|
// recupero la fase della disposizione
|
|
int nPhase = pDisp->GetPhase() ;
|
|
// recupero se con movimenti autonomi
|
|
bool bEmpty = pDisp->IsEmpty() ;
|
|
// recupero flag disposizione con movimenti manuali
|
|
bool bSomeByHand = pDisp->GetSomeByHand() ;
|
|
// se con movimenti autonomi
|
|
if ( ! bEmpty) {
|
|
// richiamo gestione evento appena prima di inizio disposizione
|
|
if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) {
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
return false ;
|
|
}
|
|
// cambio fase
|
|
m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ;
|
|
// se previsto, aggiorno utensile e assi conseguenti
|
|
if ( pDisp->IsWithTool()) {
|
|
int nErr ;
|
|
if ( ! UpdateTool( bFirst, nErr)) {
|
|
nStatus = CalcStatusOnError( nErr) ;
|
|
return false ;
|
|
}
|
|
}
|
|
++ m_nOpInd ;
|
|
// richiamo gestione evento inizio disposizione
|
|
if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, false, bSomeByHand)) {
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
return false ;
|
|
}
|
|
// se ci sono movimenti manuali, aggiorno visualizzazione e breve pausa (200 ms)
|
|
if ( bSomeByHand)
|
|
Sleep( 200) ;
|
|
break ;
|
|
}
|
|
// altrimenti disposizione passiva
|
|
else {
|
|
// richiamo gestione evento appena prima di inizio disposizione
|
|
if ( ! OnDispositionStarting( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand)) {
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
return false ;
|
|
}
|
|
// cambio fase
|
|
m_pMchMgr->SetCurrPhase( nPhase, ( nPhase == 1)) ;
|
|
++ m_nOpInd ;
|
|
// richiamo gestione evento inizio e fine disposizione
|
|
if ( ! OnDispositionStart( m_nOpId, m_nOpInd, nPhase, sTable, ptOri1, true, bSomeByHand) ||
|
|
! OnDispositionEnd()) {
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
return false ;
|
|
}
|
|
// se non è inizio, aggiorno visualizzazione e breve pausa (200 ms)
|
|
if ( nPhase != 1) {
|
|
ExeDraw() ;
|
|
Sleep( 200) ;
|
|
}
|
|
}
|
|
}
|
|
// passo alla operazione successiva
|
|
m_nOpId = m_pMchMgr->GetNextActiveOperation( m_nOpId) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ManageOperationEnd( int& nStatus)
|
|
{
|
|
bool bOk = false ;
|
|
// non c'è operazione in corso (solo prima disposizione senza lavorazioni)
|
|
if ( m_nOpId == GDB_ID_NULL)
|
|
bOk = true ;
|
|
// se altrimenti è una lavorazione
|
|
else if ( GetMachining( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) {
|
|
// richiamo gestione evento fine lavorazione
|
|
bOk = OnMachiningEnd() ;
|
|
}
|
|
// se altrimenti è una disposizione
|
|
else if ( GetDisposition( m_pGeomDB->GetUserObj( m_nOpId)) != nullptr) {
|
|
// richiamo gestione evento fine disposizione
|
|
bOk = OnDispositionEnd() ;
|
|
}
|
|
// gestione stato
|
|
if ( ! bOk)
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::FindAndManagePathStart( int& nStatus)
|
|
{
|
|
// se devo cercare il primo nella nuova operazione
|
|
if ( m_nCLPathId == GDB_ID_NULL) {
|
|
// aggiorno gli altri dati
|
|
int nClId = m_pGeomDB->GetFirstNameInGroup( m_nOpId, MCH_CL) ;
|
|
m_nCLPathId = m_pGeomDB->GetFirstGroupInGroup( nClId) ;
|
|
m_nCLPathInd = 0 ;
|
|
m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ;
|
|
m_nEntInd = 0 ;
|
|
m_dCoeff = 0 ;
|
|
}
|
|
// altrimenti cerco il successivo nella stessa operazione
|
|
else {
|
|
// recupero un nuovo CLpath
|
|
while ( m_nEntId == GDB_ID_NULL) {
|
|
m_nCLPathId = m_pGeomDB->GetNextGroup( m_nCLPathId) ;
|
|
// se non ce ne sono altri, devo passare a una nuova lavorazione
|
|
if ( m_nCLPathId == GDB_ID_NULL)
|
|
break ;
|
|
m_nEntId = m_pGeomDB->GetFirstInGroup( m_nCLPathId) ;
|
|
m_nEntInd = 0 ;
|
|
m_dCoeff = 0 ;
|
|
}
|
|
}
|
|
// reset eventuale curva di TipTrace
|
|
m_nCurrTrace = GDB_ID_NULL ;
|
|
// 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( 0) ;
|
|
return false ;
|
|
}
|
|
}
|
|
// se altrimenti trovato nuovo CL path vuoto
|
|
else if ( m_nCLPathId != GDB_ID_NULL) {
|
|
// recupero il numero di eventi ausiliari di inizio
|
|
if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS_TOT, m_nAuxSTot))
|
|
m_nAuxSTot = 0 ;
|
|
m_nAuxSInd = 0 ;
|
|
// recupero il numero di eventi ausiliari di fine
|
|
if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot))
|
|
m_nAuxETot = 0 ;
|
|
m_nAuxEInd = 0 ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ManagePathEnd( int& nStatus)
|
|
{
|
|
// recupero il numero di eventi ausiliari di fine
|
|
if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE_TOT, m_nAuxETot))
|
|
m_nAuxETot = 0 ;
|
|
m_nAuxEInd = 0 ;
|
|
// richiamo gestione evento fine percorso di lavoro
|
|
bool bOk = OnPathEnd( m_nAuxETot) ;
|
|
// gestione stato
|
|
if ( ! bOk)
|
|
nStatus = CalcStatusOnError( 0) ;
|
|
// reset eventuale curva di TipTrace
|
|
m_nCurrTrace = GDB_ID_NULL ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ManagePathStartAux( int& nStatus)
|
|
{
|
|
// aggiorno indice corrente
|
|
++ m_nAuxSInd ;
|
|
// recupero i dati per l'evento corrente
|
|
string sAS ;
|
|
if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AS + ToString( m_nAuxSInd), sAS)) {
|
|
nStatus = MCH_SIM_ERR ;
|
|
return false ;
|
|
}
|
|
// richiamo gestione evento ausiliario prima di inizio percorso di lavoro
|
|
int nErr ;
|
|
if ( ! OnPathStartAux( m_nAuxSInd, sAS, nErr)) {
|
|
nStatus = CalcStatusOnError( nErr) ;
|
|
return false ;
|
|
}
|
|
nStatus = MCH_SIM_END_STEP ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ManagePathEndAux( int& nStatus)
|
|
{
|
|
// aggiorno indice corrente
|
|
++ m_nAuxEInd ;
|
|
// recupero i dati per l'evento corrente
|
|
string sAE ;
|
|
if ( ! m_pGeomDB->GetInfo( m_nCLPathId, KEY_AE + ToString( m_nAuxEInd), sAE)) {
|
|
nStatus = MCH_SIM_ERR ;
|
|
return false ;
|
|
}
|
|
// richiamo gestione evento ausiliario dopo fine percorso di lavoro
|
|
int nErr ;
|
|
if ( ! OnPathEndAux( m_nAuxEInd, sAE, nErr)) {
|
|
nStatus = CalcStatusOnError( nErr) ;
|
|
return false ;
|
|
}
|
|
nStatus = MCH_SIM_END_STEP ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ManageMove( int& nStatus)
|
|
{
|
|
// Imposto lunghezza di movimento effettuata
|
|
double dCurrMove = 0 ;
|
|
while ( m_nEntId != GDB_ID_NULL) {
|
|
// eseguo movimento singolo
|
|
double dMove ;
|
|
if ( ! ManageSingleMove( nStatus, dMove))
|
|
return false ;
|
|
dCurrMove += dMove ;
|
|
// se modalità play e fine entità e non raggiunta la lunghezza di movimento voluto
|
|
if ( m_nUiStatus == MCH_UISIM_PLAY && nStatus == MCH_SIM_END_STEP && dCurrMove < 0.75 * m_dStep) {
|
|
// recupero una nuova entità
|
|
m_nEntId = m_pGeomDB->GetNext( m_nEntId) ;
|
|
m_dCoeff = 0 ;
|
|
}
|
|
else
|
|
break ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ManageSingleMove( int& nStatus, double& dMove)
|
|
{
|
|
// Recupero posizione finale
|
|
const CamData* pCamData = GetCamData( m_pGeomDB->GetUserObj( m_nEntId)) ;
|
|
if ( pCamData == nullptr) {
|
|
nStatus = MCH_SIM_ERR ;
|
|
return false ;
|
|
}
|
|
switch ( pCamData->GetAxesStatus()) {
|
|
case CamData::AS_OK :
|
|
break ;
|
|
case CamData::AS_OUTSTROKE : {
|
|
DBLVECTOR OutAxes = pCamData->GetAxesVal() ;
|
|
if ( ! m_pMchMgr->GetCurrIsRobot()) {
|
|
for ( int i = int( 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] ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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<Frame3d> vFrVzmI( m_VmId.size()) ;
|
|
for ( int i = 0 ; i < int( m_VmId.size()) ; ++ i)
|
|
bOkI = m_pGeomDB->GetGlobFrame( m_VmId[i], vFrVzmI[i]) && bOkI ;
|
|
|
|
// Eventuale primo tracciamento punto tip utensile
|
|
if ( m_nCurrTrace == GDB_ID_NULL)
|
|
TraceToolTipMove( nMoveType) ;
|
|
|
|
// 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) ;
|
|
// eventuale tracciamento punto tip utensile
|
|
TraceToolTipMove( nMoveType) ;
|
|
}
|
|
}
|
|
// Eseguo movimento su arco
|
|
else {
|
|
// dati dell'arco
|
|
Point3d ptCen = pCamData->GetAxesCen() ;
|
|
double dAngCen = pCamData->GetAxesAngCen() ;
|
|
double dRad = pCamData->GetAxesRad() ;
|
|
Vector3d vtN = pCamData->GetAxesNormDir() ;
|
|
double dDeltaN = ( Point3d( AxesEnd[0], AxesEnd[1], AxesEnd[2]) - ptCen) * vtN ;
|
|
double dDiffAng = ( m_dCoeff - dPrevCoeff) * dAngCen ;
|
|
Vector3d vtRot = Point3d( m_AxesVal[0], m_AxesVal[1], m_AxesVal[2]) - ptCen ;
|
|
vtRot.Rotate( vtN, dPrevCoeff * dAngCen) ;
|
|
// se attivi Vmill o CollisionCheck approssimo movimento con più step
|
|
int nStep = 1 ;
|
|
if ( ! m_VmId.empty() || NeedCollisionCheck()) {
|
|
const double MIN_LEN_STEP = 2. ;
|
|
const double MAX_LEN_STEP = 10. ;
|
|
double dLenStep = Clamp( 0.1 * m_dTDiam, MIN_LEN_STEP, MAX_LEN_STEP) ;
|
|
nStep = max( int( abs( dDiffAng * DEGTORAD * dRad) / dLenStep), 1) ;
|
|
const double ANG_STEP = 5. ;
|
|
if ( abs( dDiffAng) / nStep > ANG_STEP)
|
|
nStep = int( abs( dDiffAng) / ANG_STEP) ;
|
|
}
|
|
for ( int i = 1 ; i <= nStep ; ++ i) {
|
|
double dCurrCoeff = dPrevCoeff + ( m_dCoeff - dPrevCoeff) / nStep * i ;
|
|
DBLVECTOR vDeltaVal( m_AxesName.size()) ;
|
|
// assi lineari
|
|
vtRot.Rotate( vtN, dDiffAng / nStep) ;
|
|
double dPrevVal, dVal ;
|
|
m_pMachine->GetAxisPos( m_AxesName[0], dPrevVal) ;
|
|
dVal = ptCen.x + vtRot.x + dCurrCoeff * dDeltaN * vtN.x ;
|
|
m_pMachine->SetAxisPos( m_AxesName[0], dVal) ;
|
|
vDeltaVal[0] = dVal - dPrevVal ;
|
|
m_pMachine->GetAxisPos( m_AxesName[1], dPrevVal) ;
|
|
dVal = ptCen.y + vtRot.y + dCurrCoeff * dDeltaN * vtN.y ;
|
|
m_pMachine->SetAxisPos( m_AxesName[1], dVal) ;
|
|
vDeltaVal[1] = dVal - dPrevVal ;
|
|
m_pMachine->GetAxisPos( m_AxesName[2], dPrevVal) ;
|
|
dVal = ptCen.z + vtRot.z + dCurrCoeff * dDeltaN * vtN.z ;
|
|
m_pMachine->SetAxisPos( m_AxesName[2], dVal) ;
|
|
vDeltaVal[2] = dVal - dPrevVal ;
|
|
// assi rotanti
|
|
for ( int j = 3 ; j < int( m_AxesName.size()) ; ++ j) {
|
|
double dPrevVal ; m_pMachine->GetAxisPos( m_AxesName[j], dPrevVal) ;
|
|
double dVal = m_AxesVal[j] * ( 1 - dCurrCoeff) + AxesEnd[j] * dCurrCoeff ;
|
|
m_pMachine->SetAxisPos( m_AxesName[j], dVal) ;
|
|
vDeltaVal[j] = dVal - dPrevVal ;
|
|
}
|
|
// eventuali assi ausiliari
|
|
for ( int j = 0 ; j < int( m_AuxAxesName.size()) ; ++ j) {
|
|
double dVal = 0 ;
|
|
if ( m_AuxAxesLink[j] == 0) {
|
|
dVal = m_AuxAxesVal[j] * ( 1 - dCurrCoeff) + m_AuxAxesEnd[j] * dCurrCoeff ;
|
|
}
|
|
else {
|
|
m_pMachine->GetAxisPos( m_AuxAxesName[j], dVal) ;
|
|
if ( m_AuxAxesLink[j] > 0)
|
|
dVal += vDeltaVal[m_AuxAxesLink[j] - 1] ;
|
|
else
|
|
dVal -= vDeltaVal[-m_AuxAxesLink[j] - 1] ;
|
|
}
|
|
m_pMachine->SetAxisPos( m_AuxAxesName[j], dVal) ;
|
|
}
|
|
// se abilitato, eseguo eventuale Vmill
|
|
for ( int j = 0 ; m_bEnableVm && j < int( m_VmTool.size()) ; ++ j) {
|
|
Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ;
|
|
bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ;
|
|
for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) {
|
|
Frame3d frVzmF ;
|
|
bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ;
|
|
ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs,
|
|
vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ;
|
|
// se ultimo utensile, salvo riferimento per prossimo inizio
|
|
if ( j == int( m_VmTool.size()) - 1)
|
|
vFrVzmI[k] = frVzmF ;
|
|
}
|
|
// aggiorno prossimo inizio
|
|
vPtNoseI[j] = ptNoseF ;
|
|
vVtDirI[j] = vtDirF ;
|
|
vVtAuxI[j] = vtAuxF ;
|
|
}
|
|
// eseguo eventuale collision check
|
|
bCollCheck = bCollCheck && ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ;
|
|
// eventuale tracciamento punto tip utensile
|
|
TraceToolTipMove( 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) ;
|
|
// eventuale tracciamento punto tip utensile
|
|
TraceToolTipMove( nMoveType) ;
|
|
}
|
|
}
|
|
|
|
// Se riscontrata collisione
|
|
if ( ! bCollCheck) {
|
|
// Richiamo funzione di convalida collisione
|
|
int nErr ;
|
|
if ( ! OnCollision( nCdInd, nObjInd, nErr)) {
|
|
nStatus = CalcStatusOnError( nErr) ;
|
|
// Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo
|
|
if ( m_dCoeff > COEFF_LIM) {
|
|
if ( m_bEnabAxes) {
|
|
for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i)
|
|
m_AxesVal[i] = AxesEnd[i] ;
|
|
}
|
|
// richiamo gestione evento fine entità, senza gestirne eventuali errori
|
|
int nErr ;
|
|
OnMoveEnd( nErr) ;
|
|
}
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
// Se arrivato a fine interpolazione movimento, salvo posizioni e segnalo
|
|
if ( m_dCoeff > COEFF_LIM) {
|
|
if ( m_bEnabAxes) {
|
|
for ( size_t i = 0 ; i < m_AxesName.size() ; ++ i)
|
|
m_AxesVal[i] = AxesEnd[i] ;
|
|
}
|
|
nStatus = MCH_SIM_END_STEP ;
|
|
// richiamo gestione evento fine entità
|
|
int nErr ;
|
|
if ( ! OnMoveEnd( nErr)) {
|
|
nStatus = CalcStatusOnError( nErr) ;
|
|
return false ;
|
|
}
|
|
}
|
|
// Altrimenti sto muovendomi all'interno dell'entità
|
|
else
|
|
nStatus = MCH_SIM_OK ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SimulatorSP::CalcStatusOnError( int nErr)
|
|
{
|
|
if ( Stopped())
|
|
return MCH_SIM_STOP ;
|
|
else if ( nErr == ERR_OUTSTROKE)
|
|
return MCH_SIM_OUTSTROKE ;
|
|
else if ( nErr == ERR_COLLISION)
|
|
return MCH_SIM_COLLISION ;
|
|
else
|
|
return MCH_SIM_ERR ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::GetHeadCurrPosDirAux( const std::string& sHead, int nExit, Point3d& ptH, Vector3d& vtH, Vector3d& vtA)
|
|
{
|
|
int nHeadId = m_pMachine->GetHeadId( sHead) ;
|
|
int nExitId = m_pMachine->GetExitId( sHead, nExit) ;
|
|
if ( nHeadId == GDB_ID_NULL || nExitId == GDB_ID_NULL)
|
|
return false ;
|
|
Frame3d frExit ; m_pGeomDB->GetGroupGlobFrame( nExitId, frExit) ;
|
|
ptH = frExit.Orig() ;
|
|
vtH = frExit.VersZ() ;
|
|
vtA = V_NULL ;
|
|
int nDirAuxId = m_pGeomDB->GetFirstNameInGroup( nHeadId, MCH_AUX_VECT) ;
|
|
if ( nDirAuxId != GDB_ID_NULL) {
|
|
const IGeoVector3d* pGV = GetGeoVector3d( m_pGeomDB->GetGeoObj( nDirAuxId)) ;
|
|
if ( pGV != nullptr) {
|
|
Frame3d frHead ; m_pGeomDB->GetGroupGlobFrame( nHeadId, frHead) ;
|
|
vtA = pGV->GetVector() ;
|
|
vtA.ToGlob( frHead) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ExecLineVmill( int nVmId, int nCurrTool, double dVmTdOffs, double dVmAdOffs,
|
|
const Point3d& ptHi, const Vector3d& vtHi, const Vector3d& vtAi, const Frame3d& frVzmI,
|
|
const Point3d& ptHf, const Vector3d& vtHf, const Vector3d& vtAf, const Frame3d& frVzmF)
|
|
{
|
|
// Recupero Zmap
|
|
IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( nVmId)) ;
|
|
if ( pVZM == nullptr) {
|
|
string sOut = " --> GetVolZmap (" + ToString( nVmId) +") Error <--" ;
|
|
LOG_DBG_INFO( GetEMkLogger(), sOut.c_str())
|
|
return false ;
|
|
}
|
|
// Porto gli estremi nel riferimento opportuno dello Zmap
|
|
Point3d ptHiL = ptHi ; ptHiL.ToLoc( frVzmI) ;
|
|
Vector3d vtHiL = vtHi ; vtHiL.ToLoc( frVzmI) ;
|
|
Vector3d vtAiL = vtAi ; vtAiL.ToLoc( frVzmI) ;
|
|
Point3d ptHfL = ptHf ; ptHfL.ToLoc( frVzmF) ;
|
|
Vector3d vtHfL = vtHf ; vtHfL.ToLoc( frVzmF) ;
|
|
Vector3d vtAfL = vtAf ; vtAfL.ToLoc( frVzmF) ;
|
|
// Eventuali offset
|
|
ptHiL += dVmTdOffs * vtHiL + dVmAdOffs * vtAiL ;
|
|
ptHfL += dVmTdOffs * vtHfL + dVmAdOffs * vtAfL ;
|
|
// Log per debug
|
|
if ( ExeGetDebugLevel() >= 10) {
|
|
string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) +
|
|
" Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) +
|
|
") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ;
|
|
LOG_DBG_INFO( GetEMkLogger(), sOut.c_str())
|
|
}
|
|
// Se utensile che non lavora di testa
|
|
if ( ! m_bCutOnTip) {
|
|
// se movimento di testa (angolo movimento verso la testa oltre 5.8deg), non eseguo asportazione
|
|
Vector3d vtDirM = Media( vtHiL, vtHfL) ;
|
|
vtDirM.Normalize() ;
|
|
double dAxMove = ( ptHfL - ptHiL) * vtDirM ;
|
|
if ( dAxMove < -EPS_SMALL) {
|
|
double dMove = ( ptHfL - ptHiL).Len() ;
|
|
if ( dAxMove < -0.1 * abs( dMove))
|
|
return true ;
|
|
}
|
|
}
|
|
// Eseguo
|
|
bool bOk = pVZM->MillingStep( nCurrTool, ptHiL, vtHiL, vtAiL, ptHfL, vtHfL, vtAfL) ;
|
|
if ( ! bOk) {
|
|
if ( ExeGetDebugLevel() < 10) {
|
|
string sOut = "Zmap=" + ToString( nVmId) + " Tool=" + ToString( nCurrTool) +
|
|
" Pi=(" + ToString( ptHiL) + ") Vi=(" + ToString( vtHiL) + ") Ai=(" + ToString( vtAiL) +
|
|
") Pf=(" + ToString( ptHfL) + ") Vf=(" + ToString( vtHfL) + ") Af=(" + ToString( vtAfL) + ")" ;
|
|
LOG_DBG_INFO( GetEMkLogger(), sOut.c_str())
|
|
}
|
|
LOG_DBG_INFO( GetEMkLogger(), " --> MillingStep Error <--")
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ExecCollisionCheck( int& nCdInd, int& nObjInd, int nMoveType)
|
|
{
|
|
// se non ci sono oggetti da controllare o non ci sono grezzi o equivalenti, tutto bene
|
|
if ( ! NeedCollisionCheck())
|
|
return true ;
|
|
// ciclo sui grezzi o equivalenti
|
|
for ( int i = 0 ; i < int( m_CdId.size()) ; ++ i) {
|
|
// se modo hidden è da saltare
|
|
int nMode ;
|
|
if ( m_pGeomDB->GetCalcMode( m_CdId[i], nMode) && nMode == GDB_MD_HIDDEN)
|
|
continue ;
|
|
// verifico se è il grezzo in lavorazione
|
|
bool bIsRaw = ( find( m_VmId.begin(), m_VmId.end(), m_CdId[i]) != m_VmId.end()) ;
|
|
// recupero solido o trimesh, se altro lo salto
|
|
const IVolZmap* pVZM = GetVolZmap( m_pGeomDB->GetGeoObj( m_CdId[i])) ;
|
|
const ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeomDB->GetGeoObj( m_CdId[i])) ;
|
|
if ( pVZM == nullptr && pSTM == nullptr)
|
|
continue ;
|
|
// recupero il riferimento
|
|
Frame3d frCd ; m_pGeomDB->GetGlobFrame( m_CdId[i], frCd) ;
|
|
// 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
|
|
SimulatorSP::SetCollisionMark( int nCdInd, int nObjInd)
|
|
{
|
|
if ( m_pGeomDB == nullptr)
|
|
return false ;
|
|
m_nCollMarkId.clear() ;
|
|
int nCdMarkId = FindCollisionMarkId( m_pGeomDB, m_CdId[nCdInd]) ;
|
|
m_pGeomDB->SetMark( nCdMarkId, GDB_MK_ON) ;
|
|
m_nCollMarkId.push_back( nCdMarkId) ;
|
|
int nCoMarkId = FindCollisionMarkId( m_pGeomDB, m_CollObj[nObjInd].nFrameId) ;
|
|
m_pGeomDB->SetMark( nCoMarkId, GDB_MK_ON_2) ;
|
|
m_nCollMarkId.push_back( nCoMarkId) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::ResetCollisionMark( void)
|
|
{
|
|
if ( m_pGeomDB == nullptr)
|
|
return false ;
|
|
for ( auto nId : m_nCollMarkId)
|
|
m_pGeomDB->ResetMark( nId) ;
|
|
m_nCollMarkId.clear() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::EnableToolTipTrace( bool bEnable)
|
|
{
|
|
if ( bEnable != m_bEnableTrace) {
|
|
if ( bEnable) {
|
|
;
|
|
}
|
|
else {
|
|
int nTraceCrvId = m_pGeomDB->GetFirstInGroup( m_nTraceGroup) ;
|
|
while ( nTraceCrvId != GDB_ID_NULL) {
|
|
m_pGeomDB->SetStatus( nTraceCrvId, GDB_ST_OFF) ;
|
|
nTraceCrvId = m_pGeomDB->GetNext( nTraceCrvId) ;
|
|
}
|
|
m_nCurrTrace = GDB_ID_NULL ;
|
|
}
|
|
}
|
|
m_bEnableTrace = bEnable ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::TraceToolTipMove( int nMoveType)
|
|
{
|
|
// verifico che la tracciatura sia abilitata
|
|
if ( ! m_bEnableTrace)
|
|
return true ;
|
|
// recupero il gruppo per le curve di traccia
|
|
int nTraceGrpId ;
|
|
if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_TOOLTRACE, nTraceGrpId))
|
|
return false ;
|
|
m_nTraceGroup = nTraceGrpId ;
|
|
// recupero posizione utensile corrente
|
|
int nExitId = m_pMachine->GetExitId( m_sHead, m_nExit) ;
|
|
Frame3d frExit ;
|
|
if ( ! m_pGeomDB->GetGroupGlobFrame( nExitId, frExit))
|
|
return false ;
|
|
// determino se tracciare uscita mandrino o punta utensile e aggiusto di conseguenza
|
|
static const string TRACE_ONEXIT = "OnExit" ;
|
|
bool bOnExit = false ;
|
|
m_pGeomDB->GetInfo( m_nTraceGroup, TRACE_ONEXIT, bOnExit) ;
|
|
Point3d ptTip = frExit.Orig() - ( ! bOnExit ? m_dTLen : 0) * frExit.VersZ() ;
|
|
// disabilito gestione segnalazione modifiche progetto
|
|
SetModifiedOff modOff ;
|
|
// eseguo tracciatura
|
|
static const string TRACE_MOVE = "Move" ;
|
|
static const int TRACE_MAX_LINE = 1000 ;
|
|
if ( m_nCurrTrace == GDB_ID_NULL) {
|
|
m_nCurrTrace = ExeCreateGeoPoint( nTraceGrpId, ptTip, GDB_ID_ROOT) ;
|
|
m_pGeomDB->SetInfo( m_nCurrTrace, TRACE_MOVE, nMoveType) ;
|
|
m_pGeomDB->SetStipple( m_nCurrTrace, ( nMoveType == 0 ? 3 : 0), 0x8C8C) ;
|
|
}
|
|
else {
|
|
const ICurveComposite* pCC = GetCurveComposite( m_pGeomDB->GetGeoObj( m_nCurrTrace)) ;
|
|
int nCount = ( pCC != nullptr ? pCC->GetCurveCount() : 0) ;
|
|
int nTraMove ;
|
|
m_pGeomDB->GetInfo( m_nCurrTrace, TRACE_MOVE, nTraMove) ;
|
|
if ( ( nMoveType == 0) == ( nTraMove == 0) && nCount < TRACE_MAX_LINE)
|
|
ExeAddCurveCompoLine( m_nCurrTrace, ptTip, true, GDB_ID_ROOT) ;
|
|
else {
|
|
Point3d ptPrev ; ExeEndPoint( m_nCurrTrace, GDB_ID_ROOT, ptPrev) ;
|
|
m_nCurrTrace = ExeCreateGeoPoint( nTraceGrpId, ptPrev, GDB_ID_ROOT) ;
|
|
ExeAddCurveCompoLine( m_nCurrTrace, ptTip, true, GDB_ID_ROOT) ;
|
|
m_pGeomDB->SetInfo( m_nCurrTrace, TRACE_MOVE, nMoveType) ;
|
|
m_pGeomDB->SetStipple( m_nCurrTrace, ( nMoveType == 0 ? 3 : 0), 0x8C8C) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnInit( void)
|
|
{
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_INIT))
|
|
return true ;
|
|
// chiamo la funzione di ingresso nella simulazione
|
|
return m_pMachine->LuaCallFunction( ON_SIMUL_INIT) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnExit( void)
|
|
{
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_EXIT))
|
|
return true ;
|
|
// chiamo la funzione di uscita dalla simulazione
|
|
return m_pMachine->LuaCallFunction( ON_SIMUL_EXIT) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnProgramStart( bool bFirst)
|
|
{
|
|
// assegno flag inizio simulazione
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIM1ST, bFirst) ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_START))
|
|
return true ;
|
|
// chiamo la funzione di inizio simulazione
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_START) ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnProgramEnd( void)
|
|
{
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_END))
|
|
return true ;
|
|
// chiamo la funzione di fine simulazione
|
|
return m_pMachine->LuaCallFunction( ON_SIMUL_END) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnDispositionStarting( int nOpId, int nOpInd, int nPhase,
|
|
const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand)
|
|
{
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ;
|
|
// assegno nuovo indice di fase
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ;
|
|
// assegno nome e valore riferimento della tavola corrente
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ;
|
|
// assegno flag disposizione passiva
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ;
|
|
// assegno flag disposizione con operazioni manuali
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_STARTING))
|
|
return true ;
|
|
// chiamo la funzione di inizio disposizione
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_STARTING) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnDispositionStart( int nOpId, int nOpInd, int nPhase,
|
|
const string& sTable, const Point3d& ptOri1, bool bEmpty, bool bSomeByHand)
|
|
{
|
|
// assegno identificativo e indice disposizione
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPID, nOpId) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_DISPIND, nOpInd) ;
|
|
// assegno nuovo indice di fase
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_PHASE, nPhase) ;
|
|
// assegno nome e valore riferimento della tavola corrente
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABNAME, sTable) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TABORI1, ptOri1) ;
|
|
// assegno flag disposizione passiva
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EMPTY, bEmpty) ;
|
|
// assegno flag disposizione con operazioni manuali
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SBH, bSomeByHand) ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_START))
|
|
return true ;
|
|
// chiamo la funzione di inizio disposizione
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_START) ;
|
|
// recupero i dati di ritorno
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ;
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnDispositionEnd( void)
|
|
{
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_DISPOSITION_END))
|
|
return true ;
|
|
// chiamo la funzione di fine disposizione
|
|
bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_DISPOSITION_END) ;
|
|
// recupero i dati di ritorno
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_VMILL, m_VmId) ;
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnToolSelect( const string& sTool, const string& sHead, int nExit, const string& sTcPos,
|
|
bool bFirst, bool bFloating, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// reset oggetti per verifica collisione con grezzo
|
|
m_CollObj.clear() ;
|
|
// assegno il nome dell'utensile, la testa e l'uscita
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TOOL, sTool) ||
|
|
! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_HEAD, sHead) ||
|
|
! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_EXIT, nExit) ||
|
|
! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TCPOS, sTcPos) ||
|
|
! 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 ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_SELECT))
|
|
return true ;
|
|
// chiamo la funzione di selezione utensile
|
|
bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_SELECT) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
// recupero dati per verifica collisione
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SAFEDIST, m_dSafeDist) ;
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_CODET, m_CdId) ;
|
|
// verifico codice di errore
|
|
bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
// recupero i dati di ritorno per assi ausiliari
|
|
ResetAuxAxes() ;
|
|
int nNumAuxAxes = 0 ;
|
|
if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0)
|
|
return ( bOk && nErr == 0) ;
|
|
m_AuxAxesName.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesToken.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesInvert.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesOffset.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesLinear.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesVal.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesEnd.reserve( nNumAuxAxes) ;
|
|
for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) {
|
|
string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ;
|
|
string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ;
|
|
if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) &&
|
|
m_pMachine->GetAxisToken( sName, sToken) &&
|
|
m_pMachine->GetAxisInvert( sName, bInvert) &&
|
|
m_pMachine->GetAxisOffset( sName, dOffset) &&
|
|
m_pMachine->GetAxisType( sName, bLinear) &&
|
|
m_pMachine->GetAxisPos( sName, dVal)) {
|
|
// se non è già negli assi principali, lo aggiungo
|
|
if ( find( m_AxesName.begin(), m_AxesName.end(), sName) == m_AxesName.end()) {
|
|
m_AuxAxesName.emplace_back( sName) ;
|
|
m_AuxAxesToken.emplace_back( sToken) ;
|
|
m_AuxAxesInvert.push_back( bInvert) ;
|
|
m_AuxAxesOffset.push_back( dOffset) ;
|
|
m_AuxAxesLinear.push_back( bLinear) ;
|
|
m_AuxAxesVal.emplace_back( dVal) ;
|
|
m_AuxAxesEnd.emplace_back( dVal) ;
|
|
m_AuxAxesLink.emplace_back( 0) ;
|
|
}
|
|
}
|
|
else {
|
|
bOk = false ;
|
|
nErr = ERR_TOOL_SEL ;
|
|
}
|
|
}
|
|
|
|
return ( bOk && nErr == 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnToolDeselect( const string& sNextTool, const string& sNextHead, int nNextExit, const string& sNextTcPos, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// assegno il prossimo utensile
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTOOL, sNextTool) ;
|
|
// assegno la prossima testa
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTHEAD, sNextHead) ;
|
|
// assegno la prossima uscita
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTEXIT, nNextExit) ;
|
|
// assegno l'eventuale prossima posizione nel TC
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_NEXTTCPOS, sNextTcPos) ;
|
|
// reset errore
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_TOOL_DESELECT))
|
|
return bOk ;
|
|
// chiamo la funzione di deselezione utensile
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_TOOL_DESELECT) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
// verifico codice di errore
|
|
bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
return ( bOk && nErr == 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnMachiningStart( int nOpId, int nOpInd, const Point3d& ptMin, const Point3d& ptMax,
|
|
const DBLVECTOR& vAxMin, const DBLVECTOR& vAxMax)
|
|
{
|
|
// assegno identificativo e indice lavorazione
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHID, nOpId) ||
|
|
! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MCHIND, nOpInd))
|
|
return false ;
|
|
// assegno punti estremi dell'ingombro della lavorazione
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMIN, ptMin) ||
|
|
! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MMAX, ptMax))
|
|
return false ;
|
|
// assegno punti estremi dell'ingombro degli assi della lavorazione
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMIN, vAxMin) ||
|
|
! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MAXMAX, vAxMax))
|
|
return false ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_START))
|
|
return true ;
|
|
// chiamo la funzione di inizio disposizione
|
|
bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_START) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnMachiningEnd( void)
|
|
{
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MACHINING_END))
|
|
return true ;
|
|
// chiamo la funzione di fine lavorazione
|
|
bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MACHINING_END) ;
|
|
// 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
|
|
SimulatorSP::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) ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START))
|
|
return bOk ;
|
|
// chiamo la funzione di inizio percorso di lavorazione
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnPathEnd( int nAE)
|
|
{
|
|
// assegno numero di dati ausiliari finali
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXTOT, nAE) ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END))
|
|
return bOk ;
|
|
// chiamo la funzione di fine percorso di lavorazione
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnPathStartAux( int nInd, const string& sAS, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_START_AUX))
|
|
return true ;
|
|
// assegno indice, valore dato ausiliario e resetto errore
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAS) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
// chiamo la funzione di evento ausiliario all'inizio del percorso
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_START_AUX) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
// verifico codice di errore
|
|
bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
return ( bOk && nErr == 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnPathEndAux( int nInd, const string& sAE, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_PATH_END_AUX))
|
|
return true ;
|
|
// assegno indice, valore dato ausiliario e resetto errore
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUXIND, nInd) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_AUX, sAE) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
// chiamo la funzione di evento ausiliario alla fine del percorso
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_PATH_END_AUX) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
// verifico codice di errore
|
|
bOk = bOk && m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
return ( bOk && nErr == 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnMoveStart( const CamData* pCamData, const CamData* pNextCamData, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// recupero e assegno i dati
|
|
// dati generali e reset errore
|
|
bool bOk = m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEID, m_nEntId) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVEIND, m_nEntInd) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVE, pCamData->GetMoveType()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MASK, pCamData->GetAxesMask()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG, pCamData->GetFlag()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_FLAG2, pCamData->GetFlag2()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_INDEX, pCamData->GetIndex()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
// valore degli assi all'inizio e alla fine del movimento
|
|
bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ;
|
|
int nNumAxes = int( m_AxesName.size()) ;
|
|
const DBLVECTOR& AxesEnd = pCamData->GetAxesVal() ;
|
|
for ( int i = 1 ; i <= MAX_AXES ; ++ i) {
|
|
if ( i <= nNumAxes) {
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot), m_AxesVal[i-1]) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot), AxesEnd[i-1]) ;
|
|
}
|
|
else {
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisPrev( i, GLOB_VAR, bIsRobot)) ;
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisValue( i, GLOB_VAR, bIsRobot)) ;
|
|
}
|
|
}
|
|
// versori utensile, correzione e ausiliario alla fine del movimento
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_TDIR, pCamData->GetToolDir()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_CDIR, pCamData->GetCorrDir()) ;
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ADIR, pCamData->GetBackAuxDir()) ;
|
|
// anticipazione di alcuni dati dell'eventuale movimento successivo dello stesso percorso
|
|
if ( pNextCamData != nullptr && pNextCamData->GetAxesStatus() == CamData::AS_OK) {
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_MOVESUCC, pNextCamData->GetMoveType()) ;
|
|
const DBLVECTOR& AxesNext = pNextCamData->GetAxesVal() ;
|
|
for ( int i = 1 ; i <= MAX_AXES ; ++ i) {
|
|
if ( i <= nNumAxes)
|
|
bOk = bOk && m_pMachine->LuaSetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot), AxesNext[i-1]) ;
|
|
else
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ;
|
|
}
|
|
}
|
|
else {
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_MOVESUCC) ;
|
|
for ( int i = 1 ; i <= MAX_AXES ; ++ i)
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GetGlobVarAxisNext( i, GLOB_VAR, bIsRobot)) ;
|
|
}
|
|
// reset abilitazione assi attivi
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_ENABAXES) ;
|
|
// reset numero assi ausiliari
|
|
bOk = bOk && m_pMachine->LuaResetGlobVar( GLOB_VAR + GVAR_AUXAXES) ;
|
|
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_START)) {
|
|
ResetAuxAxes() ;
|
|
return bOk ;
|
|
}
|
|
// chiamo la funzione
|
|
bOk = bOk && m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_START) ;
|
|
// con errore, esco
|
|
if ( ! bOk) {
|
|
ResetAuxAxes() ;
|
|
return false ;
|
|
}
|
|
|
|
// verifico codice di errore
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
if ( nErr != 0)
|
|
return false ;
|
|
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
|
|
// reset assi ausiliari
|
|
ResetAuxAxes() ;
|
|
|
|
// recupero i dati di ritorno
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_MASK, m_nAxesMask) ;
|
|
if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ENABAXES, m_bEnabAxes))
|
|
m_bEnabAxes = true ;
|
|
if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_SHOWAXES, m_bShowAxes))
|
|
m_bShowAxes = m_bEnabAxes ;
|
|
int nNumAuxAxes = 0 ;
|
|
if ( ! m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_AUXAXES, nNumAuxAxes) || nNumAuxAxes == 0)
|
|
return true ;
|
|
m_AuxAxesName.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesToken.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesInvert.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesOffset.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesLinear.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesVal.reserve( nNumAuxAxes) ;
|
|
m_AuxAxesEnd.reserve( nNumAuxAxes) ;
|
|
for ( int i = 1 ; i <= nNumAuxAxes && bOk ; ++ i) {
|
|
string sName ; string sToken ; bool bInvert ; double dOffset ; bool bLinear ; double dVal ; double dEnd ; string sLink ;
|
|
string sAuxAxVal = GLOB_VAR + GVAR_AN ; ReplaceString( sAuxAxVal, "N", ToString( i)) ;
|
|
string sAuxAxName = GLOB_VAR + GVAR_ANN ; ReplaceString( sAuxAxName, "N", ToString( i)) ;
|
|
string sAuxAxMaster = GLOB_VAR + GVAR_ANM ; ReplaceString( sAuxAxMaster, "N", ToString( i)) ;
|
|
if ( m_pMachine->LuaGetGlobVar( sAuxAxName, sName) &&
|
|
m_pMachine->GetAxisToken( sName, sToken) &&
|
|
m_pMachine->GetAxisInvert( sName, bInvert) &&
|
|
m_pMachine->GetAxisOffset( sName, dOffset) &&
|
|
m_pMachine->GetAxisType( sName, bLinear) &&
|
|
m_pMachine->GetAxisPos( sName, dVal)) {
|
|
// se assi principali abilitati e da agganciare ad asse principale
|
|
if ( m_bEnabAxes && m_pMachine->LuaGetGlobVar( sAuxAxMaster, sLink)) {
|
|
bool bNeg = ( sLink.find( '-') != string::npos) ;
|
|
string sMainAxis = sLink ; ReplaceString( sMainAxis, "-", "") ;
|
|
int nInd = 0 ;
|
|
for ( int 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
|
|
SimulatorSP::OnMoveEnd( int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_MOVE_END))
|
|
return true ;
|
|
// reset errore
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr))
|
|
return false ;
|
|
// chiamo la funzione
|
|
bool bOk = m_pMachine->LuaCallFunction( ON_SIMUL_MOVE_END) ;
|
|
// forzo aggiornamento posizione assi (possono essere stati mossi nello script)
|
|
UpdateAxesPos() ;
|
|
// verifico codice di errore
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
return ( bOk && nErr == 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnCollision( int nCdInd, int nObjInd, int& nErr)
|
|
{
|
|
// reset stato di errore da script
|
|
nErr = 0 ;
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_SIMUL_COLLISION))
|
|
return true ;
|
|
// reset stato di errore
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr))
|
|
return false ;
|
|
// assegno identificativi grezzo e oggetto in collisione
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMVMID, m_CdId[nCdInd]))
|
|
return false ;
|
|
if ( ! m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_SIMCOBIND, m_CollObj[nObjInd].nInd))
|
|
return false ;
|
|
// chiamo la funzione
|
|
if ( ! m_pMachine->LuaCallFunction( ON_SIMUL_COLLISION))
|
|
return false ;
|
|
// verifico codice di errore
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
// l'errore standard di collisione è stato portato da 1 a 11 per non collidere con altri tipi di errori
|
|
if ( nErr == 1) {
|
|
nErr = ERR_COLLISION ;
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
}
|
|
// evidenzio le geometrie in collisione
|
|
if ( nErr == ERR_COLLISION) {
|
|
SetCollisionMark( nCdInd, nObjInd) ;
|
|
ExeDraw() ;
|
|
}
|
|
|
|
return ( nErr == 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::OnResetMachine( void)
|
|
{
|
|
// verifico esistenza funzione
|
|
if ( ! m_pMachine->LuaExistsFunction( ON_RESET_MACHINE))
|
|
return true ;
|
|
// eseguo reset macchina
|
|
return m_pMachine->LuaCallFunction( ON_RESET_MACHINE) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::AddCollisionObj( int nInd, bool bToolOn, int nFrameId, int nType,
|
|
const Vector3d& vtMove, double dPar1, double dPar2, double dPar3)
|
|
{
|
|
// verifiche sui parametri
|
|
if ( nInd <= 0 || nFrameId <= GDB_ID_NULL)
|
|
return false ;
|
|
switch ( nType) {
|
|
case MCH_SIM_COB_BOX :
|
|
if ( abs( dPar1) < EPS_SMALL || abs( dPar2) < EPS_SMALL || abs( dPar3) < EPS_SMALL)
|
|
return false ;
|
|
break ;
|
|
case MCH_SIM_COB_CYL :
|
|
if ( dPar1 < EPS_SMALL || abs( dPar2) < EPS_SMALL)
|
|
return false ;
|
|
break ;
|
|
case MCH_SIM_COB_SPHE :
|
|
if ( dPar1 < EPS_SMALL)
|
|
return false ;
|
|
break ;
|
|
case MCH_SIM_COB_CONE :
|
|
if ( ( dPar1 < EPS_SMALL && dPar2 < EPS_SMALL) || dPar3 < EPS_SMALL)
|
|
return false ;
|
|
break ;
|
|
case MCH_SIM_COB_POLY :
|
|
if ( ! ExeSurfIsClosed( nFrameId))
|
|
return false ;
|
|
break ;
|
|
default :
|
|
return false ;
|
|
}
|
|
// aggiungo al vettore
|
|
m_CollObj.emplace_back( nInd, bToolOn, nFrameId, nType, vtMove, dPar1, dPar2, dPar3) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::RemoveCollisionObj( int nFrameId)
|
|
{
|
|
erase_if( m_CollObj, [nFrameId]( CollObj Item) { return ( Item.nFrameId == nFrameId) ; }) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
SimulatorSP::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
|
|
SimulatorSP::SetToolForVmill( const string& sTool, const string& sHead, int nExit, int nFlag, double dPar1, double dPar2,
|
|
const INTVECTOR& vVmill, bool bFirst)
|
|
{
|
|
// disabilito eventuale registrazione comandi EXE (riabilitazione automatica)
|
|
CmdLogOff cmdLogOff ;
|
|
// se vVmill vuoto, esco
|
|
if ( vVmill.empty())
|
|
return true ;
|
|
// se utensile, testa o uscita non definiti, reset ed esco
|
|
if ( IsEmptyOrSpaces( sTool) || IsEmptyOrSpaces( sHead) || nExit < 1) {
|
|
ExeVolZmapResetTools( vVmill) ;
|
|
if ( bFirst)
|
|
m_bEnableVm = false ;
|
|
return false ;
|
|
}
|
|
// imposto utensile come corrente
|
|
string sOldTool ; m_pMchMgr->TdbGetCurrToolParam( TPA_NAME, sOldTool) ;
|
|
if ( sTool != sOldTool && ! m_pMchMgr->TdbSetCurrTool( sTool)) {
|
|
ExeVolZmapResetTools( vVmill) ;
|
|
if ( bFirst)
|
|
m_bEnableVm = false ;
|
|
return false ;
|
|
}
|
|
// recupero dati utensile
|
|
int nInd = 1 ;
|
|
int nType ; m_pMchMgr->TdbGetCurrToolParam( TPA_TYPE, nType) ;
|
|
double dLen ; m_pMchMgr->TdbGetCurrToolParam( TPA_LEN, dLen) ;
|
|
double dDiam ; m_pMchMgr->TdbGetCurrToolParam( TPA_DIAM, dDiam) ;
|
|
double dThick ; m_pMchMgr->TdbGetCurrToolParam( TPA_THICK, dThick) ;
|
|
double dCornR ; m_pMchMgr->TdbGetCurrToolParam( TPA_CORNRAD, dCornR) ;
|
|
double dSideAng ; m_pMchMgr->TdbGetCurrToolParam( TPA_SIDEANG, dSideAng) ;
|
|
double dMaxMat ; m_pMchMgr->TdbGetCurrToolParam( TPA_MAXMAT, dMaxMat) ;
|
|
string sNotes ; m_pMchMgr->TdbGetCurrToolParam( TPA_USERNOTES, sNotes) ;
|
|
// 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
|
|
SimulatorSP::EnableToolsForVmill( bool bEnable)
|
|
{
|
|
m_bEnableVm = bEnable ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
SimulatorSP::MoveAxes( int nMoveType, const SAMVECTOR& vAxNaEpSt)
|
|
{
|
|
// Salvo lo step di simulazione corrente
|
|
double dOrigStep = m_dStep ;
|
|
// Verifico ci siano assi da muovere
|
|
if ( vAxNaEpSt.empty())
|
|
return SIM_AXMV_RES_ERR ;
|
|
// Tipo di cinematica
|
|
bool bIsRobot = m_pMchMgr->GetCurrIsRobot() ;
|
|
// Numero assi da muovere
|
|
int nAxCount = int( vAxNaEpSt.size()) ;
|
|
// Posizioni iniziali
|
|
DBLVECTOR vPrev( nAxCount) ;
|
|
for ( int i = 0 ; i < nAxCount ; ++ i) {
|
|
if ( ! m_pMchMgr->GetAxisPos( vAxNaEpSt[i].sName, vPrev[i]))
|
|
return SIM_AXMV_RES_ERR ;
|
|
}
|
|
// Posizione e direzione attuali degli utensili e riferimenti dei pezzi (per Vmill)
|
|
bool bExecVmill = (( nMoveType != 0 || ! NeedCollisionCheck()) && ! m_VmTool.empty() && ! m_VmId.empty()) ;
|
|
PNTVECTOR vPtNoseI ;
|
|
VCT3DVECTOR vVtDirI ;
|
|
VCT3DVECTOR vVtAuxI ;
|
|
vector<Frame3d> 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) ;
|
|
bool bViewAllFrames = true ;
|
|
int nStep = 1 ;
|
|
for ( int i = 0 ; i < nAxCount ; ++ i) {
|
|
double dMove = abs( vAxNaEpSt[i].dEndPos - vPrev[i]) ;
|
|
double dStep = vAxNaEpSt[i].dStep ;
|
|
if ( dStep < 0) {
|
|
if ( abs( dStep - STEP_FEED) < EPS_SMALL)
|
|
dStep = m_dStep ;
|
|
else if ( abs( dStep - STEP_RAPID) < EPS_SMALL)
|
|
dStep = 4 * m_dStep ;
|
|
else if ( abs( dStep - STEP_RAPROT) < EPS_SMALL) {
|
|
dStep = 0.4 * m_dStep ;
|
|
bViewAllFrames = ( bIsRobot ? true : false) ;
|
|
}
|
|
else { // STEP_COLLROT
|
|
dStep = min( 0.4 * m_dStep, COLL_STEP) ;
|
|
bViewAllFrames = ( bIsRobot ? true : false) ;
|
|
}
|
|
}
|
|
dStep = Clamp( dStep, MIN_STEP, dMaxStep) ;
|
|
int nAxStep = int( dMove / dStep) + 1 ;
|
|
nStep = max( nStep, nAxStep) ;
|
|
}
|
|
// Eseguo il movimento
|
|
for ( int i = 1 ; i <= nStep ; ++ i) {
|
|
// Muovo
|
|
bool bMoveOk = true ;
|
|
double dCoeff = double( i) / nStep ;
|
|
for ( int j = 0 ; j < nAxCount ; ++ j) {
|
|
bMoveOk = m_pMchMgr->SetAxisPos( vAxNaEpSt[j].sName, ( 1 - dCoeff) * vPrev[j] + dCoeff * vAxNaEpSt[j].dEndPos) && bMoveOk ;
|
|
}
|
|
// Se abilitato e richiesto, eseguo eventuale Vmill
|
|
if ( m_bEnableVm && bExecVmill) {
|
|
for ( int j = 0 ; j < int( m_VmTool.size()) ; ++ j) {
|
|
Point3d ptNoseF ; Vector3d vtDirF ; Vector3d vtAuxF ;
|
|
bool bOkF = GetHeadCurrPosDirAux( m_VmTool[j].sHead, m_VmTool[j].nExit, ptNoseF, vtDirF, vtAuxF) ;
|
|
for ( int k = 0 ; k < int( m_VmId.size()) ; ++ k) {
|
|
Frame3d frVzmF ;
|
|
bOkF = m_pGeomDB->GetGlobFrame( m_VmId[k], frVzmF) && bOkF ;
|
|
ExecLineVmill( m_VmId[k], j, m_VmTool[j].dTdOffs, m_VmTool[j].dAdOffs,
|
|
vPtNoseI[j], vVtDirI[j], vVtAuxI[j], vFrVzmI[k], ptNoseF, vtDirF, vtAuxF, frVzmF) ;
|
|
// se ultimo utensile, salvo riferimento per prossimo inizio
|
|
if ( j == int( m_VmTool.size()) - 1)
|
|
vFrVzmI[k] = frVzmF ;
|
|
}
|
|
// aggiorno prossimo inizio
|
|
vPtNoseI[j] = ptNoseF ;
|
|
vVtDirI[j] = vtDirF ;
|
|
vVtAuxI[j] = vtAuxF ;
|
|
}
|
|
}
|
|
// Aggiorno visualizzazione
|
|
if ( bViewAllFrames || ( i % 8) == 0 || i == nStep)
|
|
ExeDraw() ;
|
|
// Verifico collisioni
|
|
int nCdInd, nObjInd ;
|
|
bool bCollCheck = ExecCollisionCheck( nCdInd, nObjInd, nMoveType) ;
|
|
// eventuale tracciamento punto tip utensile
|
|
TraceToolTipMove( nMoveType) ;
|
|
// Se riscontrata collisione
|
|
if ( ! bCollCheck) {
|
|
// Richiamo funzione di convalida collisione
|
|
int nPrevErr ;
|
|
m_pMachine->LuaGetGlobVar( GLOB_VAR + GVAR_ERR, nPrevErr) ;
|
|
int nErr ;
|
|
if ( ! OnCollision( nCdInd, nObjInd, nErr) && nErr == ERR_COLLISION) {
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nErr) ;
|
|
if ( ExeGetEnableUI()) {
|
|
// Box di messaggio : Collisione! AVVERTIMENTO
|
|
ExeMessageBox( ExeGetMsg( 5319), ExeGetMsg( 5315), MB_OK | MB_ICONWARNING) ;
|
|
// Gestione Pausa
|
|
m_nUiStatus = MCH_UISIM_PAUSE ;
|
|
while ( m_nUiStatus == MCH_UISIM_PAUSE) {
|
|
// -11 notifica al simulatore pausa dopo collisione
|
|
ExeProcessEvents( -11, 4) ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
m_pMachine->LuaSetGlobVar( GLOB_VAR + GVAR_ERR, nPrevErr) ;
|
|
}
|
|
}
|
|
// In caso di errore esco
|
|
if ( ! bMoveOk)
|
|
return SIM_AXMV_RES_ERR ;
|
|
// Gestione aggiornamenti...
|
|
if ( ExeGetEnableUI()) {
|
|
// Aggiornamento interfaccia
|
|
ExeProcessEvents( 0, 0) ;
|
|
while ( m_nUiStatus == MCH_UISIM_PAUSE) {
|
|
ExeProcessEvents( 0, 4) ;
|
|
}
|
|
// Gestione Stop
|
|
if ( m_nUiStatus == MCH_UISIM_STOP)
|
|
return SIM_AXMV_RES_STOP ;
|
|
// Se cambia lo step di simulazione in modo significativo ...
|
|
if ( abs( m_dStep - dOrigStep) > 10 || abs( ( m_dStep - dOrigStep) / ( m_dStep + dOrigStep)) > 0.2) {
|
|
double dRat = m_dStep / dOrigStep ;
|
|
for ( int j = 0 ; j < nAxCount ; ++ j) {
|
|
if ( vAxNaEpSt[j].dStep > 0)
|
|
const_cast<double&>( vAxNaEpSt[j].dStep) *= dRat ;
|
|
}
|
|
return MoveAxes( nMoveType, vAxNaEpSt) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return SIM_AXMV_RES_OK ;
|
|
}
|