simulate python: fix cmake, glfw usage, update Python version of physics loop
This commit is contained in:
@@ -62,7 +62,6 @@ add_compile_options("${MUJOCO_HARDEN_COMPILE_OPTIONS}")
|
||||
add_link_options("${MUJOCO_HARDEN_LINK_OPTIONS}")
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter Development)
|
||||
find_package(glfw3 3.3 REQUIRED)
|
||||
|
||||
include(FindOrFetch)
|
||||
|
||||
@@ -116,37 +115,37 @@ if(NOT TARGET mujoco)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ==================== MJSIMULATE LIBRARY ==========================================
|
||||
if(NOT TARGET mjsimulate)
|
||||
find_library(MJSIMULATE_LIBRARY mjsimulate mjsimulate HINTS ${MUJOCO_LIBRARY_DIR} REQUIRED)
|
||||
find_path(MJSIMULATE_INCLUDE mujoco/simulate.h mujoco/uitools.h mujoco/array_safety.h HINTS ${MUJOCO_INCLUDE_DIR} REQUIRED)
|
||||
message("MuJoCo Simulate is at ${MJSIMULATE_LIBRARY}")
|
||||
message("MuJoCo Simulate headers are at ${MJSIMULATE_INCLUDE}")
|
||||
add_library(mjsimulate SHARED IMPORTED)
|
||||
# ==================== LIBSIMULATE LIBRARY ==========================================
|
||||
if(NOT TARGET libsimulate)
|
||||
find_library(LIBSIMULATE_LIBRARY libsimulate libsimulate HINTS ${MUJOCO_LIBRARY_DIR} REQUIRED)
|
||||
find_path(LIBSIMULATE_INCLUDE mujoco/simulate.h mujoco/uitools.h mujoco/array_safety.h HINTS ${MUJOCO_INCLUDE_DIR} REQUIRED)
|
||||
message("MuJoCo Simulate is at ${LIBSIMULATE_LIBRARY}")
|
||||
message("MuJoCo Simulate headers are at ${LIBSIMULATE_INCLUDE}")
|
||||
add_library(libsimulate SHARED IMPORTED)
|
||||
if(WIN32)
|
||||
set_target_properties(mjsimulate PROPERTIES IMPORTED_IMPLIB "${MJSIMULATE_LIBRARY}")
|
||||
set_target_properties(libsimulate PROPERTIES IMPORTED_IMPLIB "${LIBSIMULATE_LIBRARY}")
|
||||
else()
|
||||
set_target_properties(mjsimulate PROPERTIES IMPORTED_LOCATION "${MJSIMULATE_LIBRARY}")
|
||||
set_target_properties(libsimulate PROPERTIES IMPORTED_LOCATION "${LIBSIMULATE_LIBRARY}")
|
||||
endif()
|
||||
target_include_directories(mjsimulate INTERFACE "${MJSIMULATE_INCLUDE}")
|
||||
target_include_directories(libsimulate INTERFACE "${LIBSIMULATE_INCLUDE}")
|
||||
if(APPLE)
|
||||
execute_process(
|
||||
COMMAND otool -XD ${MJSIMULATE_LIBRARY}
|
||||
COMMAND otool -XD ${LIBSIMULATE_LIBRARY}
|
||||
COMMAND head -n 1
|
||||
COMMAND xargs dirname
|
||||
COMMAND xargs echo -n
|
||||
OUTPUT_VARIABLE MJSIMULATE_INSTALL_NAME_DIR
|
||||
OUTPUT_VARIABLE LIBSIMULATE_INSTALL_NAME_DIR
|
||||
)
|
||||
set_target_properties(mjsimulate PROPERTIES INSTALL_NAME_DIR "${MJSIMULATE_INSTALL_NAME_DIR}")
|
||||
set_target_properties(libsimulate PROPERTIES INSTALL_NAME_DIR "${LIBSIMULATE_INSTALL_NAME_DIR}")
|
||||
elseif(UNIX)
|
||||
execute_process(
|
||||
COMMAND objdump -p ${MJSIMULATE_LIBRARY}
|
||||
COMMAND objdump -p ${LIBSIMULATE_LIBRARY}
|
||||
COMMAND grep SONAME
|
||||
COMMAND grep -Po [^\\s]+$
|
||||
COMMAND xargs echo -n
|
||||
OUTPUT_VARIABLE MJSIMULATE_SONAME
|
||||
OUTPUT_VARIABLE LIBSIMULATE_SONAME
|
||||
)
|
||||
set_target_properties(mjsimulate PROPERTIES IMPORTED_SONAME "${MJSIMULATE_SONAME}")
|
||||
set_target_properties(libsimulate PROPERTIES IMPORTED_SONAME "${LIBSIMULATE_SONAME}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -266,7 +265,7 @@ target_link_libraries(errors_header INTERFACE crossplatform func_wrap mujoco)
|
||||
add_library(raw INTERFACE)
|
||||
target_sources(raw INTERFACE raw.h)
|
||||
set_target_properties(raw PROPERTIES PUBLIC_HEADER raw.h)
|
||||
target_link_libraries(raw INTERFACE mujoco mjsimulate)
|
||||
target_link_libraries(raw INTERFACE mujoco)
|
||||
|
||||
add_library(structs_header INTERFACE)
|
||||
target_sources(
|
||||
@@ -344,7 +343,7 @@ target_link_libraries(
|
||||
)
|
||||
|
||||
mujoco_pybind11_module(_constants constants.cc)
|
||||
target_link_libraries(_constants PRIVATE mujoco mjsimulate)
|
||||
target_link_libraries(_constants PRIVATE mujoco)
|
||||
|
||||
mujoco_pybind11_module(_enums enums.cc)
|
||||
target_link_libraries(
|
||||
@@ -408,10 +407,9 @@ target_link_libraries(
|
||||
mujoco_pybind11_module(_simulate simulate.cc)
|
||||
target_link_libraries(
|
||||
_simulate
|
||||
PRIVATE mjsimulate
|
||||
PRIVATE libsimulate
|
||||
mujoco
|
||||
raw
|
||||
glfw
|
||||
structs_header)
|
||||
target_link_options(_simulate PRIVATE -Wl,-no-as-needed)
|
||||
|
||||
@@ -426,7 +424,7 @@ set(LIBRARIES_FOR_WHEEL
|
||||
"$<TARGET_FILE:_simulate>"
|
||||
"$<TARGET_FILE:_structs>"
|
||||
"$<TARGET_FILE:mujoco>"
|
||||
"$<TARGET_FILE:mjsimulate>"
|
||||
"$<TARGET_FILE:libsimulate>"
|
||||
)
|
||||
|
||||
if(MUJOCO_PYTHON_MAKE_WHEEL)
|
||||
@@ -455,6 +453,6 @@ if(MUJOCO_PYTHON_MAKE_WHEEL)
|
||||
_simulate
|
||||
_structs
|
||||
mujoco
|
||||
mjsimulate
|
||||
libsimulate
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/simulate.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
#include <pybind11/cast.h>
|
||||
@@ -79,9 +78,6 @@ PYBIND11_MODULE(_constants, pymodule) {
|
||||
// from mujoco.h
|
||||
X(mjVERSION_HEADER);
|
||||
|
||||
// from simulate.h
|
||||
X(mujoco::Simulate::kMaxFilenameLength);
|
||||
|
||||
#undef X
|
||||
pymodule.attr("mjDISABLESTRING") = MakeTuple(mjDISABLESTRING);
|
||||
pymodule.attr("mjENABLESTRING") = MakeTuple(mjENABLESTRING);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mjrender.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/simulate.h>
|
||||
|
||||
// Type aliases for MuJoCo C structs to allow us refer to consistently refer
|
||||
// to them under the "raw" namespace.
|
||||
@@ -56,9 +55,6 @@ using MjvOption = ::mjvOption;
|
||||
using MjvScene = ::mjvScene;
|
||||
using MjvFigure = ::mjvFigure;
|
||||
|
||||
// From simulate.h
|
||||
using Simulate = ::mujoco::Simulate;
|
||||
|
||||
} // namespace mujoco::raw
|
||||
|
||||
#endif // MUJOCO_PYTHON_RAW_H_
|
||||
|
||||
+32
-38
@@ -34,107 +34,101 @@ namespace {
|
||||
|
||||
namespace py = ::pybind11;
|
||||
|
||||
const auto simulate_doc = R"(
|
||||
Python wrapper for the Simulate class
|
||||
)";
|
||||
|
||||
// We define SimulateWrapper here instead of in structs because
|
||||
// we do not want to make _structs dependent on gflw
|
||||
|
||||
PYBIND11_MODULE(_simulate, pymodule) {
|
||||
namespace py = ::pybind11;
|
||||
|
||||
py::class_<mujoco::raw::Simulate>(pymodule, "Simulate")
|
||||
py::class_<mujoco::Simulate>(pymodule, "Simulate")
|
||||
.def(py::init<>())
|
||||
.def("renderloop",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
simulate.renderloop();
|
||||
},
|
||||
py::call_guard<py::gil_scoped_release>())
|
||||
.def("load",
|
||||
[](mujoco::raw::Simulate& simulate, std::string filename, const MjModelWrapper& m, MjDataWrapper& d, bool delete_old_m_d) {
|
||||
[](mujoco::Simulate& simulate, std::string filename, const MjModelWrapper& m, MjDataWrapper& d) {
|
||||
const raw::MjModel* m_ptr = m.get();
|
||||
raw::MjData* d_ptr = d.get();
|
||||
simulate.load(filename.c_str(), (mjModel*)m_ptr, d_ptr, delete_old_m_d);
|
||||
simulate.load(filename.c_str(), (mjModel*)m_ptr, d_ptr);
|
||||
},
|
||||
py::call_guard<py::gil_scoped_release>())
|
||||
.def("applyposepertubations", &mujoco::raw::Simulate::applyposepertubations)
|
||||
.def("applyforceperturbations", &mujoco::raw::Simulate::applyforceperturbations)
|
||||
.def("applyposepertubations", &mujoco::Simulate::applyposepertubations)
|
||||
.def("applyforceperturbations", &mujoco::Simulate::applyforceperturbations)
|
||||
|
||||
.def("lock", // TODO wrap mutex properly as as seperate pybind11 object?
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
simulate.mtx.lock();
|
||||
},
|
||||
py::call_guard<py::gil_scoped_release>())
|
||||
.def("unlock",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
simulate.mtx.unlock();
|
||||
},
|
||||
py::call_guard<py::gil_scoped_release>())
|
||||
.def_readwrite("ctrlnoisestd", &mujoco::raw::Simulate::ctrlnoisestd)
|
||||
.def_readwrite("ctrlnoiserate", &mujoco::raw::Simulate::ctrlnoiserate)
|
||||
.def_readwrite("slow_down", &mujoco::raw::Simulate::slow_down)
|
||||
.def_readwrite("speed_changed", &mujoco::raw::Simulate::speed_changed)
|
||||
.def("getrefreshRate",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
return simulate.vmode.refreshRate;
|
||||
})
|
||||
.def_readwrite("ctrlnoisestd", &mujoco::Simulate::ctrlnoisestd)
|
||||
.def_readwrite("ctrlnoiserate", &mujoco::Simulate::ctrlnoiserate)
|
||||
|
||||
.def_readwrite("realtimeindex", &mujoco::Simulate::realTimeIndex)
|
||||
.def_readwrite("speedchanged", &mujoco::Simulate::speedChanged)
|
||||
.def_readwrite("measuredslowdown", &mujoco::Simulate::measuredSlowdown)
|
||||
.def_readwrite("refreshrate", &mujoco::Simulate::refreshRate)
|
||||
|
||||
.def_readwrite("busywait", &mujoco::Simulate::busywait)
|
||||
.def_readwrite("run", &mujoco::Simulate::run)
|
||||
|
||||
.def_readwrite("busywait", &mujoco::raw::Simulate::busywait)
|
||||
.def_readwrite("run", &mujoco::raw::Simulate::run)
|
||||
//.def_readwrite("exitrequest", &mujoco::raw::Simulate::exitrequest)
|
||||
.def("getexitrequest",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
return simulate.exitrequest.load();
|
||||
}
|
||||
)
|
||||
.def("setexitrequest",
|
||||
[](mujoco::raw::Simulate& simulate, bool exitrequest) {
|
||||
[](mujoco::Simulate& simulate, bool exitrequest) {
|
||||
simulate.exitrequest.store(exitrequest);
|
||||
}
|
||||
)
|
||||
// .def_readwrite("uiloadrequest", &mujoco::raw::Simulate::uiloadrequest)
|
||||
|
||||
.def("getuiloadrequest",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
return simulate.uiloadrequest.load();
|
||||
}
|
||||
)
|
||||
.def("setuiloadrequest",
|
||||
[](mujoco::raw::Simulate& simulate, int uiloadrequest) {
|
||||
[](mujoco::Simulate& simulate, int uiloadrequest) {
|
||||
simulate.uiloadrequest.store(uiloadrequest);
|
||||
}
|
||||
)
|
||||
.def("uiloadrequest_fetch_sub",
|
||||
[](mujoco::raw::Simulate& simulate, int arg) {
|
||||
[](mujoco::Simulate& simulate, int arg) {
|
||||
simulate.uiloadrequest.fetch_sub(arg);
|
||||
}
|
||||
)
|
||||
// .def_readwrite("droploadrequest", &mujoco::raw::Simulate::droploadrequest)
|
||||
|
||||
.def("getdroploadrequest",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
return simulate.droploadrequest.load();
|
||||
}
|
||||
)
|
||||
.def("setdroploadrequest",
|
||||
[](mujoco::raw::Simulate& simulate, bool droploadrequest) {
|
||||
[](mujoco::Simulate& simulate, bool droploadrequest) {
|
||||
simulate.droploadrequest.store(droploadrequest);
|
||||
}
|
||||
)
|
||||
.def("getdropfilename",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
return (char*)simulate.dropfilename;
|
||||
}
|
||||
)
|
||||
.def("getfilename",
|
||||
[](mujoco::raw::Simulate& simulate) {
|
||||
[](mujoco::Simulate& simulate) {
|
||||
return (char*)simulate.filename;
|
||||
}
|
||||
)
|
||||
.def("setloadError",
|
||||
[](mujoco::raw::Simulate& simulate, std::string& loadError) {
|
||||
[](mujoco::Simulate& simulate, std::string& loadError) {
|
||||
strncpy(simulate.loadError, loadError.c_str(), simulate.kMaxFilenameLength);
|
||||
}
|
||||
);
|
||||
|
||||
pymodule.def("setglfwdlhandle", [](std::uintptr_t dlhandle) { mujoco::setglfwdlhandle(reinterpret_cast<void*>(dlhandle)); });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
+55
-26
@@ -18,6 +18,9 @@ import mujoco
|
||||
from mujoco import _simulate
|
||||
|
||||
import glfw
|
||||
from glfw import _glfw
|
||||
_simulate.setglfwdlhandle(_glfw._handle)
|
||||
|
||||
import numpy as np
|
||||
|
||||
import ctypes
|
||||
@@ -29,6 +32,14 @@ class Simulate(_simulate.Simulate):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# logarithmically spaced realtime slow-down coefficients (percent)
|
||||
self.percentrealtime = [
|
||||
100, 80, 66, 50, 40, 33, 25, 20, 16, 13,
|
||||
10, 8, 6.6, 5.0, 4, 3.3, 2.5, 2, 1.6, 1.3,
|
||||
1, .8, .66, .5, .4, .33, .25, .2, .16, .13,
|
||||
.1
|
||||
]
|
||||
|
||||
def _get_refreshRate(self):
|
||||
return self.getrefreshRate()
|
||||
|
||||
@@ -107,14 +118,14 @@ def load_and_step_model(m, d, simulate, filename, preload_callback=None, load_ca
|
||||
|
||||
if mnew is not None:
|
||||
dnew = mujoco.MjData(mnew)
|
||||
simulate.load(filename, mnew, dnew, False)
|
||||
simulate.load(filename, mnew, dnew)
|
||||
mujoco.mj_forward(mnew, dnew)
|
||||
else:
|
||||
mnew = None
|
||||
dnew = None
|
||||
|
||||
if load_callback is not None:
|
||||
load_callback(mnew, dnew, loadError)
|
||||
load_callback(mnew, dnew)
|
||||
|
||||
return mnew, dnew, loadError
|
||||
|
||||
@@ -132,11 +143,11 @@ def run_physics_loop(simulate, preload_callback=None, load_callback=None, file=N
|
||||
|
||||
# constants
|
||||
syncmisalign = 0.1 # maximum time mis-alignment before re-sync
|
||||
refreshfactor = 0.7 # fraction of refresh available for simulation
|
||||
simrefreshfraction = 0.7 # fraction of refresh available for simulation
|
||||
|
||||
# cpu-sim synchronization point
|
||||
cpusync = 0.0
|
||||
simsync = 0.0
|
||||
synccpu = 0.0
|
||||
syncsim = 0.0
|
||||
|
||||
# run until asked to exit
|
||||
while not simulate.exitrequest:
|
||||
@@ -144,7 +155,6 @@ def run_physics_loop(simulate, preload_callback=None, load_callback=None, file=N
|
||||
simulate.droploadrequest = 0
|
||||
m_, d_, loadError = load_and_step_model(m, d, simulate, simulate.dropfilename,
|
||||
preload_callback, load_callback)
|
||||
|
||||
if m_ is not None:
|
||||
m = m_
|
||||
d = d_
|
||||
@@ -178,28 +188,36 @@ def run_physics_loop(simulate, preload_callback=None, load_callback=None, file=N
|
||||
# running
|
||||
if simulate.run != 0:
|
||||
# record cpu time at start of iteration
|
||||
tmstart = glfw.get_time()
|
||||
startcpu = glfw.get_time()
|
||||
|
||||
elapsedcpu = startcpu - synccpu
|
||||
elapsedsim = d.time - syncsim
|
||||
|
||||
# inject noise
|
||||
if simulate.ctrlnoisestd != 0.0:
|
||||
# convert rate and scale to discrete time given current timestep
|
||||
# convert rate and scale to discrete time (Ornstein–Uhlenbeck)
|
||||
rate = math.exp(-m.opt.timestep / simulate.ctrlnoiserate)
|
||||
scale = simulate.ctrlnoisestd * math.sqrt(1-rate*rate)
|
||||
|
||||
for i in range(m.nu):
|
||||
# update noise
|
||||
ctrlnoise[i] = rate * ctrlnoise[i] + scale * mujoco.mju_standardNormal(None)
|
||||
|
||||
# apply noise
|
||||
d.ctrl[i] = ctrlnoise[i]
|
||||
|
||||
# out-of-sync (for any reason)
|
||||
offset = abs((d.time*simulate.slow_down - simsync) - (tmstart - cpusync))
|
||||
if (d.time*simulate.slow_down < simsync or tmstart < cpusync or cpusync == 0.0 or
|
||||
offset > syncmisalign*simulate.slow_down or simulate.speed_changed):
|
||||
# requested slow-down factor
|
||||
slowdown = 100 / simulate.percentrealtime[simulate.realtimeindex]
|
||||
|
||||
# misalignment condition: distance from target sim time is bigger than syncmisalign
|
||||
misaligned = abs(elapsedcpu/slowdown - elapsedsim) > syncmisalign
|
||||
|
||||
# out-of-sync (for any reason): reset sync times, step
|
||||
if elapsedsim < 0 or elapsedcpu < 0 or synccpu == 0 or misaligned or simulate.speedchanged:
|
||||
# re-sync
|
||||
cpusync = tmstart
|
||||
simsync = d.time*simulate.slow_down
|
||||
simulate.speed_changed = False
|
||||
synccpu = startcpu
|
||||
syncsim = d.time
|
||||
simulate.speedchanged = False
|
||||
|
||||
# clear old perturbations, apply new
|
||||
d.xfrc_applied[:, :] = 0
|
||||
@@ -209,21 +227,30 @@ def run_physics_loop(simulate, preload_callback=None, load_callback=None, file=N
|
||||
# run single step, let next iteration deal with timing
|
||||
mujoco.mj_step(m, d)
|
||||
|
||||
# in-sync
|
||||
# in-sync: step until ahead of cpu
|
||||
else:
|
||||
while ((d.time*simulate.slow_down - simsync) < (glfw.get_time() - cpusync) and
|
||||
(glfw.get_time() - tmstart) < (refreshfactor/simulate.refreshRate)):
|
||||
measured = False
|
||||
prevsim = d.time
|
||||
refreshtime = simrefreshfraction/simulate.refreshrate;
|
||||
|
||||
# step while sim lags behind cpu and within refreshtime
|
||||
while (((d.time - syncsim)*slowdown < (glfw.get_time() - synccpu))
|
||||
and ((glfw.get_time() - startcpu) < refreshtime)):
|
||||
# measure slowdown before first step
|
||||
if not measured and elapsedsim:
|
||||
simulate.measuredslowdown = elapsedcpu / elapsedsim
|
||||
measured = True
|
||||
|
||||
# clear old perturbations, apply new
|
||||
d.xfrc_applied[:, :] = 0
|
||||
simulate.applyposepertubations(0) # move mocap bodies only
|
||||
simulate.applyforceperturbations()
|
||||
|
||||
# run mj_step
|
||||
prevtm = d.time*simulate.slow_down
|
||||
# call mj_step
|
||||
mujoco.mj_step(m, d)
|
||||
|
||||
# break on reset
|
||||
if d.time*simulate.slow_down < prevtm:
|
||||
# break if reset
|
||||
if d.time < prevsim:
|
||||
break
|
||||
|
||||
# paused
|
||||
@@ -237,13 +264,14 @@ def run_physics_loop(simulate, preload_callback=None, load_callback=None, file=N
|
||||
# end exclusive access
|
||||
simulate.unlock()
|
||||
|
||||
def run_simulate_and_physics(file=None, preload_callback=None, load_callback=None):
|
||||
def run_simulate_and_physics(file=None, preload_callback=None, load_callback=None, init=True, terminate=True):
|
||||
# simulate object encapsulates the UI
|
||||
simulate = Simulate()
|
||||
|
||||
# init GLFW
|
||||
if not glfw.init():
|
||||
raise mujoco.FatalError('could not initialize GLFW')
|
||||
if init:
|
||||
if not glfw.init():
|
||||
raise mujoco.FatalError('could not initialize GLFW')
|
||||
|
||||
# if m is not None:
|
||||
physics_thread = threading.Thread(target=lambda: run_physics_loop(simulate, preload_callback=preload_callback, load_callback=load_callback, file=file))
|
||||
@@ -253,4 +281,5 @@ def run_simulate_and_physics(file=None, preload_callback=None, load_callback=Non
|
||||
simulate.renderloop()
|
||||
physics_thread.join()
|
||||
|
||||
glfw.terminate()
|
||||
if terminate:
|
||||
glfw.terminate()
|
||||
|
||||
+5
-4
@@ -63,11 +63,11 @@ def get_mujoco_lib_pattern():
|
||||
|
||||
def get_external_lib_patterns():
|
||||
if platform.system() == 'Windows':
|
||||
return ['mujoco.dll', 'mjsimulate.dll']
|
||||
return ['mujoco.dll', 'libsimulate.dll']
|
||||
elif platform.system() == 'Darwin':
|
||||
return ['libmujoco.*.dylib', 'libmjsimulate.*.dylib']
|
||||
return ['libmujoco.*.dylib', 'liblibsimulate.*.dylib']
|
||||
else:
|
||||
return ['libmujoco.so.*', 'libmjsimulate.so*']
|
||||
return ['libmujoco.so.*', 'liblibsimulate.so*']
|
||||
|
||||
def start_and_end(iterable):
|
||||
it = iter(iterable)
|
||||
@@ -318,7 +318,8 @@ setup(
|
||||
'libmujoco*.so.*',
|
||||
'mujoco.dll',
|
||||
'include/mujoco/*.h',
|
||||
'libmjsimulate*.so*',
|
||||
'liblibsimulate.*.dylib',
|
||||
'liblibsimulate*.so*',
|
||||
]),
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user