|
83 | 83 | _RENDER_FLAG_OVERRIDES_NOT_SUPPORTED_FOR_DEPTH_OR_SEGMENTATION = ( |
84 | 84 | '`render_flag_overrides` are not supported for depth or segmentation ' |
85 | 85 | 'rendering.') |
| 86 | +_KEYFRAME_ID_OUT_OF_RANGE = ( |
| 87 | + '`keyframe_id` must be between 0 and {max_valid} inclusive, got: {actual}.') |
86 | 88 |
|
87 | 89 |
|
88 | 90 | class Physics(_control.Physics): |
@@ -267,9 +269,22 @@ def copy(self, share_model=False): |
267 | 269 | new_obj._reload_from_data(new_data) # pylint: disable=protected-access |
268 | 270 | return new_obj |
269 | 271 |
|
270 | | - def reset(self): |
271 | | - """Resets internal variables of the physics simulation.""" |
272 | | - mjlib.mj_resetData(self.model.ptr, self.data.ptr) |
| 272 | + def reset(self, keyframe_id=None): |
| 273 | + """Resets internal variables of the simulation, possibly to a keyframe. |
| 274 | +
|
| 275 | + Args: |
| 276 | + keyframe_id: Optional int. If specified, the keyframe (saved state) to |
| 277 | + which to set the state. |
| 278 | +
|
| 279 | + """ |
| 280 | + if keyframe_id is None: |
| 281 | + mjlib.mj_resetData(self.model.ptr, self.data.ptr) |
| 282 | + else: |
| 283 | + if not 0 <= keyframe_id < self.model.nkey: |
| 284 | + raise ValueError(_KEYFRAME_ID_OUT_OF_RANGE.format( |
| 285 | + max_valid=self.model.nkey-1, actual=keyframe_id)) |
| 286 | + mjlib.mj_resetDataKeyframe(self.model.ptr, self.data.ptr, keyframe_id) |
| 287 | + |
273 | 288 | # Disable actuation since we don't yet have meaningful control inputs. |
274 | 289 | with self.model.disable('actuation'): |
275 | 290 | self.forward() |
|
0 commit comments