51 #include <sys/types.h> 60 #include "rnr/rnrconfig.h" 61 #include "rnr/units.h" 64 #ifdef HEK_HAS_SYS_BOARD 66 #endif // HEK_HAS_SYS_BOARD 68 #include "Dynamixel/Dynamixel.h" 69 #include "Dynamixel/DynaComm.h" 70 #include "Dynamixel/DynaServo.h" 71 #include "Dynamixel/DynaChain.h" 72 #include "Dynamixel/DynaBgThread.h" 73 #include "Dynamixel/DynaError.h" 96 #define MEGASEC 1000000 97 #define GIGASEC 1000000000 100 struct timespec now()
105 clock_gettime(CLOCK_REALTIME, &ts);
111 struct timespec add(const struct timespec &t1,
const struct timespec &t2)
115 t3.tv_sec = t1.tv_sec + t2.tv_sec;
116 t3.tv_nsec = t1.tv_nsec + t2.tv_nsec;
118 if( t3.tv_nsec >= GIGASEC )
121 t3.tv_nsec -= GIGASEC;
128 struct timespec sub(const struct timespec &t1,
const struct timespec &t2)
132 t3.tv_sec = t1.tv_sec - t2.tv_sec;
133 t3.tv_nsec = t1.tv_nsec - t2.tv_nsec;
138 t3.tv_nsec += GIGASEC;
145 bool le(
const struct timespec &t1,
const struct timespec &t2)
147 if( t1.tv_sec < t2.tv_sec )
151 else if( t1.tv_sec > t2.tv_sec )
155 else if( t1.tv_nsec < t2.tv_nsec )
159 else if( t1.tv_nsec > t2.tv_nsec )
170 double ttod(
const struct timespec &t)
172 return (
double)t.tv_sec + ((double)t.tv_nsec)/((double)GIGASEC);
180 HekMonitor::HekMonitor()
182 m_eMonState = MonStateIdInit;
184 m_bEStopCond =
false;
185 m_bAlarmCond =
false;
189 #ifdef HEK_HAS_SYS_BOARD 193 #endif // HEK_HAS_SYS_BOARD 195 m_byLimitBits = 0x00;
196 m_byEEAuxBits = 0x00;
199 pthread_mutex_init(&m_mutexMon, NULL);
200 pthread_cond_init(&m_condMon, NULL);
204 m_eMonThState = MonThStateIdExit;
205 m_eMonThStateOld = MonThStateIdInit;
208 HekMonitor::~HekMonitor()
212 pthread_cond_destroy(&m_condMon);
213 pthread_mutex_destroy(&m_mutexMon);
216 int HekMonitor::open(uint_t uHekHwVer,
217 const string &strDevArduino,
218 int nBaudRateArduino)
224 LOGWARN(
"Monitoring hardware already opened.");
228 if( (rc = m_hwif.open(uHekHwVer, strDevArduino, nBaudRateArduino)) < 0 )
230 LOGERROR(
"Hekateros monitor hardware open failed.");
233 else if( (rc = m_hwif.scan()) < 0 )
235 LOGERROR(
"Hekateros monitor hardware scan failed.");
239 if( (rc = createMonThread()) < 0 )
241 LOGERROR(
"Hekateros monitor thread creation failed.");
245 m_eMonState = MonStateIdInit;
248 LOGDIAG2(
"Opened monitoring hardware.");
253 int HekMonitor::close()
261 m_eMonState = MonStateIdInit;
263 m_bEStopCond =
false;
264 m_bAlarmCond =
false;
268 m_opticalLimits.clear();
270 #ifdef HEK_HAS_SYS_BOARD 274 #endif // HEK_HAS_SYS_BOARD 276 m_byLimitBits = 0x00;
277 m_byEEAuxBits = 0x00;
279 LOGDIAG2(
"Closed monitoring hardware.");
290 int HekMonitor::start(
double fHz)
296 LOGERROR(
"Monitor hardware not open.");
297 return -HEK_ECODE_NO_RSRC;
299 else if( m_eMonThState != MonThStateIdIdle )
301 LOGERROR(
"Monitor thread not in idle state.");
302 return -HEK_ECODE_BAD_OP;
304 else if( fHz <= 0.0 )
306 LOGERROR(
"Monitor thread run Hz=%lf invalid.", fHz);
307 return -HEK_ECODE_BAD_OP;
313 m_tPeriod.tv_sec = (time_t)fPeriod;
314 fPeriod -= (double)m_tPeriod.tv_sec;
315 m_tPeriod.tv_nsec = (time_t)(fPeriod * GIGASEC);
319 LOGDIAG3(
"Monitor thread started running at %.1lf Hz.", m_fHz);
321 signalMonThread(MonThStateIdRun);
323 m_eMonState = MonStateIdRunNormal;
328 int HekMonitor::stop()
332 LOGERROR(
"Monitor hardware not open.");
333 return -HEK_ECODE_NO_RSRC;
335 else if( m_eMonThState != MonThStateIdRun )
337 LOGERROR(
"Monitor thread not in run state.");
338 return -HEK_ECODE_BAD_OP;
341 LOGDIAG3(
"Monitor thread stopped - blocked waiting.");
343 signalMonThread(MonThStateIdIdle);
345 m_eMonState = MonStateIdInit;
361 for(i = 0; i < HekOptLimitMaxPerJoint; ++i)
385 m_opticalLimits[opticalLimit.
m_uMask] = opticalLimit;
396 void HekMonitor::markAlarmCond(
bool bAlarmCond)
398 m_bAlarmCond = bAlarmCond;
400 writeAlarmLED(m_bAlarmCond || m_bEStopCond);
403 void HekMonitor::markEStopCond(
bool bEStopCond)
405 m_bEStopCond = bEStopCond;
409 m_bAlarmCond = m_bEStopCond;
412 writeAlarmLED(m_bAlarmCond || m_bEStopCond);
420 byte_t HekMonitor::readLimitSwitches()
428 byVal = m_hwif.cmdReadLimits();
435 byte_t HekMonitor::readEEGpio()
443 byVal = m_hwif.cmdReadAux();
450 int HekMonitor::writeEEGpioPin(byte_t byPin, byte_t byVal)
456 rc = m_hwif.cmdWritePin(byPin, byVal);
463 int HekMonitor::configEEGpioPin(byte_t byPin,
char cDir)
469 rc = m_hwif.cmdConfigPin(byPin, cDir);
476 void HekMonitor::writeAlarmLED(
bool bState)
480 m_hwif.cmdSetAlarmLED(bState? 1: 0);
485 void HekMonitor::testInterface()
489 m_hwif.cmdTestInterface();
499 HekTriState HekMonitor::getJointLimitTriState(
HekRobotJoint *pJoint,
int nLimit)
503 if( uMask == HekIOExpUnassigned )
505 return HekTriStateUnknown;
507 else if( m_opticalLimits[uMask].m_uCurVal & HekIOExpLight )
509 return HekTriStateLight;
513 return HekTriStateDark;
522 int HekMonitor::createMonThread()
526 m_eMonThState = MonThStateIdIdle;
528 rc = pthread_create(&m_threadMon, NULL, HekMonitor::monThread, (
void*)
this);
537 LOGSYSERROR(
"pthread_create()");
538 m_eMonThState = MonThStateIdExit;
545 void HekMonitor::destroyMonThread()
547 signalMonThread(MonThStateIdExit);
551 pthread_cancel(m_threadMon);
552 pthread_join(m_threadMon, NULL);
554 LOGDIAG3(
"Monitor thread canceled.");
561 m_eMonThStateOld = m_eMonThState;
562 m_eMonThState = eNewThState;
563 pthread_cond_signal(&m_condMon);
568 void HekMonitor::idleWait()
572 while( m_eMonThState == MonThStateIdIdle )
574 pthread_cond_wait(&m_condMon, &m_mutexMon);
581 void HekMonitor::runWait()
583 struct timespec tNow = now();
587 m_tStart = add(m_tStart, m_tPeriod);
590 if( le(m_tStart, tNow) )
592 LOGWARN(
"Monitor slipped timing by %lf seconds.",
593 ttod(sub(tNow, m_tStart)));
598 pthread_cond_timedwait(&m_condMon, &m_mutexMon, &m_tStart);
606 switch( eMonThState )
608 case MonThStateIdInit:
610 case MonThStateIdIdle:
612 case MonThStateIdRun:
614 case MonThStateIdExit:
621 #undef HEK_MON_TEST_IF 623 void *HekMonitor::monThread(
void *pArg)
629 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
630 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
635 LOGDIAG3(
"Monitor thread created.");
641 LOGDIAG3(
"Monitor thread: %s -> %s state.",
648 case MonThStateIdIdle:
652 case MonThStateIdRun:
654 #ifdef HEK_MON_TEST_IF 662 case MonThStateIdExit:
666 LOGERROR(
"%d: Unknown monitor state.", pThis->
m_eMonThState);
676 LOGDIAG3(
"Monitor thread exited.");
681 void HekMonitor::monJointLimits()
684 static double TuneBackOffVel =
degToRad(10.0);
686 MapOpticalLimits::iterator iter;
693 if( (m_pDynaChain == NULL) || (m_pKin == NULL) )
698 m_byLimitBits = readLimitSwitches();
700 for(iter = m_opticalLimits.begin(); iter != m_opticalLimits.end(); ++iter)
702 byMask = iter->first;
703 pJoint = iter->second.m_pJoint;
705 byVal = m_byLimitBits & byMask;
710 if( (byVal == HekIOExpDark) && (byVal != iter->second.m_uCurVal) )
716 double fJointCurPos, fJointCurVel;
720 m_pKin->getJointCurPosVel(strJointName, fJointCurPos, fJointCurVel);
722 if( fJointCurPos < pJoint->m_fMinSoftLimitRads )
734 m_pKin->stop(strJointName);
743 iter->second.m_uCurVal = byVal;
747 void HekMonitor::monEEAuxIO()
751 void HekMonitor::monServoAlarms()
756 bool bAlarmState =
false;
758 if( m_pDynaChain == NULL )
776 for(nServoId = m_pDynaChain->IterStart(&iter);
777 nServoId != DYNA_ID_NONE;
778 nServoId = m_pDynaChain->IterNext(&iter))
780 if( (pServo = m_pDynaChain->GetServo(nServoId)) != NULL )
782 if( pServo->GetAlarms() != DYNA_ALARM_NONE )
794 if( bAlarmState != m_bAlarmCond )
796 writeAlarmLED(bAlarmState);
797 m_bAlarmCond = bAlarmState;
void runWait()
Monitor thread block timed wait in run state.
HekOpticalLimit_T m_limit[HekOptLimitMaxPerJoint]
optical limits
HekRobotJoint * m_pJoint
limit switch associated robotic joint
byte_t m_uBit
i/o expander bit position
void idleWait()
Monitor thread block wait in idle state.
HekDesc - Hekateros full robotic manipulator descripition class interface.
double m_fMinSoftLimitRads
joint min soft limit (radians)
void monJointLimits()
Monitor joint (optical) limits for state transitions.
Operational robotic joint description class.
<b><i>Hekateros</i></b> optical limit switches.
Joint points and trajectory class interfaces.
double m_fMinBlackPos
minimum complete occlusion position
Hekateros Robot State classes interface.
<b><i>Hekateros</i></b> Arduino Uno compatible I/O board class interface.
bool doStopAtLimits() const
Get auto-stop at joint electronic limits state.
byte_t m_uCurVal
i/o expander current bit value
Hekateros Monitor Class interface.
double m_fMaxEdgePos
maxinum edge position of occlusion band
Hekateros joint classes interfaces.
double m_fMaxBlackPos
maximum complete occlusion position
MonThStateId m_eMonThState
monitoring thread state
double m_fMinEdgePos
mininum edge position of occlusion band
byte_t m_byOptLimitMask[HekOptLimitMaxPerJoint]
optical limit mask array
const char * getThStateName(MonThStateId eNewState)
Get thread state name string.
std::string m_strName
joint name
byte_t m_uMask
i/o expander bit mask
Top-level package include file.
double degToRad(double d)
Convert degrees to radians.
double m_fMaxSoftLimitRads
joint max soft limit (radians)
void monEEAuxIO()
Monitor End Effector auxillary I/O.
void unlock()
Unlock the monitor thread mutex.
<b><i>Hekateros</i></b> product specification base classes.
MonThStateId
monitor thread states.
<b><i>Hekateros</i></b> power, joint limits, and alarm monitoring class.
Operational robotic joint optical limits class.
Hekateros common utilities.
Robotic joint specification.
void testInterface()
Test interface.
double m_fCenterPos
center of operation position
HekOpticalLimit_T m_limit
optical limit info
The <b><i>Hekateros</i></b> namespace encapsulates all <b><i>Hekateros</i></b> related constructs...
void monServoAlarms()
Monitor servos for alarms.
MonThStateId m_eMonThStateOld
monitoring thread old state