Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialize a flexcomp object in PyMJCF #445

Open
sachinkundu opened this issue Dec 21, 2023 · 4 comments
Open

Initialize a flexcomp object in PyMJCF #445

sachinkundu opened this issue Dec 21, 2023 · 4 comments
Assignees

Comments

@sachinkundu
Copy link

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
Copy link

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
Copy link
Collaborator

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

@adityadutt09
Copy link

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 = """

<!-- Shirt -->
<flexcomp name="bag_flex" type="mesh" radius="0.01" dim="2" pos="0 0 2"
  file="rocobench/envs/assets/objects/meshes/bag0_0.obj">
  <contact solref="0.003" selfcollide="none" />
  <edge equality="true" damping="0.1" />
  <plugin plugin="mujoco.elasticity.shell">
    <config key="poisson" value="0" />
    <config key="thickness" value="8e-3" />
    <config key="young" value="3e5" />
  </plugin>
</flexcomp>

<!-- Lights -->
<light directional="true" diffuse=".2 .2 .2" specular="0 0 0" pos="0 0 5" dir="0 0 -1"
  castshadow="false" />
<light directional="false" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="0 0 4" dir="0 0 -1" />
"""

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
----> 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 """A named constructor from a string containing an MJCF XML file.
424
425 Args:
(...)
433 A new Physics instance.
434 """
435 model = wrapper.MjModel.from_xml_string(xml_string, assets=assets)
--> 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 """A named constructor from a wrapper.MjModel instance."""
418 data = wrapper.MjData(model)
--> 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 """Initializes a new Physics instance.
118
119 Args:
120 data: Instance of wrapper.MjData.
...
300 def _get_size_name(field_name, struct_name='mjmodel'):
301 # Look up size name in metadata.
--> 302 return sizes.array_sizes[struct_name][field_name][0]

KeyError: 'name_flexadr'`

@kidpaul94
Copy link

kidpaul94 commented Nov 12, 2024

Any updates regarding this issue? I'm also facing a very similar issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants