Simulate: move all glfw calls to main thread to fix MacOS
This commit is contained in:
+34
-25
@@ -92,7 +92,7 @@ mjModel* LoadModel(const char* file, mj::Simulate& simulate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// simulate in background thread (while rendering in main thread)
|
// simulate in background thread (while rendering in main thread)
|
||||||
void SimulateLoop(mj::Simulate& simulate) {
|
void PhysicsLoop(mj::Simulate& simulate) {
|
||||||
// cpu-sim syncronization point
|
// cpu-sim syncronization point
|
||||||
double cpusync = 0;
|
double cpusync = 0;
|
||||||
mjtNum simsync = 0;
|
mjtNum simsync = 0;
|
||||||
@@ -222,6 +222,31 @@ void SimulateLoop(mj::Simulate& simulate) {
|
|||||||
}
|
}
|
||||||
} // end unnamed namespace
|
} // end unnamed namespace
|
||||||
|
|
||||||
|
//---------------------------------- physics_thread ---------------------------------------
|
||||||
|
void PhysicsThread(mj::Simulate* simulate, const char* filename) {
|
||||||
|
// request loadmodel if file given (otherwise drag-and-drop)
|
||||||
|
if (filename != nullptr) {
|
||||||
|
m = LoadModel(filename, *simulate);
|
||||||
|
if (m) {
|
||||||
|
d = mj_makeData(m);
|
||||||
|
simulate->load(filename, m, d, true);
|
||||||
|
mj_forward(m, d);
|
||||||
|
|
||||||
|
// allocate ctrlnoise
|
||||||
|
free(ctrlnoise);
|
||||||
|
ctrlnoise = (mjtNum*) malloc(sizeof(mjtNum)*m->nu);
|
||||||
|
mju_zero(ctrlnoise, m->nu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicsLoop(*simulate);
|
||||||
|
|
||||||
|
// delete everything we allocated
|
||||||
|
free(ctrlnoise);
|
||||||
|
mj_deleteData(d);
|
||||||
|
mj_deleteModel(m);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------- main -------------------------------------------------
|
//---------------------------------- main -------------------------------------------------
|
||||||
|
|
||||||
// run event loop
|
// run event loop
|
||||||
@@ -240,33 +265,17 @@ int main(int argc, const char** argv) {
|
|||||||
mju_error("could not initialize GLFW");
|
mju_error("could not initialize GLFW");
|
||||||
}
|
}
|
||||||
|
|
||||||
// start simulation thread (this creates the UI)
|
const char* filename = nullptr;
|
||||||
simulate.startthread();
|
if (argc > 1) {
|
||||||
|
filename = argv[1];
|
||||||
// request loadmodel if file given (otherwise drag-and-drop)
|
|
||||||
if (argc>1) {
|
|
||||||
m = LoadModel(argv[1], simulate);
|
|
||||||
if (m) {
|
|
||||||
d = mj_makeData(m);
|
|
||||||
simulate.load(argv[1], m, d, true);
|
|
||||||
mj_forward(m, d);
|
|
||||||
|
|
||||||
// allocate ctrlnoise
|
|
||||||
free(ctrlnoise);
|
|
||||||
ctrlnoise = (mjtNum*) malloc(sizeof(mjtNum)*m->nu);
|
|
||||||
mju_zero(ctrlnoise, m->nu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SimulateLoop(simulate);
|
// start physics thread
|
||||||
|
std::thread physicsthreadhandle = std::thread(&PhysicsThread, &simulate, filename);
|
||||||
|
|
||||||
// If simulate loop exited its time to stop the UI
|
// start simulation UI loop (blocking call)
|
||||||
simulate.stopthread();
|
simulate.renderloop();
|
||||||
|
physicsthreadhandle.join();
|
||||||
// delete everything we allocated
|
|
||||||
free(ctrlnoise);
|
|
||||||
mj_deleteData(d);
|
|
||||||
mj_deleteModel(m);
|
|
||||||
|
|
||||||
// terminate GLFW (crashes with Linux NVidia drivers)
|
// terminate GLFW (crashes with Linux NVidia drivers)
|
||||||
#if defined(__APPLE__) || defined(_WIN32)
|
#if defined(__APPLE__) || defined(_WIN32)
|
||||||
|
|||||||
+1
-19
@@ -1535,18 +1535,6 @@ namespace mju = ::mujoco::sample_util;
|
|||||||
Simulate::Simulate(void) {
|
Simulate::Simulate(void) {
|
||||||
} // TODO constructor is now empty...
|
} // TODO constructor is now empty...
|
||||||
|
|
||||||
//------------------------ start the render thread -----------------------------
|
|
||||||
void Simulate::startthread(void) {
|
|
||||||
this->renderthreadhandle = std::thread(&Simulate::renderthread, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------ stop the render thread ------------------------------
|
|
||||||
void Simulate::stopthread(void) {
|
|
||||||
// stop simulation thread
|
|
||||||
this->exitrequest = 1;
|
|
||||||
this->renderthreadhandle.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------ apply pose perturbations ----------------------------
|
//------------------------ apply pose perturbations ----------------------------
|
||||||
void Simulate::applyposepertubations(int flg_paused) {
|
void Simulate::applyposepertubations(int flg_paused) {
|
||||||
if (this->m != nullptr) {
|
if (this->m != nullptr) {
|
||||||
@@ -1798,7 +1786,7 @@ void Simulate::clearcallback(void) {
|
|||||||
uiClearCallback(this->window);
|
uiClearCallback(this->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Simulate::renderthread(void) {
|
void Simulate::renderloop(void) {
|
||||||
// Set timer callback (milliseconds)
|
// Set timer callback (milliseconds)
|
||||||
mjcb_time = timer;
|
mjcb_time = timer;
|
||||||
|
|
||||||
@@ -1900,12 +1888,6 @@ void Simulate::renderthread(void) {
|
|||||||
this->clearcallback();
|
this->clearcallback();
|
||||||
mjv_freeScene(&this->scn);
|
mjv_freeScene(&this->scn);
|
||||||
mjr_freeContext(&this->con);
|
mjr_freeContext(&this->con);
|
||||||
|
|
||||||
// terminate GLFW (crashes with Linux NVidia drivers)
|
|
||||||
// Must call terminate in this thread on Windows with NVidia drivers (Intel is fine)
|
|
||||||
#if defined(__APPLE__) || defined(_WIN32)
|
|
||||||
glfwTerminate();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mujoco
|
} // namespace mujoco
|
||||||
|
|||||||
+4
-6
@@ -44,7 +44,7 @@ class MJSIMULATEAPI Simulate {
|
|||||||
Simulate(void);
|
Simulate(void);
|
||||||
|
|
||||||
// Start the Simulate UI thread
|
// Start the Simulate UI thread
|
||||||
void startthread(void);
|
// void startthread(void);
|
||||||
|
|
||||||
// Stop the Simulate UI thread
|
// Stop the Simulate UI thread
|
||||||
void stopthread(void);
|
void stopthread(void);
|
||||||
@@ -72,15 +72,13 @@ class MJSIMULATEAPI Simulate {
|
|||||||
// clear callbacks registered in external structures
|
// clear callbacks registered in external structures
|
||||||
void clearcallback(void);
|
void clearcallback(void);
|
||||||
|
|
||||||
// thread to render the UI
|
// loop to render the UI (must be called from main thread because of MacOS)
|
||||||
void renderthread(void);
|
// https://discourse.glfw.org/t/multithreading-glfw/573/5
|
||||||
|
void renderloop(void);
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
static constexpr int kMaxFilenameLength = 1000;
|
static constexpr int kMaxFilenameLength = 1000;
|
||||||
|
|
||||||
// the UI rendering thread
|
|
||||||
std::thread renderthreadhandle;
|
|
||||||
|
|
||||||
// model and data to be visualized
|
// model and data to be visualized
|
||||||
mjModel* mnew = nullptr;
|
mjModel* mnew = nullptr;
|
||||||
mjData* dnew = nullptr;
|
mjData* dnew = nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user