Expose a handle for the Python viewer.

This change also requires user scripts to explicitly synchronize changes to physics state to the viewer. The Simulate class was reconfigured so that certain UI events are handled during this sync operation, outside of the render loop on the main thread. These correspond to operations that require access to the full mjModel/mjData.

To support other, more interactive operations (e.g. camera movements), a new mjvSceneState struct is introduced which captures only the portion of the physics state required for scene re-rendering. The mjvSceneState is updated from mjModel/mjData during the viewer sync operation, and is significantly cheaper than a full mj_copyModel and mj_copyData.

Fixes https://github.com/deepmind/mujoco/issues/796

PiperOrigin-RevId: 525723636
Change-Id: Id08d0210a2c067d5afe85e2bf104f276aeddd75e
This commit is contained in:
Saran Tunyasuvunakool
2023-04-20 05:58:32 -07:00
committed by Copybara-Service
parent 4f5da9c554
commit b362cb4972
34 changed files with 4644 additions and 1088 deletions
+16 -15
View File
@@ -313,7 +313,7 @@ void PhysicsLoop(mj::Simulate& sim) {
{
// lock the sim mutex
const std::lock_guard<std::mutex> lock(sim.mtx);
const std::unique_lock<std::recursive_mutex> lock(sim.mtx);
// run only if model is present
if (m) {
@@ -356,11 +356,6 @@ void PhysicsLoop(mj::Simulate& sim) {
syncSim = d->time;
sim.speed_changed = false;
// clear old perturbations, apply new
mju_zero(d->xfrc_applied, 6*m->nbody);
sim.ApplyPosePerturbations(0); // move mocap bodies only
sim.ApplyForcePerturbations();
// run single step, let next iteration deal with timing
mj_step(m, d);
}
@@ -382,11 +377,6 @@ void PhysicsLoop(mj::Simulate& sim) {
measured = true;
}
// clear old perturbations, apply new
mju_zero(d->xfrc_applied, 6*m->nbody);
sim.ApplyPosePerturbations(0); // move mocap bodies only
sim.ApplyForcePerturbations();
// call mj_step
mj_step(m, d);
@@ -400,9 +390,6 @@ void PhysicsLoop(mj::Simulate& sim) {
// paused
else {
// apply pose perturbation
sim.ApplyPosePerturbations(1); // move mocap and dynamic bodies
// run mj_forward, to update rendering and joint sliders
mj_forward(m, d);
}
@@ -468,9 +455,23 @@ int main(int argc, const char** argv) {
// scan for libraries in the plugin directory to load additional plugins
scanPluginLibraries();
mjvScene scn;
mjv_defaultScene(&scn);
mjvCamera cam;
mjv_defaultCamera(&cam);
mjvOption opt;
mjv_defaultOption(&opt);
mjvPerturb pert;
mjv_defaultPerturb(&pert);
// simulate object encapsulates the UI
auto sim = std::make_unique<mj::Simulate>(
std::make_unique<mj::GlfwAdapter>());
std::make_unique<mj::GlfwAdapter>(),
&scn, &cam, &opt, &pert, /* fully_managed = */ true
);
const char* filename = nullptr;
if (argc > 1) {