opensim-org / opensim-core

SimTK OpenSim C++ libraries and command-line applications, and Java/Python wrapping.
https://opensim.stanford.edu
Apache License 2.0
802 stars 324 forks source link

Pickle opensim #3525

Closed A-Artemis closed 1 year ago

A-Artemis commented 1 year ago

Hi, I have made a opensim environment of type gymnasium.Env and I am trying to pickle this so that I can use multi-processing from the stable-baselines3 RL algorithms.

Stable-baselines3 require that the env be pickled, however I encounter the following error:

  File "/home/aurelien/anaconda3/envs/opensim/lib/python3.11/site-packages/cloudpickle/cloudpickle_fast.py", line 632, in dump
    return Pickler.dump(self, obj)
           ^^^^^^^^^^^^^^^^^^^^^^^
TypeError: cannot pickle 'SwigPyObject' object

The following components in my class that are Swig are:

actuatorSet = {SetActuators} <opensim.simulation.SetActuators; proxy of <Swig Object of type 'OpenSim::Set< OpenSim::Actuator > *' at 0x7f9215165650> >
bodySet = {BodySet} <opensim.simulation.BodySet; proxy of <Swig Object of type 'OpenSim::BodySet *' at 0x7f92151650b0> >
brain = {PrescribedController} <opensim.simulation.PrescribedController; proxy of <Swig Object of type 'OpenSim::PrescribedController *' at 0x7f9215165380> >
contactGeometrySet = {ContactGeometrySet} <opensim.simulation.ContactGeometrySet; proxy of <Swig Object of type 'OpenSim::ContactGeometrySet *' at 0x7f9215165620> >
forceSet = {ForceSet} <opensim.simulation.ForceSet; proxy of <Swig Object of type 'OpenSim::ForceSet *' at 0x7f9215165500> >
jointSet = {JointSet} <opensim.simulation.JointSet; proxy of <Swig Object of type 'OpenSim::JointSet *' at 0x7f92151650e0> >
manager = {Manager} <opensim.simulation.Manager; proxy of <Swig Object of type 'OpenSim::Manager *' at 0x7f9215165890> >
markerSet = {MarkerSet} <opensim.simulation.MarkerSet; proxy of <Swig Object of type 'OpenSim::MarkerSet *' at 0x7f9215165140> >
model = {Model} <opensim.simulation.Model; proxy of <Swig Object of type 'OpenSim::Model *' at 0x7f9215164d50> >
muscleSet = {SetMuscles} <opensim.simulation.SetMuscles; proxy of <Swig Object of type 'OpenSim::Set< Muscle > *' at 0x7f9215165470> >
state = {State} <opensim.simbody.State; proxy of <Swig Object of type 'SimTK::State *' at 0x7f9215165740> >

Is there a way to pickle the opensim functions? Or serialize them in another way?

system details os - Linux 22.04 opensim - 4.4.1 (installed by building the source code from GitHub) python 3.11.4 cloudpickle 2.2.1

nickbianco commented 1 year ago

Hi @A-Artemis. Unfortunately, the Python interface to OpenSim is built on SWIG, so if SwigPyObject is not picklable, I don't think any of the API will be picklable. It's possible that a different approach to the bindings (e.g., pybind11) might work, but we don't have plans to shift away from SWIG at the moment.

A-Artemis commented 1 year ago

Hi @nickbianco thanks for the quick reply. Unfortunately different bindings did not solve the issue.

Would there be a way to implement methods to help serialize the objects? I've had a look at https://stackoverflow.com/questions/65942415/how-to-pickle-serialize-a-swigpyobject and https://github.com/uqfoundation/pathos/issues/148#issuecomment-506052407 are those possible approaches?

nickbianco commented 1 year ago

It might be possible to serialize the objects (the latter approach seems more promising). I'd be happy to review a PR if you want to give it a shot yourself, but internally we have no plans to make any changes to the bindings.

nickbianco commented 1 year ago

Closing due to inactivity.