1

プログラムに問題があると思います。外部の追跡システムと継続的に通信し、そこからポイントの座標を取得するオブジェクトを作成する必要があります。このクラスをboost::thread内にラップし、Glutアプリケーションを最初に呼び出す前に、スレッドオブジェクトを作成してデタッチします。

クラスの顕著なメソッドのコードは次のとおりです

boost::mutex resourceMutex;

void Tracker::init()
{  
  boost::mutex::scoped_lock lock(resourceMutex);

  try
  {
    // some initializations
  }
  catch (std::bad_alloc const&)
  {  
     cerr << "Memory allocation fail during init!" << endl;
  }

  try
  {  
     p3dData = (Position3d*)calloc( NUM_MARKERS , sizeof( Position3d ) );
     if ( p3dData==NULL )
       throw std::bad_alloc();
  }
  catch ( std::bad_alloc const&)
  {  
     cerr << "Memory allocation fail during memory allocation!" << endl;
  }

}

void Tracker::update()
{
  boost::mutex::scoped_lock lock(optotrakResourceMutex);
  //... operations on vector< Eigen::Vector3d > points
}

vector<Eigen::Vector3d> &Tracker::getAllPoints()
{
  return points;
}

私のglutTimerFuncは、すべてのフレームがメソッドgetAllPointsを使用してポイントを選択する更新関数を呼び出しますが、トラッカースレッドはそれらを継続的に更新します(実際、データへのアクセスの頻度は異なりますが、スレッドの呼び出しはglut更新関数よりも高速です呼び出します。

プログラムが終了すると、最初にnewで割り当てられたTrackerオブジェクトを削除してから、それを含むスレッドを中断しますが、メモリリークであると思われる奇妙な動作が発生することがあります。

さまざまなアクセス頻度とscoped_lockの使用でデータを取得する方法は正しいですか、それともgetAllPointsメソッドに何らかの注意を払う必要がありますか?

4

1 に答える 1

1

専用のトラッカースレッドがTracker::update()デバイスからローカリゼーションデータを取得するために継続的に呼び出していることを理解しています(NDI Optotrak?)

次に、OpenGLアプリケーションは、を使用してメインスレッドから定期的に最新のポイントにアクセスしますTracker::getAllPoints()

この場合、3DポイントのベクトルはTracker::points、これら2つのスレッド間の共有リソースです。

同時アクセスを防ぐには、現在のコードのように書き込むだけでなく、での書き込み操作update() withでの読み取りの両方をミューテックスで保護する必要があります。getAllPoints()メインスレッドの読み取りコードは、ミューテックスもロックする必要があります。

// In your main application:
void timerFunc()
{
    Tracker* tracker = ...;            // Obtain a pointer to the tracker object
    tracker->LockResourceMutex();      // Enter critical section
    vector< Eigen::Vector3d >& pointsRef = tracker->getAllPoints();
    //... operations on points, protected by the mutex
    tracker->UnlockResourceMutex();    // Leave critical section
}

// In class Tracker:
void Tracker::LockResourceMutex() { optotrakResourceMutex.lock(); }
void Tracker::UnlockResourceMutex() { optotrakResourceMutex.unlock(); }

警告:のポイントでの操作timerFunc()が遅い場合、ミューテックスは長時間ロックされたままになり、を呼び出すときにトラッカースレッドがブロックしますTracker::update()

より良い設計は、参照の代わりに3DポイントベクトルのコピーTracker::getAllPoints()を返すように変更することです。

// In class Tracker:
vector<Eigen::Vector3d> Tracker::getAllPoints()
{
    boost::mutex::scoped_lock lock(optotrakResourceMutex);
    return points; // Will call the std::vector() copy constructor
}

// In your main application:
void timerFunc()
{
    Tracker* tracker = ...;            // Obtain a pointer to the tracker object
    vector< Eigen::Vector3d > myPoints = tracker->getAllPoints();
    //... operations on your own copy if points
}

ミューテックスがTrackerクラスにどのようにカプセル化されているか、そしてどのようにtimerFunc()それについて心配する必要がないかに注意してください。

また、コピー中にのみミューテックスがロックされることに注意してください。3Dベクトルのリストのコピーは、それらに対する数学演算よりも確かに高速になります。

于 2013-11-27T08:13:13.293 に答える