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)
|
||||
void SimulateLoop(mj::Simulate& simulate) {
|
||||
void PhysicsLoop(mj::Simulate& simulate) {
|
||||
// cpu-sim syncronization point
|
||||
double cpusync = 0;
|
||||
mjtNum simsync = 0;
|
||||
@@ -222,6 +222,31 @@ void SimulateLoop(mj::Simulate& simulate) {
|
||||
}
|
||||
} // 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 -------------------------------------------------
|
||||
|
||||
// run event loop
|
||||
@@ -240,33 +265,17 @@ int main(int argc, const char** argv) {
|
||||
mju_error("could not initialize GLFW");
|
||||
}
|
||||
|
||||
// start simulation thread (this creates the UI)
|
||||
simulate.startthread();
|
||||
|
||||
// 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);
|
||||
}
|
||||
const char* filename = nullptr;
|
||||
if (argc > 1) {
|
||||
filename = argv[1];
|
||||
}
|
||||
|
||||
SimulateLoop(simulate);
|
||||
// start physics thread
|
||||
std::thread physicsthreadhandle = std::thread(&PhysicsThread, &simulate, filename);
|
||||
|
||||
// If simulate loop exited its time to stop the UI
|
||||
simulate.stopthread();
|
||||
|
||||
// delete everything we allocated
|
||||
free(ctrlnoise);
|
||||
mj_deleteData(d);
|
||||
mj_deleteModel(m);
|
||||
// start simulation UI loop (blocking call)
|
||||
simulate.renderloop();
|
||||
physicsthreadhandle.join();
|
||||
|
||||
// terminate GLFW (crashes with Linux NVidia drivers)
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
|
||||
+1
-19
@@ -1535,18 +1535,6 @@ namespace mju = ::mujoco::sample_util;
|
||||
Simulate::Simulate(void) {
|
||||
} // 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 ----------------------------
|
||||
void Simulate::applyposepertubations(int flg_paused) {
|
||||
if (this->m != nullptr) {
|
||||
@@ -1798,7 +1786,7 @@ void Simulate::clearcallback(void) {
|
||||
uiClearCallback(this->window);
|
||||
}
|
||||
|
||||
void Simulate::renderthread(void) {
|
||||
void Simulate::renderloop(void) {
|
||||
// Set timer callback (milliseconds)
|
||||
mjcb_time = timer;
|
||||
|
||||
@@ -1900,12 +1888,6 @@ void Simulate::renderthread(void) {
|
||||
this->clearcallback();
|
||||
mjv_freeScene(&this->scn);
|
||||
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
|
||||
|
||||
+4
-6
@@ -44,7 +44,7 @@ class MJSIMULATEAPI Simulate {
|
||||
Simulate(void);
|
||||
|
||||
// Start the Simulate UI thread
|
||||
void startthread(void);
|
||||
// void startthread(void);
|
||||
|
||||
// Stop the Simulate UI thread
|
||||
void stopthread(void);
|
||||
@@ -72,15 +72,13 @@ class MJSIMULATEAPI Simulate {
|
||||
// clear callbacks registered in external structures
|
||||
void clearcallback(void);
|
||||
|
||||
// thread to render the UI
|
||||
void renderthread(void);
|
||||
// loop to render the UI (must be called from main thread because of MacOS)
|
||||
// https://discourse.glfw.org/t/multithreading-glfw/573/5
|
||||
void renderloop(void);
|
||||
|
||||
// constants
|
||||
static constexpr int kMaxFilenameLength = 1000;
|
||||
|
||||
// the UI rendering thread
|
||||
std::thread renderthreadhandle;
|
||||
|
||||
// model and data to be visualized
|
||||
mjModel* mnew = nullptr;
|
||||
mjData* dnew = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user