class_docstr: Adds physics simulation on top of kb.Scene using PyBullet.
class_docstr_tok: ["Adds","physics","simulation","on","top","of","kb.Scene","using","PyBullet","."]
docstr: Run the physics simulation.
  
  The resulting animation is saved directly as keyframes in the assets,
  and also returned (together with the collision events).
  
  Args:
    frame_start: The first frame from which to start the simulation (inclusive).
      Also the first frame for which keyframes are stored.
    frame_end: The last frame (inclusive) that is simulated (and for which animations
      are computed).
  
  Returns:
    A dict of all animations and a list of all collision events.
docstr_tok: ["Run","the","physics","simulation",".","The","resulting","animation","is","saved","directly","as","keyframes","in","the","assets",",","and","also","returned","(","together","with","the","collision","events",")",".","Args",":","frame_start",":","The","first","frame","from","which","to","start","the","simulation","(","inclusive",")",".","Also","the","first","frame","for","which","keyframes","are","stored",".","frame_end",":","The","last","frame","(","inclusive",")","that","is","simulated","(","and","for","which","animations","are","computed",")",".","Returns",":","A","dict","of","all","animations","and","a","list","of","all","collision","events","."]
code: def run(
      self, frame_start: int = 0, frame_end: Optional[int] = None
  ) -> Tuple[Dict[core.PhysicalObject, Dict[str, list]], List[dict]]:
      """
      Run the physics simulation.
  
      The resulting animation is saved directly as keyframes in the assets,
      and also returned (together with the collision events).
  
      Args:
        frame_start: The first frame from which to start the simulation (inclusive).
          Also the first frame for which keyframes are stored.
        frame_end: The last frame (inclusive) that is simulated (and for which animations
          are computed).
  
      Returns:
        A dict of all animations and a list of all collision events.
      """
  
      frame_end = (
          self.scene.frame_end if frame_end is None else frame_end
      )
      steps_per_frame = self.scene.step_rate // self.scene.frame_rate
      max_step = (frame_end - frame_start + 1) * steps_per_frame
  
      obj_idxs = [
          self._physics_client.getBodyUniqueId(i)
          for i in range(self._physics_client.getNumBodies())
      ]
      animation = {
          obj_id: {
              "position": [],
              "quaternion": [],
              "velocity": [],
              "angular_velocity": [],
          }
          for obj_id in obj_idxs
      }
  
      collisions = []
      for current_step in range(max_step):
          contact_points = self._physics_client.getContactPoints()
          for collision in contact_points:
              (
                  contact_flag,
                  body_a,
                  body_b,
                  link_a,
                  link_b,
                  position_a,
                  position_b,
                  contact_normal_b,
                  contact_distance,
                  normal_force,
                  lateral_friction1,
                  lateral_friction_dir1,
                  lateral_friction2,
                  lateral_friction_dir2,
              ) = collision
              del link_a, link_b  # < unused
              del contact_flag, contact_distance, position_a  # < unused
              del lateral_friction1, lateral_friction2  # < unused
              del (
                  lateral_friction_dir1,
                  lateral_friction_dir2,
              )  # < unused
              if normal_force > 1e-6:
                  collisions.append(
                      {
                          "instances": (
                              self._obj_idx_to_asset(body_b),
                              self._obj_idx_to_asset(body_a),
                          ),
                          "position": position_b,
                          "contact_normal": contact_normal_b,
                          "frame": current_step / steps_per_frame,
                          "force": normal_force,
                      }
                  )
  
          if current_step % steps_per_frame == 0:
              for obj_idx in obj_idxs:
                  position, quaternion = self.get_position_and_rotation(
                      obj_idx
                  )
                  velocity, angular_velocity = self.get_velocities(
                      obj_idx
                  )
  
                  animation[obj_idx]["position"].append(position)
                  animation[obj_idx]["quaternion"].append(quaternion)
                  animation[obj_idx]["velocity"].append(velocity)
                  animation[obj_idx]["angular_velocity"].append(
                      angular_velocity
                  )
  
          self._physics_client.stepSimulation()
  
      animation = {
          asset: animation[asset.linked_objects[self]]
          for asset in self.scene.assets
          if asset.linked_objects.get(self) in obj_idxs
      }
  
      # --- Transfer simulation to renderer keyframes
      for obj in animation.keys():
          for frame_id in range(frame_end - frame_start + 1):
              obj.position = animation[obj]["position"][frame_id]
              obj.quaternion = animation[obj]["quaternion"][frame_id]
              obj.velocity = animation[obj]["velocity"][frame_id]
              obj.angular_velocity = animation[obj]["angular_velocity"][
                  frame_id
              ]
              obj.keyframe_insert("position", frame_id + frame_start)
              obj.keyframe_insert("quaternion", frame_id + frame_start)
              obj.keyframe_insert("velocity", frame_id + frame_start)
              obj.keyframe_insert(
                  "angular_velocity", frame_id + frame_start
              )
  
      return animation, collisions
  
imports: import functools
  import inspect
  import logging
  import pathlib
  import sys
  import tempfile
  from typing import Dict, List, Optional, Tuple, Union
  import tensorflow
  from singledispatchmethod import singledispatchmethod
  from kubric import core
  from kubric.redirect_io import RedirectStream
label_desc: Use image node_id 15 for calling the PyBullet obj's underlying member method code with example usage: obj.run(frame_start, frame_end) and returns: animation,  collisions