Returns an MJCF XML string defining a model of springs and dampers. Args: n_bodies: An integer, the number of bodies (DoFs) in the system. n_actuators: An integer, the number of actuated bodies. random: A `numpy.random.RandomState` instance. stiffness_range: A tuple containing min
(n_bodies,
n_actuators,
random,
stiffness_range=(15, 25),
damping_range=(0, 0))
| 138 | |
| 139 | |
| 140 | def _make_model(n_bodies, |
| 141 | n_actuators, |
| 142 | random, |
| 143 | stiffness_range=(15, 25), |
| 144 | damping_range=(0, 0)): |
| 145 | """Returns an MJCF XML string defining a model of springs and dampers. |
| 146 | |
| 147 | Args: |
| 148 | n_bodies: An integer, the number of bodies (DoFs) in the system. |
| 149 | n_actuators: An integer, the number of actuated bodies. |
| 150 | random: A `numpy.random.RandomState` instance. |
| 151 | stiffness_range: A tuple containing minimum and maximum stiffness. Each |
| 152 | joint's stiffness is sampled uniformly from this interval. |
| 153 | damping_range: A tuple containing minimum and maximum damping. Each joint's |
| 154 | damping is sampled uniformly from this interval. |
| 155 | |
| 156 | Returns: |
| 157 | An MJCF string describing the linear system. |
| 158 | |
| 159 | Raises: |
| 160 | ValueError: If the number of bodies or actuators is erronous. |
| 161 | """ |
| 162 | if n_bodies < 1 or n_actuators < 1: |
| 163 | raise ValueError('At least 1 body and 1 actuator required.') |
| 164 | if n_actuators > n_bodies: |
| 165 | raise ValueError('At most 1 actuator per body.') |
| 166 | |
| 167 | file_path = os.path.join(os.path.dirname(__file__), 'lqr.xml') |
| 168 | with resources.GetResourceAsFile(file_path) as xml_file: |
| 169 | mjcf = xml_tools.parse(xml_file) |
| 170 | parent = mjcf.find('./worldbody') |
| 171 | actuator = etree.SubElement(mjcf.getroot(), 'actuator') |
| 172 | tendon = etree.SubElement(mjcf.getroot(), 'tendon') |
| 173 | |
| 174 | for body in range(n_bodies): |
| 175 | # Inserting body. |
| 176 | child = _make_body(body, stiffness_range, damping_range, random) |
| 177 | site_name = 'site_{}'.format(body) |
| 178 | child.append(etree.Element('site', name=site_name)) |
| 179 | |
| 180 | if body == 0: |
| 181 | child.set('pos', '.25 0 .1') |
| 182 | # Add actuators to the first n_actuators bodies. |
| 183 | if body < n_actuators: |
| 184 | # Adding actuator. |
| 185 | joint_name = 'joint_{}'.format(body) |
| 186 | motor_name = 'motor_{}'.format(body) |
| 187 | child.find('joint').set('name', joint_name) |
| 188 | actuator.append(etree.Element('motor', name=motor_name, joint=joint_name)) |
| 189 | |
| 190 | # Add a tendon between consecutive bodies (for visualisation purposes only). |
| 191 | if body < n_bodies - 1: |
| 192 | child_site_name = 'site_{}'.format(body + 1) |
| 193 | tendon_name = 'tendon_{}'.format(body) |
| 194 | spatial = etree.SubElement(tendon, 'spatial', name=tendon_name) |
| 195 | spatial.append(etree.Element('site', site=site_name)) |
| 196 | spatial.append(etree.Element('site', site=child_site_name)) |
| 197 | parent.append(child) |
no test coverage detected
searching dependent graphs…