(self)
| 254 | getattr(binding, 'invalid_attribute') |
| 255 | |
| 256 | def test_dirty(self): |
| 257 | self.physics.forward() |
| 258 | self.assertFalse(self.physics.is_dirty) |
| 259 | |
| 260 | joints, _ = self.sample_elements('joint', single_element=False) |
| 261 | sites, _ = self.sample_elements('site', single_element=False) |
| 262 | |
| 263 | # Accessing qpos shouldn't trigger a recalculation. |
| 264 | _ = self.physics.bind(joints).qpos |
| 265 | self.assertFalse(self.physics.is_dirty) |
| 266 | |
| 267 | # Reassignments to qpos should cause the physics to become dirty. |
| 268 | site_xpos_before = copy.deepcopy(self.physics.bind(sites).xpos) |
| 269 | self.physics.bind(joints).qpos += 0.5 |
| 270 | self.assertTrue(self.physics.is_dirty) |
| 271 | |
| 272 | # Accessing stuff in mjModel shouldn't trigger a recalculation. |
| 273 | _ = self.physics.bind(sites).pos |
| 274 | self.assertTrue(self.physics.is_dirty) |
| 275 | |
| 276 | # Accessing stuff in mjData should trigger a recalculation. |
| 277 | actual_sites_xpos_after = copy.deepcopy(self.physics.bind(sites).xpos) |
| 278 | self.assertFalse(self.physics.is_dirty) |
| 279 | self.assertFalse((actual_sites_xpos_after == site_xpos_before).all()) |
| 280 | |
| 281 | # Automatic recalculation should render `forward` a no-op here. |
| 282 | self.physics.forward() |
| 283 | expected_sites_xpos_after = self.physics.bind(sites).xpos |
| 284 | np.testing.assert_array_equal(actual_sites_xpos_after, |
| 285 | expected_sites_xpos_after) |
| 286 | |
| 287 | # `forward` should not be called on subsequent queries to xpos. |
| 288 | with mock.patch.object( |
| 289 | self.physics, 'forward', |
| 290 | side_effect=self.physics.forward) as mock_forward: |
| 291 | _ = self.physics.bind(sites).xpos |
| 292 | mock_forward.assert_not_called() |
| 293 | |
| 294 | @parameterized.parameters(True, False) |
| 295 | def test_assign_while_dirty(self, assign_via_slice): |
nothing calls this directly
no test coverage detected