Simulate: fix reload button causing segfault, make interface changes needed for Python bindings

This commit is contained in:
Levi Burner
2022-05-17 09:37:52 -04:00
parent 447877abef
commit 033ca81db6
4 changed files with 76 additions and 21 deletions
+3 -2
View File
@@ -7,6 +7,7 @@ COMMON=-O2 -I../include -L../lib -std=c++11 -pthread -Wl,-rpath,'$$ORIGIN'/../li
all: all:
$(CC) -c -O2 -fPIC -I../include uitools.c $(CC) -c -O2 -fPIC -I../include uitools.c
$(CXX) -c -O2 -fPIC -I../include simulate.cc $(CXX) -c -O2 -fPIC -I../include simulate.cc
$(CXX) -shared -o libmjsimulate.so simulate.o uitools.o $(CXX) $(COMMON) -shared -Wl,-no-as-needed -Wl,-soname,libmjsimulate.so.2.1.5 -lmujoco -o libmjsimulate.so.2.1.5 simulate.o uitools.o
mv libmjsimulate.so ../lib/libmjsimulate.so mv libmjsimulate.so.2.1.5 ../lib/libmjsimulate.so.2.1.5
ln -sf ../lib/libmjsimulate.so.2.1.5 ../lib/libmjsimulate.so
$(CXX) $(COMMON) -Wl,-no-as-needed main.cc -lmjsimulate -lmujoco -lGL -lglfw -o ../bin/simulate $(CXX) $(COMMON) -Wl,-no-as-needed main.cc -lmjsimulate -lmujoco -lGL -lglfw -o ../bin/simulate
+44 -17
View File
@@ -102,15 +102,37 @@ void SimulateLoop(mj::Simulate& simulate) {
if (simulate.droploadrequest) { if (simulate.droploadrequest) {
mjModel* mnew = LoadModel(simulate.dropfilename, simulate); mjModel* mnew = LoadModel(simulate.dropfilename, simulate);
simulate.droploadrequest = 0;
if (mnew) { if (mnew) {
mjData* dnew = mj_makeData(mnew); mjData* dnew = mj_makeData(mnew);
simulate.load(simulate.dropfilename, mnew, dnew, true); simulate.load(simulate.dropfilename, mnew, dnew, true);
simulate.droploadrequest = 0; m = mnew;
d = dnew;
mj_forward(m, d);
// allocate ctrlnoise
free(ctrlnoise);
ctrlnoise = (mjtNum*) malloc(sizeof(mjtNum)*m->nu);
mju_zero(ctrlnoise, m->nu);
}
}
if (simulate.uiloadrequest) {
mjModel* mnew = LoadModel(simulate.filename, simulate);
simulate.uiloadrequest = 0;
if (mnew) {
mjData* dnew = mj_makeData(mnew);
simulate.load(simulate.filename, mnew, dnew, true);
m = mnew; m = mnew;
d = dnew; d = dnew;
mj_forward(m, d); mj_forward(m, d);
// allocate ctrlnoise
free(ctrlnoise);
ctrlnoise = (mjtNum*) malloc(sizeof(mjtNum)*m->nu);
mju_zero(ctrlnoise, m->nu);
} }
} }
@@ -157,8 +179,8 @@ void SimulateLoop(mj::Simulate& simulate) {
// clear old perturbations, apply new // clear old perturbations, apply new
mju_zero(d->xfrc_applied, 6*m->nbody); mju_zero(d->xfrc_applied, 6*m->nbody);
mjv_applyPerturbPose(m, d, &simulate.pert, 0); // move mocap bodies only simulate.applyposepertubations(0); // move mocap bodies only
mjv_applyPerturbForce(m, d, &simulate.pert); simulate.applyforceperturbations();
// run single step, let next iteration deal with timing // run single step, let next iteration deal with timing
mj_step(m, d); mj_step(m, d);
@@ -171,8 +193,8 @@ void SimulateLoop(mj::Simulate& simulate) {
(glfwGetTime()-tmstart) < refreshfactor/simulate.vmode.refreshRate) { (glfwGetTime()-tmstart) < refreshfactor/simulate.vmode.refreshRate) {
// clear old perturbations, apply new // clear old perturbations, apply new
mju_zero(d->xfrc_applied, 6*m->nbody); mju_zero(d->xfrc_applied, 6*m->nbody);
mjv_applyPerturbPose(m, d, &simulate.pert, 0); // move mocap bodies only simulate.applyposepertubations(0); // move mocap bodies only
mjv_applyPerturbForce(m, d, &simulate.pert); simulate.applyforceperturbations();
// run mj_step // run mj_step
mjtNum prevtm = d->time*simulate.slow_down; mjtNum prevtm = d->time*simulate.slow_down;
@@ -189,7 +211,7 @@ void SimulateLoop(mj::Simulate& simulate) {
// paused // paused
else { else {
// apply pose perturbation // apply pose perturbation
mjv_applyPerturbPose(m, d, &simulate.pert, 1); // move mocap and dynamic bodies simulate.applyposepertubations(1); // move mocap and dynamic bodies
// run mj_forward, to update rendering and joint sliders // run mj_forward, to update rendering and joint sliders
mj_forward(m, d); mj_forward(m, d);
@@ -210,19 +232,9 @@ int main(int argc, const char** argv) {
mju_error("Headers and library have different versions"); mju_error("Headers and library have different versions");
} }
// simulate object for encapsulates UI // simulate object encapsulates the UI
mj::Simulate simulate; mj::Simulate simulate;
// 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);
}
}
// init GLFW // init GLFW
if (!glfwInit()) { if (!glfwInit()) {
mju_error("could not initialize GLFW"); mju_error("could not initialize GLFW");
@@ -231,6 +243,21 @@ int main(int argc, const char** argv) {
// start simulation thread (this creates the UI) // start simulation thread (this creates the UI)
simulate.startthread(); 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);
}
}
SimulateLoop(simulate); SimulateLoop(simulate);
// If simulate loop exited its time to stop the UI // If simulate loop exited its time to stop the UI
+22 -2
View File
@@ -1150,7 +1150,7 @@ void uiEvent(mjuiState* state) {
break; break;
case 2: // Reload case 2: // Reload
simulate->loadrequest = 1; simulate->uiloadrequest = 1;
break; break;
case 3: // Align case 3: // Align
@@ -1548,8 +1548,21 @@ void Simulate::stopthread(void) {
this->renderthreadhandle.join(); this->renderthreadhandle.join();
} }
//------------------------ apply pose perturbations ----------------------------
void Simulate::applyposepertubations(int flg_paused) {
if (this->m != nullptr) {
mjv_applyPerturbPose(this->m, this->d, &this->pert, flg_paused); // move mocap bodies only
}
}
//-------------------- Tell the render thread to load a file ------------------- //------------------------ apply force perturbations ---------------------------
void Simulate::applyforceperturbations(void) {
if (this->m != nullptr) {
mjv_applyPerturbForce(this->m, this->d, &this->pert);
}
}
//-------------------- Tell the render thread to load a file and wait ----------
void Simulate::load(const char* file, void Simulate::load(const char* file,
mjModel* mnew, mjModel* mnew,
mjData* dnew, mjData* dnew,
@@ -1559,6 +1572,13 @@ void Simulate::load(const char* file,
this->delete_old_m_d = delete_old_m_d; this->delete_old_m_d = delete_old_m_d;
mju::strcpy_arr(this->filename, file); mju::strcpy_arr(this->filename, file);
this->loadrequest = 2; this->loadrequest = 2;
// Wait for the render thread to be done loading
// so that we know the old model and data's memory can
// be free'd by the other thread (sometimes python)
while (this->loadrequest > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
} }
//------------------------ load mjb or xml model ------------------------------- //------------------------ load mjb or xml model -------------------------------
+7
View File
@@ -36,6 +36,12 @@ class Simulate {
// Stop the Simulate UI thread // Stop the Simulate UI thread
void stopthread(void); void stopthread(void);
// Apply UI pose perturbations to model and data
void applyposepertubations(int flg_paused);
// Apply UI force perturbations to model and data
void applyforceperturbations(void);
// Request that the Simulate UI thread render a new model // Request that the Simulate UI thread render a new model
// optionally delete the old model and data when done // optionally delete the old model and data when done
void load(const char* file, mjModel* m, mjData* d, bool delete_old_m_d); void load(const char* file, mjModel* m, mjData* d, bool delete_old_m_d);
@@ -91,6 +97,7 @@ class Simulate {
// simulation // simulation
int run = 1; int run = 1;
int key = 0; int key = 0;
int uiloadrequest = 0;
int droploadrequest = 0; int droploadrequest = 0;
int loadrequest = 0; int loadrequest = 0;
// strings // strings