google-deepmind / dm_control

Google DeepMind's software stack for physics-based simulation and Reinforcement Learning environments, using MuJoCo.
Apache License 2.0
3.63k stars 647 forks source link

Initialize a flexcomp object in PyMJCF #445

Open sachinkundu opened 6 months ago

sachinkundu commented 6 months ago

Mujoco 3.0 introduced flexcomp object for modelling deformable obejcts.

However trying to create a Prop using

class Cloth(prop.Prop):
    """Simple cloth prop that consists of a MuJoco flexcomp."""

    def _build(self, *args, **kwargs):
        del args, kwargs
        mjcf_root = mjcf.RootElement()

        mjcf_root.extension.add('plugin', plugin="mujoco.elasticity.shell")

        # Props need to contain a body called prop_root
        mjcf_root.worldbody.add('body', name='prop_root')

        cloth_object = mjcf.from_file('cloth.xml')
        mjcf_root.attach(cloth_object)

        super()._build('cloth', mjcf_root)

Errors out as flexcomp is not recoginzed as part of schema.

I modified schema.xml(which is part of mjcf under dm_control) and after adding all the tags and attibutes that I am using in an xml such as below

<mujoco model="cloth">
    <extension>
        <plugin plugin="mujoco.elasticity.shell"/>
    </extension>

    <worldbody>
        <body name="cloth">
            <flexcomp type="grid" count="10 5 1" spacing=".025 .025 .025" mass="0.1"
                      name="cloth" radius="0.001">
                <contact condim="6" solref="0.001"/>
                <edge equality="true" damping="0.1"/>
                <plugin plugin="mujoco.elasticity.shell">
                    <config key="poisson" value="0"/>
                    <config key="thickness" value="10e-3"/>
                    <!--Units are in Pa (SI)-->
                    <config key="young" value="3e4"/>
                </plugin>
            </flexcomp>
        </body>
    </worldbody>
</mujoco>

I can get the xml to be parsed and get a Prop object. I looked at composite as an example and copied over the spec as described in mujoco XML reference.

However I cannot get the simulation to run and it fails at this line self._qp_mapper = _CartesianVelocityMapper(qp_params) in dm_robotics/moma/effectors/cartesian_6d_velocity_effector.py. The error is Process finished with exit code 139 (interrupted by signal 11:SIGSEGV) which just sounds like it crashed

I cannot understand why. The whole file which I am running is

"""Minimal working example of the dm_robotics Panda model."""
import dm_env
import numpy as np
from dm_env import specs

from dm_robotics.panda import environment
from dm_robotics.panda import parameters as params
from dm_robotics.panda import run_loop, utils

from dm_robotics.panda import arm_constants

import math
from dm_control import mjcf
from dm_robotics.moma import entity_initializer, prop
from dm_control.composer.variation import distributions, rotations

class Ball(prop.Prop):
    """Simple ball prop that consists of a MuJoco sphere geom."""

    def _build(self, *args, **kwargs):
        del args, kwargs
        mjcf_root = mjcf.RootElement()
        # Props need to contain a body called prop_root
        body = mjcf_root.worldbody.add('body', name='prop_root')
        body.add('geom',
                 type='sphere',
                 size=[0.04],
                 solref=[0.01, 0.5],
                 mass=1,
                 rgba=(1, 0, 0, 1))
        super()._build('ball', mjcf_root)

class Cloth(prop.Prop):
    """Simple cloth prop that consists of a MuJoco flexcomp."""

    def _build(self, *args, **kwargs):
        del args, kwargs
        mjcf_root = mjcf.RootElement()

        mjcf_root.extension.add('plugin', plugin="mujoco.elasticity.shell")

        # Props need to contain a body called prop_root
        mjcf_root.worldbody.add('body', name='prop_root')

        cloth_object = mjcf.from_file('cloth.xml')
        mjcf_root.attach(cloth_object)

        super()._build('cloth', mjcf_root)

class Agent:
    """The agent produces a trajectory tracing the path of an eight
    in the x/y control frame of the robot using end-effector velocities.
    """

    def __init__(self, spec: specs.BoundedArray) -> None:
        self._spec = spec

    def step(self, timestep: dm_env.TimeStep) -> np.ndarray:
        """Computes velocities in the x/y plane parameterized in time."""
        time = timestep.observation['time'][0]
        r = 0.1
        vel_x = r * math.cos(time)  # Derivative of x = sin(t)
        vel_y = r * ((math.cos(time) * math.cos(time)) -
                     (math.sin(time) * math.sin(time)))
        action = np.zeros(shape=self._spec.shape, dtype=self._spec.dtype)
        # The action space of the Cartesian 6D effector corresponds
        # to the linear and angular velocities in x, y and z directions
        # respectively
        action[0] = vel_x
        action[1] = vel_y
        return action

