why is the length of mjData.contact always 100?

Discussion in 'Modeling' started by lin, Feb 17, 2018.

  1. lin

    lin

    I use openai Gym and mujoco to simulate some reinforcement learning environments, and need to decide whether bodies collide after each call of env.step().

    The xml is as follows:
    Code:
    <mujoco>
      <compiler angle="degree" coordinate="local" inertiafromgeom="true" />
      <option integrator="RK4" timestep="0.02" />
      <default>
        <joint armature="0" damping="0" limited="false" />
        <geom conaffinity="0" condim="3" density="100" friction="1 0.5 0.5" margin="0.01" rgba="0.8 0.6 0.4 1" />
      </default>
      <asset>
        <texture builtin="gradient" height="100" rgb1="1 1 1" rgb2="0 0 0" type="skybox" width="100" />
        <texture builtin="flat" height="1278" mark="cross" markrgb="1 1 1" name="texgeom" random="0.01" rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" type="cube" width="127" />
        <texture builtin="checker" height="100" name="texplane" rgb1="0 0 0" rgb2="0.8 0.8 0.8" type="2d" width="100" />
        <material name="MatPlane" reflectance="0.5" shininess="1" specular="1" texrepeat="30 30" texture="texplane" />
        <material name="geom" texture="texgeom" texuniform="true" />
      </asset>
      <worldbody>
        <light cutoff="100" diffuse="1 1 1" dir="-0 0 -1.3" directional="true" exponent="1" pos="0 0 1.3" specular=".1 .1 .1" />
        <geom conaffinity="1" condim="3" material="MatPlane" name="floor" pos="0 0 0" rgba="0.8 0.9 0.8 1" size="40 40 40" type="plane" />
        <body name="torso" pos="0 0 0">
          <geom name="pointbody" pos="0 0 0.5" size="0.5" type="sphere" />
          <geom name="pointarrow" pos="0.6 0 0.5" size="0.5 0.1 0.1" type="box" />
          <joint axis="1 0 0" name="ballx" pos="0 0 0" type="slide" />
          <joint axis="0 1 0" name="bally" pos="0 0 0" type="slide" />
          <joint axis="0 0 1" limited="false" name="rot" pos="0 0 0" type="hinge" />
        </body>
      </worldbody>
      <contact>
        <exclude body1="world" body2="world"/>
      </contact>
      <actuator>
        <motor ctrllimited="true" ctrlrange="-1 1" gear="150" joint="ballx" />
        <motor ctrllimited="true" ctrlrange="-0.25 0.25" gear="150" joint="rot" />
      </actuator>
    </mujoco>
    
    When I check the content of mjData.contact, there are always 100 elements, each of them has geom1 and geom2 named "floor". After read the docs, I tryied to use contact.exclude to get rid of them.

    Thus, I add
    <contact>
    <exclude body1="world" body2="world"/>
    </contact>
    to the xml. However, the 100 contacts still exist when inspecting mjData.contact.

    How can I suppress the redundant elements of mjData.contact? Thanks.
     
  2. Emo Todorov

    Emo Todorov Administrator Staff Member

    I am not sure how you inspected mjData.comtact, but I am seeing only one active contact when I simulate your model. The array mjData.contact is preallocated, but only mjData.ncon elements are in it at a given time. The rest is left over from previous iterations and is not used (or could be just 0 if that memory was never touched).

    On a different note, your exclude statement has no effect. You need to specify a pair of bodies. Only the specified bodies are excluded, not their child bodies.
     
  3. lin

    lin

    Thanks for your quick rpely. I'm using mujoco-py developed by OpenAI, and using MjSim.data.contact to check the content. As you said, mjData.contact is preallocated, and each contact is initialized as a pair of geoms of which ids are 0.

    I guess that the mujoco will refresh the content of mjData.contact from the first element at each step. If so, maybe the python version just returns the whole contact list, and I need to extract the first mjData.ncon elements manually.

    On the other hand, I'm not sure what the meaning of "specify a pair of bodies" is. Does it mean that two bodies with different names are required? And how about excluding self-collision that a body has two geoms colliding?

    The last question is about actuator. I want to define the actions of point agent defined in the above xml as "move forward", "turn left", and "turn right". The latter two actions can be implemented using "hinge" easily. But I'm not sure how to realize "move forward". I tried "slide", but it always moves in a fixed direction specifed by the attribute axis (e.g., "1 0 0" above). Is there any way to actuate the agent to "move forward" at each step. Here, "move forward" means that, at each step, the point moves along with the edge of length 0.5 of the box named "pointarrow".

    Thanks!
     
  4. Emo Todorov

    Emo Todorov Administrator Staff Member

    Hopefully mujoco-py exports the field mjData.con, which tells you how many contacts are actually active at any time.

    Bodies are not allowed to collide with themselves, so you don't need to do anything to remove self-collisions. The exclude element expects two bodies with different names.

    The order of the joints matters. If you define the slide before the hinge, the slide axis will always point in the same direction. So you should define the hinge first and then the slide.