15 m_DeviceId(0), m_SamplingFrequency(
SamplingFrequency(0)), m_PeriodMicroSeconds(0), m_FusionStrategy(eNoFusion), m_SamplesPerFusion(0), m_CollectedFusionSamples(0), m_IsActive(false), m_IsDispatching(false), m_IsInitialized(false), m_pInternalThreadHandel(0), m_IMUEventDispatchers(), m_ReferenceTimeStamp(
CTimeStamp::s_Zero), m_LastFrameTimeStamp(
CTimeStamp::s_Zero)
19 , m_pXsensMTiModule(nullptr)
23 pthread_mutex_init(&m_IsActiveMutex,
nullptr);
24 pthread_mutex_init(&m_IsDispatchingMutex,
nullptr);
25 pthread_mutex_init(&m_EventDispatchersMutex,
nullptr);
26 pthread_mutex_init(&m_DeviceMutex,
nullptr);
31 FinalizeModuleDevice();
46 if (!PortName.length())
48 std::cerr <<
"[IMU Error: Cannot connect to empty port name!]\n\t[Operation result: (PortName.length()==0)]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
52 m_IsInitialized = InitializeDevice(PortName, Frequency);
54 return m_IsInitialized;
59 if (m_IsInitialized && (!m_IsActive))
61 const int Result = pthread_create(&m_pInternalThreadHandel,
nullptr, CIMUDevice::ThreadLoop, (
void*)
this);
65 while (Blocking && !m_IsActive)
84 pthread_join(m_pInternalThreadHandel,
nullptr);
86 while (Blocking && m_IsDispatching)
95 if (SamplesPerFusion > 1)
97 if ((m_FusionStrategy != Strategy) || (m_SamplesPerFusion != SamplesPerFusion))
99 m_FusionStrategy = Strategy;
100 m_SamplesPerFusion = SamplesPerFusion;
101 m_CollectedFusionSamples = 0;
108 std::cerr <<
"[IMU Device error: Cannot set fusion with less than 2 samples per fusion!]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
120 if (pIMUEventDispatcher)
124 if (m_IMUEventDispatchers.find(pIMUEventDispatcher) == m_IMUEventDispatchers.end())
126 pIMUEventDispatcher->
SetIMU(
this);
128 std::pair<std::set<IIMUEventDispatcher*>::iterator,
bool> Result = m_IMUEventDispatchers.insert(pIMUEventDispatcher);
130 return Result.second;
141 if (pIMUEventDispatcher)
144 std::set<IIMUEventDispatcher*>::iterator ppElement = m_IMUEventDispatchers.find(pIMUEventDispatcher);
146 if (ppElement != m_IMUEventDispatchers.end())
148 pIMUEventDispatcher->
SetIMU(
nullptr);
149 m_IMUEventDispatchers.erase(ppElement);
160 void CIMUDevice::UnregisterEventDispatchers()
162 if (m_IMUEventDispatchers.size())
166 for (
auto m_IMUEventDispatcher : m_IMUEventDispatchers)
168 m_IMUEventDispatcher->SetIMU(
nullptr);
171 m_IMUEventDispatchers.clear();
176 #ifdef _IMU_USE_XSENS_DEVICE_
178 bool CIMUDevice::InitializeXsensDevice(
const std::string& PortName,
const SamplingFrequency Frequency)
185 m_pXsensMTiModule =
new Xsens::CXsensMTiModule();
189 std::cerr <<
"[IMU Device error: Cannot open port!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
190 DestroyXsensModuleDevice();
196 std::cerr <<
"[IMU Device error: Cannot set configuration state!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
197 DestroyXsensModuleDevice();
203 std::cerr <<
"[IMU Device error: Cannot set output mode!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
204 DestroyXsensModuleDevice();
210 std::cerr <<
"[IMU Device error: Cannot set sampling period!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
211 DestroyXsensModuleDevice();
215 unsigned long DeviceId;
219 std::cerr <<
"[IMU Device error: Cannot get device ID!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
220 DestroyXsensModuleDevice();
224 m_DeviceId = DeviceId;
228 std::cerr <<
"[IMU Device error: Cannot enter measurement state!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
229 DestroyXsensModuleDevice();
236 void CIMUDevice::FinalizeXsensModuleDevice()
240 while (m_IsActive || m_IsDispatching)
246 DestroyXsensModuleDevice();
251 void CIMUDevice::DestroyXsensModuleDevice()
253 if (m_pXsensMTiModule)
257 m_pXsensMTiModule->
close();
260 delete m_pXsensMTiModule;
261 m_pXsensMTiModule =
nullptr;
273 #ifdef _IMU_USE_XSENS_DEVICE_
299 std::cerr <<
"[IMU Device error: Fail to get sample count!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
303 std::cerr <<
"[IMU Device error: Fail to get quaternion rotation!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
307 std::cerr <<
"[IMU Device error: Fail to get magnetic rotation!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
311 std::cerr <<
"[IMU Device error: Fail to get gyroscope rotation!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
315 std::cerr <<
"[IMU Device error: Fail to get acceleration vector!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
319 std::cerr <<
"[IMU Device error: Fail to read message!]\n\t[Operation result: " << m_pXsensMTiModule->
getLastRetVal() <<
"]\n\t[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
333 if (m_CollectedFusionSamples == m_SamplesPerFusion)
347 ++m_CollectedFusionSamples;
353 const float NormalizationFactor = 1.0f /
float(m_CollectedFusionSamples);
363 m_CollectedFusionSamples = 0;
370 if (m_CollectedFusionSamples == m_SamplesPerFusion)
385 ++m_CollectedFusionSamples;
391 const float NormalizationFactor = 1.0f /
float(m_CollectedFusionSamples);
401 m_CollectedFusionSamples = 0;
426 bool CIMUDevice::InitializeDevice(
const std::string& PortName,
const SamplingFrequency Frequency)
431 #ifdef _IMU_USE_XSENS_DEVICE_
433 if (InitializeXsensDevice(PortName, Frequency))
435 m_SamplingFrequency = Frequency;
436 const int Cylces = 0X1C200 / int(m_SamplingFrequency);
451 void CIMUDevice::FinalizeModuleDevice()
455 #ifdef _IMU_USE_XSENS_DEVICE_
457 FinalizeXsensModuleDevice();
461 UnregisterEventDispatchers();
465 void CIMUDevice::ShouldYield()
469 if (RemainingTime > 0)
471 usleep(__useconds_t(RemainingTime));
475 bool CIMUDevice::DispatchCylcle()
481 switch (m_FusionStrategy)
527 void CIMUDevice::SendEvent(
const CIMUEvent& Event)
530 const unsigned long int TotalDispatchers = m_IMUEventDispatchers.size();
532 if (TotalDispatchers)
534 if (TotalDispatchers == 1)
536 (*m_IMUEventDispatchers.begin())->ReceiveEvent(Event);
539 for (
auto m_IMUEventDispatcher : m_IMUEventDispatchers)
541 m_IMUEventDispatcher->ReceiveEvent(Event);
548 void CIMUDevice::SetReferenceTimeStamps()
551 gettimeofday(&m_ReferenceTimeStamp,
nullptr);
552 gettimeofday(&m_LastFrameTimeStamp,
nullptr);
554 if (m_IMUEventDispatchers.size())
555 for (
auto m_IMUEventDispatcher : m_IMUEventDispatchers)
557 m_IMUEventDispatcher->SetReferenceTimeStamps(m_ReferenceTimeStamp);
568 struct sched_param SchedulingParameters;
570 if (pthread_getschedparam(m_pInternalThreadHandel, &Policy, &SchedulingParameters) == 0)
572 const int MaximalPriority = sched_get_priority_max(ThreadPolicy);
573 const int MinimalPriority = sched_get_priority_min(ThreadPolicy);
574 const int PriorityRange = MaximalPriority - MinimalPriority;
575 const int Priority = int(round(
float(PriorityRange) * NormalizedPriority +
float(MinimalPriority)));
576 SchedulingParameters.sched_priority = Priority;
577 const int Result = pthread_setschedparam(m_pInternalThreadHandel, ThreadPolicy, &SchedulingParameters);
586 std::cerr <<
"[IMU Device error: SetThreadRunnigMode() returns EINVAL!]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
590 std::cerr <<
"[IMU Device error: SetThreadRunnigMode() returns ENOTSUP!]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
594 std::cerr <<
"[IMU Device error: SetThreadRunnigMode() returns EPERM!]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
598 std::cerr <<
"[IMU Device error: SetThreadRunnigMode() returns ESRCH!]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
607 std::cerr <<
"[IMU Device error: SetThreadRunnigMode() cannot set running mode while thread is not active!]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
612 void* CIMUDevice::ThreadLoop(
void* pData)
620 pIMUDevice->m_IsActive = true;
623 pIMUDevice->SetReferenceTimeStamps();
627 while (pIMUDevice->m_IsActive)
629 pIMUDevice->ShouldYield();
632 pIMUDevice->m_IsDispatching = true;
634 const
bool DispatchingResult = pIMUDevice->DispatchCylcle();
636 pIMUDevice->m_IsDispatching = false;
639 if (!DispatchingResult)
641 std::cerr <<
"[IMU Device error: DispatchCylcle() returns false!]\n[Source location: " << __FILE__ <<
":" << __LINE__ <<
"]" << std::endl;
647 if (pIMUDevice->m_IsActive)
650 pIMUDevice->m_IsActive = false;
654 pIMUDevice->SendEvent(CIMUEvent(CIMUEvent::eOnIMUStop, pIMUDevice));