if __name__ == '__main__':
    # We initialize the default configuration for logging
    # and argument parsing. These steps are optional.
    utils.init_logging()
    parser = utils.default_arg_parser()
    args = parser.parse_args()

    # Use RobotParams to customize Panda robots added to the environment.
    robot_params = params.RobotParams(robot_ip=args.robot_ip, actuation=arm_constants.Actuation.CARTESIAN_VELOCITY)
    panda_env = environment.PandaEnvironment(robot_params)

    ball = Ball()
    cloth = Cloth()
    props = [ball, cloth]

    panda_env.add_props(props)
    initialize_props = entity_initializer.prop_initializer.PropPlacer(
        props,
        position=distributions.Uniform(-.5, .5),
        quaternion=rotations.UniformQuaternion())

    panda_env.add_entity_initializers([initialize_props])

    with panda_env.build_task_environment() as env:
        # Print the full action, observation and reward specification
        utils.full_spec(env)
        # Initialize the agent
        agent = Agent(env.action_spec())
        # Run the environment and agent either in headless mode or inside the GUI.
        if args.gui:
            app = utils.ApplicationWithPlot()
            app.launch(env, policy=agent.step)
        else:
            run_loop.run(env, agent, [], max_steps=1000, real_time=True)

Which is just a modification of the basic example in [dm_robotics_panda] (https://github.com/JeanElsner/dm_robotics_panda)

Commenting out creating of Cloth and adding to props list works fine.

ian-chuang commented 5 months ago

I am having a similar issue trying to load a flexcomp object with dm_control PyMJCF.

I have this xml file with my flexcomp object taken from here.

<mujoco model="Flag">
    <!-- Degree of Freedom (nv):  340
         Tendons (ntendon):       288
         Actuators (nu):          0
         Constraints (nefc):      0
         This model of a flag passively flapping in the wind has no constraints and is designed to
         exert smooth dynamics computations.
    -->
      <statistic center=".4 0 .8" extent="1.3"/>

      <option wind="5 5 0" density="10" solver="CG" tolerance="1e-6">
      </option>

      <extension>
        <plugin plugin="mujoco.elasticity.shell"/>
      </extension>

      <worldbody>
        <geom name="floor" type="plane" size="0 0 .1"/>
        <light diffuse=".6 .6 .6" specular="0.2 0.2 0.2" pos="0 0 4" dir="0 0 -1"/>
        <body name="pin" pos="0 0 1.5">
          <flexcomp type="grid" count="9 19 1" spacing=".05 .05 .05" mass="10"
                    name="flag" radius="0.001">
            <edge equality="true" damping="0.001"/>
            <plugin plugin="mujoco.elasticity.shell">
              <config key="poisson" value="0"/>
              <config key="thickness" value="1e-2"/>
              <!--Units are in Pa (SI)-->
              <config key="young" value="3e6"/>
            </plugin>
          </flexcomp>
        </body>
      </worldbody>

      <equality>
        <connect body1="flag_0" anchor="0 0 0"/>
      </equality>
    </mujoco>

I try to compile this using PyMJCF in this code here:

from dm_control import mjcf

mjcf_root = mjcf.from_path("flag_flex.xml")

physics = mjcf.Physics.from_mjcf_model(mjcf_root)

I get this error below:

ValueError: Line 39: error while parsing element <edge>: during initialization of attribute 'equality' of element <edge>: Expect an integer value: got true
yuvaltassa commented 5 months ago

The documentation and the code seem to agree that this is a boolean, @quagla any idea what's going on here?

adityadutt09 commented 1 month ago

I am facing a similar issue. It seem's like dm control does not have support for flexcomp just yet? Just wanted to make sure that this is the case or if there's something I am missing. Here's the code I was trying to implement: ` bag_xml = """

""" bag_physics = dm_mujoco.Physics.from_xml_string(bag_xml) ` The error I get is: `--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[88], [line 1](vscode-notebook-cell:?execution_count=88&line=1) ----> [1](vscode-notebook-cell:?execution_count=88&line=1) bag_physics = dm_mujoco.Physics.from_xml_string(bag_xml) File ~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:436, in Physics.from_xml_string(cls, xml_string, assets) [423](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:423) """A named constructor from a string containing an MJCF XML file. [424](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:424) [425](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:425) Args: (...) [433](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:433) A new `Physics` instance. [434](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:434) """ [435](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:435) model = wrapper.MjModel.from_xml_string(xml_string, assets=assets) --> [436](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:436) return cls.from_model(model) File ~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:419, in Physics.from_model(cls, model) [417](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:417) """A named constructor from a `wrapper.MjModel` instance.""" [418](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:418) data = wrapper.MjData(model) --> [419](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:419) return cls(data) File ~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:123, in Physics.__init__(self, data) [117](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:117) """Initializes a new `Physics` instance. [118](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:118) [119](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:119) Args: [120](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/engine.py:120) data: Instance of `wrapper.MjData`. ... [300](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/index.py:300) def _get_size_name(field_name, struct_name='mjmodel'): [301](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/index.py:301) # Look up size name in metadata. --> [302](https://file+.vscode-resource.vscode-cdn.net/home/adityadutt/Desktop/robot-collab-v2/~/miniconda3/envs/roco/lib/python3.8/site-packages/dm_control/mujoco/index.py:302) return sizes.array_sizes[struct_name][field_name][0] KeyError: 'name_flexadr'`