Revision: 7723
http://playerstage.svn.sourceforge.net/playerstage/?rev=7723&view=rev
Author: hsujohnhsu
Date: 2009-05-26 18:13:32 +0000 (Tue, 26 May 2009)
Log Message:
-----------
more threads.
1. collision
2. models update
3. physics step
1 and 2 runs in parallel
3 runs after 1 and 2 are done.
Modified Paths:
--------------
code/gazebo/branches/threads/server/Simulator.cc
code/gazebo/branches/threads/server/Simulator.hh
code/gazebo/branches/threads/server/World.cc
code/gazebo/branches/threads/server/World.hh
code/gazebo/branches/threads/server/physics/ode/ODEPhysics.cc
Modified: code/gazebo/branches/threads/server/Simulator.cc
===================================================================
--- code/gazebo/branches/threads/server/Simulator.cc 2009-05-26 17:23:05 UTC
(rev 7722)
+++ code/gazebo/branches/threads/server/Simulator.cc 2009-05-26 18:13:32 UTC
(rev 7723)
@@ -47,7 +47,7 @@
#include "Simulator.hh"
-#define MAX_FRAME_RATE 60
+#define MAX_FRAME_RATE 60.0
using namespace gazebo;
@@ -78,6 +78,13 @@
selectedBody(NULL)
{
this->mutex = new boost::recursive_mutex();
+ this->p_mutex = new boost::mutex();
+ this->c_mutex = new boost::mutex();
+ this->m_mutex = new boost::mutex();
+
+ this->p_cond = new boost::condition_variable();
+ this->c_cond = new boost::condition_variable();
+ this->m_cond = new boost::condition_variable();
}
////////////////////////////////////////////////////////////////////////////////
@@ -115,11 +122,42 @@
this->physicsThread = NULL;
}
- if (this->mutex)
+ if (this->p_mutex)
{
- delete this->mutex;
- this->mutex = NULL;
+ delete this->p_mutex;
+ this->p_mutex = NULL;
}
+
+ if (this->c_mutex)
+ {
+ delete this->c_mutex;
+ this->c_mutex = NULL;
+ }
+
+ if (this->m_mutex)
+ {
+ delete this->m_mutex;
+ this->m_mutex = NULL;
+ }
+
+ if (this->p_cond)
+ {
+ delete this->p_cond;
+ this->p_cond = NULL;
+ }
+
+ if (this->c_cond)
+ {
+ delete this->c_cond;
+ this->c_cond = NULL;
+ }
+
+ if (this->m_cond)
+ {
+ delete this->m_cond;
+ this->m_cond = NULL;
+ }
+
}
////////////////////////////////////////////////////////////////////////////////
@@ -330,8 +368,8 @@
void Simulator::MainLoop()
{
double currTime = 0;
- double lastTime = 0;
- double freq = 30.0;
+ double renderUpdateRate =
std::max(MAX_FRAME_RATE,OgreAdaptor::Instance()->GetUpdateRate());
+ double renderUpdatePeriod = 1.0 / renderUpdateRate;
#ifdef TIMING
double tmpT1 = this->GetWallTime();
@@ -342,13 +380,15 @@
this->physicsThread = new boost::thread(
boost::bind(&Simulator::PhysicsLoop, this));
+ this->prevRenderTime = this->GetRealTime();
+
// Update the gui
while (!this->userQuit)
{
- currTime = this->GetWallTime();
- if ( currTime - lastTime > 1/freq)
+ currTime = this->GetRealTime();
+ if ( currTime - this->prevRenderTime > renderUpdatePeriod)
{
- lastTime = this->GetWallTime();
+ this->prevRenderTime = this->GetRealTime();
OgreAdaptor::Instance()->UpdateCameras();
@@ -359,16 +399,14 @@
World::Instance()->ProcessEntitiesToLoad();
- currTime = this->GetWallTime();
-
- if (currTime - lastTime < 1/freq)
+ if (this->GetRealTime() - this->prevRenderTime < renderUpdatePeriod)
{
- usleep((1/freq - (currTime - lastTime)) * 1e6);
+ usleep((int)((renderUpdatePeriod - (currTime - this->prevRenderTime))
* 1e6));
}
}
else
{
- usleep((1/freq - currTime - lastTime) * 1e6);
+ usleep((int)((renderUpdatePeriod - (currTime - this->prevRenderTime)) *
1e6));
}
}
@@ -467,6 +505,12 @@
}
////////////////////////////////////////////////////////////////////////////////
+bool Simulator::GetUserQuit() const
+{
+ return this->userQuit;
+}
+
+////////////////////////////////////////////////////////////////////////////////
void Simulator::SetUserPause(bool pause)
{
this->userPause = pause;
@@ -617,26 +661,59 @@
double step = world->GetPhysicsEngine()->GetStepTime();
double physicsUpdateRate = world->GetPhysicsEngine()->GetUpdateRate();
- //double renderUpdateRate = OgreAdaptor::Instance()->GetUpdateRate();
double physicsUpdatePeriod = 1.0 / physicsUpdateRate;
- //double renderUpdatePeriod = 1.0 / renderUpdateRate;
double currTime;
this->prevPhysicsTime = this->GetRealTime();
- this->prevRenderTime = this->GetRealTime();
+ /*************************************************/
+ /* */
+ /* thread control */
+ /* */
+ /*************************************************/
+ // spawning thread for collision checking
+ this->collisionsThread = new
boost::thread(boost::bind(&World::CollisionsLoop, world));
+
+ // spawning thread for models update
+ this->modelsThread = new boost::thread(boost::bind(&World::ModelsLoop,
world));
+
+ this->run_collision = true;
+ this->run_models = true;
+
+ /*********************************************/
+ /* loop for physics / constraints update */
+ /*********************************************/
while (!this->userQuit)
{
+ // thread control
+ {
+ boost::lock_guard<boost::mutex> c_lock(*this->c_mutex);
+ this->run_collision=true;
+ boost::lock_guard<boost::mutex> m_lock(*this->m_mutex);
+ this->run_models=true;
+ }
+ this->c_cond->notify_all();
+ this->m_cond->notify_all();
+
+
+
+ // wait for c and m threads to finish
+ boost::unique_lock<boost::mutex> p_lock(*this->p_mutex);
+ while (this->run_collision||this->run_models)
+ {
+ this->p_cond->wait(p_lock);
+ }
+
+
currTime = this->GetRealTime();
if (physicsUpdateRate == 0 ||
currTime - this->prevPhysicsTime >= physicsUpdatePeriod)
{
+ this->prevPhysicsTime = this->GetRealTime();
// Update the physics engine
- //if (!this->GetUserPause() && !this->IsPaused() ||
- // (this->GetUserPause() && this->GetUserStepInc()))
if (!this->IsPaused())
{
this->simTime += step;
@@ -646,15 +723,21 @@
else
{
this->pauseTime += step;
- // this->pause=true;
}
- this->prevPhysicsTime = this->GetRealTime();
-
+ // lock mutex and update physics
{
boost::recursive_mutex::scoped_lock lock(*this->mutex);
- world->Update();
+ //world->Update();
+ world->UpdatePhysics();
}
+
+ // if we are throttling physics update rate
+ // if (physicsUpdateRate != 0 &&
+ // this->GetRealTime() - this->prevPhysicsTime < physicsUpdatePeriod)
+ // {
+ // usleep((physicsUpdatePeriod - (currTime - this->prevRenderTime)) *
1e6);
+ // }
usleep(1);
}
@@ -666,7 +749,16 @@
this->userQuit = true;
break;
}
+
+ // // thread control
+
}
+
+ // // get ready to quit
+ // this->cp_mutex->unlock();
+ // this->mp_mutex->unlock();
+
+
}
////////////////////////////////////////////////////////////////////////////////
@@ -676,4 +768,74 @@
return this->mutex;
}
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+boost::mutex* Simulator::GetC()
+{
+ return this->c_mutex;
+}
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+boost::mutex* Simulator::GetP()
+{
+ return this->p_mutex;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+boost::mutex* Simulator::GetM()
+{
+ return this->m_mutex;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+boost::condition_variable* Simulator::GetPCond()
+{
+ return this->p_cond;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+boost::condition_variable* Simulator::GetCCond()
+{
+ return this->c_cond;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+boost::condition_variable* Simulator::GetMCond()
+{
+ return this->m_cond;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+bool Simulator::RunCollision()
+{
+ return this->run_collision;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+bool Simulator::RunModels()
+{
+ return this->run_models;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+void Simulator::CollisionDone()
+{
+ this->run_collision = false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/// Mutex
+void Simulator::ModelsDone()
+{
+ this->run_models = false;
+}
+
+
Modified: code/gazebo/branches/threads/server/Simulator.hh
===================================================================
--- code/gazebo/branches/threads/server/Simulator.hh 2009-05-26 17:23:05 UTC
(rev 7722)
+++ code/gazebo/branches/threads/server/Simulator.hh 2009-05-26 18:13:32 UTC
(rev 7723)
@@ -34,6 +34,7 @@
namespace boost
{
class recursive_mutex;
+ class mutex;
}
namespace gazebo
@@ -133,6 +134,9 @@
/// \brief Return true if the user has pased
public: bool GetUserPause() const;
+ /// \brief Return true if the user has decided to quit simulation
+ public: bool GetUserQuit() const;
+
/// \brief Set whether the user has paused
public: void SetUserPause(bool pause);
@@ -249,9 +253,36 @@
/// Thread in which to run the gui
private: boost::thread *physicsThread;
+ private: boost::thread *collisionsThread;
+ private: boost::thread *modelsThread;
+ // mutex between rendering and (physics,collision,models update)
private: boost::recursive_mutex *mutex;
+ // mutex for physics, collisions, models update sequence control
+ private: boost::mutex *c_mutex;
+ private: boost::mutex *m_mutex;
+ private: boost::mutex *p_mutex;
+
+ private: boost::condition_variable *p_cond;
+ private: boost::condition_variable *c_cond;
+ private: boost::condition_variable *m_cond;
+
+ public: boost::mutex* GetC();
+ public: boost::mutex* GetP();
+ public: boost::mutex* GetM();
+ public: boost::condition_variable* GetPCond();
+ public: boost::condition_variable* GetCCond();
+ public: boost::condition_variable* GetMCond();
+
+ private: bool run_collision;
+ private: bool run_models;
+
+ public: bool RunCollision();
+ public: bool RunModels();
+ public: void CollisionDone();
+ public: void ModelsDone();
+
//Singleton implementation
private: friend class DestroyerT<Simulator>;
private: friend class SingletonT<Simulator>;
Modified: code/gazebo/branches/threads/server/World.cc
===================================================================
--- code/gazebo/branches/threads/server/World.cc 2009-05-26 17:23:05 UTC
(rev 7722)
+++ code/gazebo/branches/threads/server/World.cc 2009-05-26 18:13:32 UTC
(rev 7723)
@@ -273,6 +273,159 @@
}
////////////////////////////////////////////////////////////////////////////////
+// Update physics / constraints
+void World::UpdatePhysics()
+{
+
+ if (this->simPauseTime > 0)
+ {
+ if (Simulator::Instance()->GetSimTime() >= this->simPauseTime)
+ {
+ //printf("SimTime[%f] PauseTime[%f]\n",
Simulator::Instance()->GetSimTime(), this->simPauseTime);
+
+ this->simPauseTime = 0;
+ Simulator::Instance()->SetPaused(true);
+
+ // Tell the simiface that it's okay to trigger the go ack
+ this->simIface->GoAckPost();
+ }
+ else
+ {
+ Simulator::Instance()->SetPaused(false);
+ }
+ }
+
+#ifdef TIMING
+ double tmpT1 = Simulator::Instance()->GetWallTime();
+#endif
+
+ if (!Simulator::Instance()->IsPaused() &&
+ Simulator::Instance()->GetPhysicsEnabled())
+ {
+ this->physicsEngine->UpdatePhysics();
+ }
+
+#ifdef TIMING
+ double tmpT2 = Simulator::Instance()->GetWallTime();
+ std::cout << " World::Update() Physics engine DT(" << tmpT2-tmpT1 << ")" <<
std::endl;
+#endif
+
+ this->graphics->Update();
+
+#ifdef TIMING
+ double tmpT3 = Simulator::Instance()->GetWallTime();
+ std::cout << " World::Update() graphics DT(" << tmpT3-tmpT2 << ")" <<
std::endl;
+#endif
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Update collision detection
+void World::CollisionsLoop()
+{
+
+ Simulator* simulator = Simulator::Instance();
+
+ // initialize
+ //std::cout << "C: locking pc" << std::endl;
+ //simulator->GetPC()->lock(); // make sure pc is locked before releasing
c_init
+ //std::cout << "C: unlocking c_init" << std::endl;
+ //simulator->GetCInit()->unlock(); // unlock c_init so main thread can begin
+
+ while (!simulator->GetUserQuit())
+ {
+
+ boost::unique_lock<boost::mutex> lock(*simulator->GetC());
+ while (!simulator->RunCollision())
+ {
+ simulator->GetCCond()->wait(lock);
+ }
+
+#ifdef TIMING
+ double tmpT1 = Simulator::Instance()->GetWallTime();
+#endif
+
+ if (!Simulator::Instance()->IsPaused() &&
+ Simulator::Instance()->GetPhysicsEnabled())
+ {
+ boost::recursive_mutex::scoped_lock
lock(*Simulator::Instance()->GetMutex());
+ this->physicsEngine->UpdateCollision();
+ }
+
+#ifdef TIMING
+ double tmpT2 = Simulator::Instance()->GetWallTime();
+ std::cout << " World::Update() Collision DT(" << tmpT2-tmpT1 << ")" <<
std::endl;
+#endif
+
+ // thread control
+ // std::cout << "C: unlocking pc" << std::endl;
+ // simulator->GetPC()->unlock();
+ // std::cout << "C: locking cp" << std::endl;
+ // simulator->GetCP()->lock();
+ // std::cout << "C: locking pc" << std::endl;
+ // simulator->GetPC()->lock();
+ // std::cout << "C: unlocking cp" << std::endl;
+ // simulator->GetCP()->unlock();
+ {
+ boost::lock_guard<boost::mutex> p_lock(*simulator->GetP());
+ simulator->CollisionDone();
+ }
+ simulator->GetPCond()->notify_all();
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Update models and their interfaces
+void World::ModelsLoop()
+{
+
+ Simulator* simulator = Simulator::Instance();
+
+ // initialize
+
+ while (!simulator->GetUserQuit())
+ {
+
+ boost::unique_lock<boost::mutex> lock(*simulator->GetM());
+ while (!simulator->RunModels())
+ {
+ simulator->GetMCond()->wait(lock);
+ }
+
+#ifdef TIMING
+ double tmpT1 = Simulator::Instance()->GetWallTime();
+#endif
+
+ {
+ boost::recursive_mutex::scoped_lock
lock(*Simulator::Instance()->GetMutex());
+ // Update all the models
+ std::vector< Model* >::iterator miter;
+ for (miter=this->models.begin(); miter!=this->models.end(); miter++)
+ {
+ if (*miter)
+ {
+ (*miter)->Update();
+ }
+ }
+ }
+
+#ifdef TIMING
+ double tmpT2 = Simulator::Instance()->GetWallTime();
+ std::cout << " World::Update() ALL Models update DT(" << tmpT2-tmpT1 <<
")" << std::endl;
+#endif
+
+ // thread control
+ {
+ boost::lock_guard<boost::mutex> p_lock(*simulator->GetP());
+ simulator->ModelsDone();
+ }
+ simulator->GetPCond()->notify_all();
+ }
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Process messages
void World::ProcessMessages()
{
Modified: code/gazebo/branches/threads/server/World.hh
===================================================================
--- code/gazebo/branches/threads/server/World.hh 2009-05-26 17:23:05 UTC
(rev 7722)
+++ code/gazebo/branches/threads/server/World.hh 2009-05-26 18:13:32 UTC
(rev 7723)
@@ -82,6 +82,13 @@
/// Update the world
public: void Update();
+ /// Update physics / constraints
+ public: void UpdatePhysics();
+ /// Update collision detection
+ public: void CollisionsLoop();
+ /// Update models and their interfaces
+ public: void ModelsLoop();
+
/// Finilize the world
public: void Fini();
@@ -109,10 +116,6 @@
/// \return The real time
public: double GetRealTime() const;
- /// \brief Get the wall clock time
- /// \return The wall clock time
- public: double GetWallTime() const;
-
/// \brief Load all entities
/// \param node XMLConfg node pointer
/// \param parent Parent of the model to load
Modified: code/gazebo/branches/threads/server/physics/ode/ODEPhysics.cc
===================================================================
--- code/gazebo/branches/threads/server/physics/ode/ODEPhysics.cc
2009-05-26 17:23:05 UTC (rev 7722)
+++ code/gazebo/branches/threads/server/physics/ode/ODEPhysics.cc
2009-05-26 18:13:32 UTC (rev 7723)
@@ -164,47 +164,13 @@
////////////////////////////////////////////////////////////////////////////////
// Update the ODE engine
-// void ODEPhysics::UpdatePhysics()
-// {
-// #ifdef TIMING
-// double tmpT1 = Simulator::Instance()->GetWallTime();
-// #endif
-//
-// // Update the dynamical model
-// if (this->quickStepP->GetValue())
-// dWorldQuickStep(this->worldId, this->stepTimeP->GetValue() );
-// else
-// dWorldStep( this->worldId, this->stepTimeP->GetValue() );
-//
-// #ifdef TIMING
-// double tmpT3 = Simulator::Instance()->GetWallTime();
-// std::cout << " ODE step DT (" << tmpT3-tmpT1 << ")" << std::endl;
-// //std::cout << " Physics Total DT (" << tmpT3-tmpT1 << ")" << std::endl;
-// #endif
-//
-// // Very important to clear out the contact group
-// dJointGroupEmpty( this->contactGroup );
-//
-// }
-
-////////////////////////////////////////////////////////////////////////////////
-// Update the ODE engine
void ODEPhysics::UpdatePhysics()
{
#ifdef TIMING
double tmpT1 = Simulator::Instance()->GetWallTime();
#endif
-
+
this->LockMutex();
- // Do collision detection; this will add contacts to the contact group
- dSpaceCollide( this->spaceId, this, CollisionCallback );
-
- //usleep(1000000);
-#ifdef TIMING
- double tmpT2 = Simulator::Instance()->GetWallTime();
- std::cout << " Collision DT (" << tmpT2-tmpT1 << ")" << std::endl;
-#endif
-
// Update the dynamical model
if (this->quickStepP->GetValue())
dWorldQuickStep(this->worldId, this->stepTimeP->GetValue() );
@@ -212,18 +178,57 @@
dWorldStep( this->worldId, this->stepTimeP->GetValue() );
#ifdef TIMING
- double tmpT3 = Simulator::Instance()->GetWallTime();
- std::cout << " ODE step DT (" << tmpT3-tmpT2 << ")" << std::endl;
- //std::cout << " Physics Total DT (" << tmpT3-tmpT1 << ")" << std::endl;
+ double tmpT2 = Simulator::Instance()->GetWallTime();
+ std::cout << " ODE step DT (" << tmpT2-tmpT1 << ")" << std::endl;
#endif
// Very important to clear out the contact group
dJointGroupEmpty( this->contactGroup );
+ this->UnlockMutex();
- this->UnlockMutex();
+#ifdef TIMING
+ double tmpT3 = Simulator::Instance()->GetWallTime();
+ std::cout << " Empty Joint Group DT (" << tmpT3-tmpT2 << ")" <<
std::endl;
+#endif
}
+////////////////////////////////////////////////////////////////////////////////
+// Update the ODE engine
+// void ODEPhysics::UpdatePhysics()
+// {
+// #ifdef TIMING
+// double tmpT1 = Simulator::Instance()->GetWallTime();
+// #endif
+//
+// this->LockMutex();
+// // Do collision detection; this will add contacts to the contact group
+// dSpaceCollide( this->spaceId, this, CollisionCallback );
+//
+// //usleep(1000000);
+// #ifdef TIMING
+// double tmpT2 = Simulator::Instance()->GetWallTime();
+// std::cout << " Collision DT (" << tmpT2-tmpT1 << ")" << std::endl;
+// #endif
+//
+// // Update the dynamical model
+// if (this->quickStepP->GetValue())
+// dWorldQuickStep(this->worldId, this->stepTimeP->GetValue() );
+// else
+// dWorldStep( this->worldId, this->stepTimeP->GetValue() );
+//
+// #ifdef TIMING
+// double tmpT3 = Simulator::Instance()->GetWallTime();
+// std::cout << " ODE step DT (" << tmpT3-tmpT2 << ")" << std::endl;
+// //std::cout << " Physics Total DT (" << tmpT3-tmpT1 << ")" << std::endl;
+// #endif
+//
+// // Very important to clear out the contact group
+// dJointGroupEmpty( this->contactGroup );
+//
+// this->UnlockMutex();
+// }
+
////////////////////////////////////////////////////////////////////////////////
// Finilize the ODE engine
void ODEPhysics::Fini()
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, &
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit