GazzolaLab / Elastica-RL-control

Code for the cases presented in the paper "Elastica: A compliant mechanics environment for soft robotic control"
MIT License
26 stars 9 forks source link

Issue running with pyelastica==0.2.2.post2 and above #13

Open saultshaker opened 10 months ago

saultshaker commented 10 months ago

Background

I've been able to successfully run all Cases in this repo within a virtual environment. In it, I am using pyelastica==0.1.0.post5

However, if I keep all things the same but changed to pyelastica==0.2.2.post2, I get the following error when I run Case1/logging_bio_args.py

Traceback (most recent call last):
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/elastica/wrappers/constraints.py", line 188, in __call__
    *positions, *directors, *self._args, _system=rod, **self._kwargs
TypeError: __init__() got an unexpected keyword argument '_system'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/saul/Elastica-RL-control/Case1/logging_bio_args.py", line 182, in <module>
    model.learn(total_timesteps=int(args.total_timesteps))
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/stable_baselines/trpo_mpi/trpo_mpi.py", line 333, in learn
    seg = seg_gen.__next__()
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/stable_baselines/common/runners.py", line 89, in traj_segment_generator
    observation = env.reset()
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/stable_baselines/bench/monitor.py", line 80, in reset
    return self.env.reset(**kwargs)
  File "/home/saul/Elastica-RL-control/Case1/set_environment.py", line 610, in reset
    self.simulator.finalize()
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/elastica/wrappers/base_system.py", line 147, in finalize
    finalize()
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/elastica/wrappers/constraints.py", line 63, in _finalize_constraints
    for constraint in self._constraints
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/elastica/wrappers/constraints.py", line 63, in <listcomp>
    for constraint in self._constraints
  File "/home/saul/anaconda3/envs/rlcontrol-2/lib/python3.7/site-packages/elastica/wrappers/constraints.py", line 193, in __call__
    "Unable to construct boundary condition class. Note that:\n"
TypeError: Unable to construct boundary condition class. Note that:
1. Any rod properties needed should be placed first
in the boundary_condition __init__ like so (pos_one, pos_two, <other_args>)
2. Number of requested position and directors such as (1, 2) should match
the __init__ method. eg MyBC.__init__(pos_one, director_one, director_two)
should have the `using` call as .using(MyBC, positions=(1,), directors=(1,-1))

Attempting to find the cause of this error, I believe this the error resulted from the adoption of Mixin and Composition to the code design, which happened after the publication of the Elastica-RL codebase.

Help!

Is there an easy way to adapt this code from Case 1 the WallBoundaryForSphere class to be compatible with pyelastica==0.3.1.post1?

        class WallBoundaryForSphere(FreeRod):
            """

            This class generates a bounded space that sphere can move inside. If sphere
            hits one of the boundaries (walls) of this space, it is reflected in opposite direction
            with the same velocity magnitude.

            """

            def __init__(self, boundaries):
                self.x_boundary_low = boundaries[0]
                self.x_boundary_high = boundaries[1]
                self.y_boundary_low = boundaries[2]
                self.y_boundary_high = boundaries[3]
                self.z_boundary_low = boundaries[4]
                self.z_boundary_high = boundaries[5]

            def constrain_values(self, sphere, time):
                pos_x = sphere.position_collection[0]
                pos_y = sphere.position_collection[1]
                pos_z = sphere.position_collection[2]

                radius = sphere.radius

                vx = sphere.velocity_collection[0]
                vy = sphere.velocity_collection[1]
                vz = sphere.velocity_collection[2]

                if (pos_x - radius) < self.x_boundary_low:
                    sphere.velocity_collection[:] = np.array([-vx, vy, vz])

                if (pos_x + radius) > self.x_boundary_high:
                    sphere.velocity_collection[:] = np.array([-vx, vy, vz])

                if (pos_y - radius) < self.y_boundary_low:
                    sphere.velocity_collection[:] = np.array([vx, -vy, vz])

                if (pos_y + radius) > self.y_boundary_high:
                    sphere.velocity_collection[:] = np.array([vx, -vy, vz])

                if (pos_z - radius) < self.z_boundary_low:
                    sphere.velocity_collection[:] = np.array([vx, vy, -vz])

                if (pos_z + radius) > self.z_boundary_high:
                    sphere.velocity_collection[:] = np.array([vx, vy, -vz])

            def constrain_rates(self, sphere, time):
                pass

Other Information

I am working on an RL project and am trying to recreate Case 1 as a benchmark for my custom system. Specifically, I am trying to recreate the target sphere moving in a bounded box so beautifully illustrated here.

For that system, I am using pyelastica==0.3.1.post1. When trying to recreate the target sphere moving in a bounded box, it seems that the error is being thrown when instantiating the WallBoundaryForSphere class.

I'm happy to provide any additional information or context, thanks in advance!

armantekinalp commented 10 months ago

We stopped updating the this code base, so it is incompatible with newer versions of pyelastica.

In order to fix this error, boundary condition class have to be derived from ConstraintBase . In your fork you can make the change.