(self, easy_align=False, flanges=True, variation=0.0,
             color=(1., 0., 0.))
Initializes a new `Duplo` instance.

    Args:
      easy_align: If True, the studs on the top of the brick will be capsules
        rather than cylinders. This makes alignment easier.
      flanges: Whether to use flanges on the bottom of the brick. These make the
        dynamics more expensive, but allow the bricks to be clicked together in
        partially overlapping configurations.
      variation: A float that controls the amount of variation in stud size (and
        therefore separation force). A value of 1.0 results in a distribution of
        separation forces that approximately matches the empirical distribution
        measured for real Duplo bricks. A value of 0.0 yields a deterministic
        separation force approximately equal to the mode of the empirical
        distribution.
      color: An optional tuple of (R, G, B) values specifying the color of the
        Duplo brick. These should be floats between 0 and 1. The default is red.

    Raises:
      ValueError: If `color` contains any value that is not between 0 and 1.
Initializes a new `Duplo` instance.
Initializes a new Duplo instance .
def _build(self, easy_align=False, flanges=True, variation=0.0,
             color=(1., 0., 0.)):
    """Initializes a new `Duplo` instance.

    Args:
      easy_align: If True, the studs on the top of the brick will be capsules
        rather than cylinders. This makes alignment easier.
      flanges: Whether to use flanges on the bottom of the brick. These make the
        dynamics more expensive, but allow the bricks to be clicked together in
        partially overlapping configurations.
      variation: A float that controls the amount of variation in stud size (and
        therefore separation force). A value of 1.0 results in a distribution of
        separation forces that approximately matches the empirical distribution
        measured for real Duplo bricks. A value of 0.0 yields a deterministic
        separation force approximately equal to the mode of the empirical
        distribution.
      color: An optional tuple of (R, G, B) values specifying the color of the
        Duplo brick. These should be floats between 0 and 1. The default is red.

    Raises:
      ValueError: If `color` contains any value that is not between 0 and 1.
    """
    self._mjcf_root = mjcf.from_path(_DUPLO_XML_PATH)

    stud = self._mjcf_root.default.find('default', 'stud')
    if easy_align:
      # Make cylindrical studs invisible and disable contacts.
      stud.geom.group = 3
      stud.geom.contype = 9
      stud.geom.conaffinity = 8
      # Make capsule studs visible and enable contacts.
      stud_cap = self._mjcf_root.default.find('default', 'stud-capsule')
      stud_cap.geom.group = 0
      stud_cap.geom.contype = 0
      stud_cap.geom.conaffinity = 4
      self._active_stud_dclass = stud_cap
    else:
      self._active_stud_dclass = stud

    if flanges:
      flange_dclass = self._mjcf_root.default.find('default', 'flange')
      flange_dclass.geom.contype = 4  # Enable contact with flanges.

    stud_size = _STUD_SIZE_PARAMS[(easy_align, flanges)]
    offset = (1 - variation) * stud_size.lower_quartile
    self._lower = offset + variation * stud_size.minimum
    self._upper = offset + variation * stud_size.maximum

    self._studs = np.ndarray((2, 4), dtype=object)
    self._holes = np.ndarray((2, 4), dtype=object)

    for row in range(2):
      for column in range(4):
        self._studs[row, column] = self._mjcf_root.find(
            'site', 'stud_{}{}'.format(row, column))
        self._holes[row, column] = self._mjcf_root.find(
            'site', 'hole_{}{}'.format(row, column))

    if not all(0 <= value <= 1 for value in color):
      raise ValueError(_COLOR_NOT_BETWEEN_0_AND_1.format(color))
    self._mjcf_root.default.geom.rgba[:3] = color
def _build ( self , easy_align = False , flanges = True , variation = 0.0 , color = ( 1. , 0. , 0. ) ) : self . _mjcf_root = mjcf . from_path ( _DUPLO_XML_PATH ) stud = self . _mjcf_root . default . find ( 'default' , 'stud' ) if easy_align : # Make cylindrical studs invisible and disable contacts. stud . geom . group = 3 stud . geom . contype = 9 stud . geom . conaffinity = 8 # Make capsule studs visible and enable contacts. stud_cap = self . _mjcf_root . default . find ( 'default' , 'stud-capsule' ) stud_cap . geom . group = 0 stud_cap . geom . contype = 0 stud_cap . geom . conaffinity = 4 self . _active_stud_dclass = stud_cap else : self . _active_stud_dclass = stud if flanges : flange_dclass = self . _mjcf_root . default . find ( 'default' , 'flange' ) flange_dclass . geom . contype = 4 # Enable contact with flanges. stud_size = _STUD_SIZE_PARAMS [ ( easy_align , flanges ) ] offset = ( 1 - variation ) * stud_size . lower_quartile self . _lower = offset + variation * stud_size . minimum self . _upper = offset + variation * stud_size . maximum self . _studs = np . ndarray ( ( 2 , 4 ) , dtype = object ) self . _holes = np . ndarray ( ( 2 , 4 ) , dtype = object ) for row in range ( 2 ) : for column in range ( 4 ) : self . _studs [ row , column ] = self . _mjcf_root . find ( 'site' , 'stud_{}{}' . format ( row , column ) ) self . _holes [ row , column ] = self . _mjcf_root . find ( 'site' , 'hole_{}{}' . format ( row , column ) ) if not all ( 0 <= value <= 1 for value in color ) : raise ValueError ( _COLOR_NOT_BETWEEN_0_AND_1 . format ( color ) ) self . _mjcf_root . default . geom . rgba [ : 3 ] = color