code: def main(flags) -> None:
      if "ALL" in flags.object_types:
          objects_types = OBJECT_TYPES
      else:
          objects_types = flags.object_types
  
      # --- Common setups & resources
      kb.setup_logging(flags.logging_level)
      kb.log_my_flags(flags)
      scratch_dir, output_dir = kb.setup_directories(flags)
  
      if flags.seed is None:
          raise ValueError("You must specify --seed to proceed.")
      seed = flags.seed
      rng = np.random.RandomState(seed=seed)
  
      scene = kb.Scene.from_flags(flags)
      simulator = kubric.simulator.pybullet.PyBullet(scene, scratch_dir)
      renderer = kubric.renderer.blender.Blender(
          scene, scratch_dir, adaptive_sampling=False
      )  # Removes salt-and-pepper artifacts in shadows.
  
      logging.info("Loading assets from %s", flags.assets_path)
      kubasic = kb.AssetSource.from_manifest(flags.assets_path)
  
      # --- Populate the scene
      logging.info("Creating a large cube as the floor...")
      # Create the "floor" of the scene. This is a large, flat cube of
      # x_length=200, y_length=200 and z_length=2 centered at x=0, y=0, z=-1.
      # This means that the floor's elevation is z + z_length/2 == -1 + 1 == 0.
      _, floor_color = _sample_color(flags.floor_color, rng)
      floor_material = kb.PrincipledBSDFMaterial(
          color=floor_color, roughness=1.0, specular=0.0
      )
      floor = kb.Cube(
          **_get_floor_scale_position_kwargs(SPAWN_REGION),
          material=floor_material,
          friction=flags.floor_friction,
          static=True,
          background=True,
      )
      scene.add(floor)
  
      # Set background color.
      _, background_color = _sample_color(flags.background_color, rng)
      logging.info(
          "Setting background color to %s...", background_color
      )
      scene.background = background_color
  
      logging.info("Adding several lights to the scene...")
      sun = kb.DirectionalLight(
          color=kb.get_color("white"),
          shadow_softness=0.2,
          intensity=3.0,
          position=(11.6608, -6.62799, 25.8232),
      )
      lamp_back = kb.RectAreaLight(
          color=kb.get_color("white"),
          intensity=50.0,
          position=(-1.1685, 2.64602, 5.81574),
      )
      lamp_key = kb.RectAreaLight(
          color=kb.get_color(0xFFEDD0),
          intensity=100.0,
          width=0.5,
          height=0.5,
          position=(6.44671, -2.90517, 4.2584),
      )
      lamp_fill = kb.RectAreaLight(
          color=kb.get_color("#c2d0ff"),
          intensity=30.0,
          width=0.5,
          height=0.5,
          position=(-4.67112, -4.0136, 3.01122),
      )
      lights = [sun, lamp_back, lamp_key, lamp_fill]
      for light in lights:
          light.look_at((0, 0, 0))
          scene.add(light)
  
      scene.ambient_illumination = kb.Color(0.05, 0.05, 0.05)
  
      logging.info("Setting up the Camera...")
      original_camera_position = (7.48113, -6.50764, 5.34367)
      scene.camera = kb.PerspectiveCamera(
          focal_length=35.0,
          sensor_width=32,
          position=original_camera_position,
      )
      scene.camera.look_at((0, 0, 0))
  
      # TODO: Refactor this so that we can render both a "spherical view"
      # and a "lattice view" through the scene.
  
      # Render cameras at the same general distance from the origin, but at
      # different positions.
      #
      # We will use spherical coordinates (r, theta, phi) to do this.
      #   x = r * cos(theta) * sin(phi)
      #   y = r * sin(theta) * sin(phi)
      #   z = r * cos(phi)
      r = np.sqrt(sum(a * a for a in original_camera_position))
      phi = np.arccos(original_camera_position[2] / r)
      theta = np.arccos(original_camera_position[0] / (r * np.sin(phi)))
  
      # At each frame, we will modify theta so that we move in a circle.
      # At each given theta value, we will also render three values of phi so our
      # data "matches" LLFF (i.e., we have motion in z as well as x and y).
      num_frames_to_render = scene.frame_end - scene.frame_start
  
      # TODO: Either parameterize this or turn it into a constant
      # matching the style guide recommendation.
      num_phi_values_per_theta = 4
  
      def add_random_objects(num_objects, objects_types, rng):
          """Returns the list of created objects."""
          logging.info(f"Randomly placing {num_objects} objects")
          objects = list()
          for _ in range(num_objects):
              shape_name = rng.choice(objects_types)
              _, size = _sample_sizes("const", rng)
              _, color = _sample_color(flags.object_colors, rng)
              segmentation_id_val = objects_types.index(shape_name) + 1
              obj = kubasic.create(
                  asset_id=shape_name,
                  scale=size,
                  segmentation_id=segmentation_id_val,
              )
  
              material_name = "Rubber"
              obj.material = kb.PrincipledBSDFMaterial(
                  color=color,
                  metallic=0.0,
                  ior=1.25,
                  roughness=0.7,
                  specular=0.33,
              )
  
              scene.add(obj)
              obj.metadata = {
                  "shape": shape_name.lower(),
                  "size": size,
                  "material": material_name.lower(),
                  "color": color.rgb,
              }
  
              # Place object randomly within SPAWN_REGION
              kb.move_until_no_overlap(
                  obj, simulator, spawn_region=SPAWN_REGION, rng=rng
              )
              objects += [obj]
              logging.info("Added object %s", obj)
          return objects
  
      # --- Place random objects (static in time)
      add_random_objects(
          flags.num_objects_static, objects_types=objects_types, rng=rng
      )
      # --- Place dynamic objects (will change in time)
      dyn_objects = add_random_objects(
          flags.num_objects_dynamic,
          objects_types=[
              "suzanne",
          ],
          rng=rng,
      )
  
      # --- if in jitter mode shake the monkeys instead
      if flags.jitter:
          for dyn_object in dyn_objects:
              dyn_object.orig_position = dyn_object.position
  
      # import pdb; pdb.set_trace();
      # exit(0)
  
      theta_change = (2 * np.pi) / (
          num_frames_to_render / num_phi_values_per_theta
      )
      for frame in range(scene.frame_start, scene.frame_end + 1):
          i = frame - scene.frame_start
          theta_new = (
              i // num_phi_values_per_theta
          ) * theta_change + theta
  
          # These values of (x, y, z) will lie on the same sphere as the original
          # camera.
          x = r * np.cos(theta_new) * np.sin(phi)
          y = r * np.sin(theta_new) * np.sin(phi)
          z = r * np.cos(phi)
  
          # To ensure have "roughly LLFF-style" data (multiple z values for the same
          # x and y), we will also adjust z. The camera is no longer guaranteed to
          # remain on the same sphere as the original camera.
          z_shift_direction = (i % num_phi_values_per_theta) - 1
          z = z + z_shift_direction * 1.2
  
          scene.camera.position = (x, y, z)
          scene.camera.look_at((0, 0, 0))
          scene.camera.keyframe_insert("position", frame)
          scene.camera.keyframe_insert("quaternion", frame)
  
          # --- randomly change the position of the dynamic objects in each frame
          for obj in dyn_objects:
              # --- hide dynamic objects once every 30 frames (evaluation set)
              if (i % 30) != 0:
                  if not flags.jitter:
                      kb.move_until_no_overlap(
                          obj,
                          simulator,
                          spawn_region=SPAWN_REGION,
                          rng=rng,
                      )
                  else:
                      obj.position = (
                          obj.orig_position + 0.1 * np.random.randn(3)
                      )
              else:
                  random_dir = np.random.randn(3)
                  random_dir = random_dir / np.linalg.norm(random_dir)
                  large_offset = 10e3
                  position = (large_offset * random_dir).tolist()
                  obj.position = position
  
              obj.keyframe_insert("position", frame)
              # print(f"moved from {old_position} to {obj.position}")
  
      # --- Rendering
      logging.info(f'Saving {output_dir / "scene.blend"}')
      renderer.save_state(output_dir / "scene.blend")
  
      print(f"jitter mode? {flags.jitter}")
  
      if flags.norender:
          logging.warning("rendering not executed")
          kb.done()
          exit(0)
  
      logging.info("Rendering the scene ...")
      render_data = renderer.render()
      # replace asset index (in scene.assets) with segmentation_id
      render_data["segmentation"] = kb.adjust_segmentation_idxs(
          render_data["segmentation"], scene.assets, scene.assets
      )
  
      # export all rendered images / segmentations / depth / ... to output dir
      kb.write_image_dict(render_data, output_dir)
  
      # --- Metadata
      logging.info("Collecting and storing metadata for each object.")
      kb.write_pkl(
          {
              "metadata": kb.get_scene_metadata(scene, seed=seed),
              "camera": kb.get_camera_info(scene.camera),
              "instances": kb.get_instance_info(scene),
              "background": {
                  "background_color": background_color,
                  "floor_color": floor_color.rgb,
                  "floor_friction": flags.floor_friction,
              },
          },
          output_dir / "metadata.pkl",
      )
  
      # Save the scene camera in a JSON file.
      scene_metadata = kb.get_scene_metadata(scene, seed=seed)
      scene_camera = kb.get_camera_info(
          scene.camera,
          height=scene_metadata["resolution"][0],
          width=scene_metadata["resolution"][1],
      )
      scene_camera["positions"] = scene_camera["positions"].tolist()
      scene_camera["quaternions"] = scene_camera["quaternions"].tolist()
      scene_camera["K"] = scene_camera["K"].tolist()
      scene_camera["R"] = scene_camera["R"].tolist()
  
      # Generate the train/test ids
      train_ids, test_ids = _make_train_test_ids(
          rng, scene_metadata["num_frames"]
      )
      logging.info(
          f"Split {num_frames_to_render} frames: {len(train_ids)} train frames, "
          f"{len(test_ids)} test frames."
      )
  
      metadata = {
          "metadata": scene_metadata,
          "camera": scene_camera,
          "segmentation_labels": objects_types,
          "scene_boundaries": _get_scene_boundaries(
              floor, SPAWN_REGION
          ),
          "split_ids": {
              "train": train_ids,
              "test": test_ids,
          },
      }
      kb.write_json(metadata, output_dir / "metadata.json")
  
      scene_gltf_file = str(scratch_dir / "scene.glb")
      logging.info("Saving %s ", scene_gltf_file)
      bpy.ops.export_scene.gltf(filepath=scene_gltf_file)
  
      output_scene_gltf_file = str(output_dir / "scene.glb")
      tf.io.gfile.copy(
          scene_gltf_file, output_scene_gltf_file, overwrite=True
      )
  
      kb.done()
  
file_path: kubric/challenges/robust_nerf/worker.py
imports: import collections
  import json
  import logging
  from typing import Dict, List, Optional, Tuple
  import kubric
  import kubric.renderer.blender
  import kubric.simulator.pybullet
  import numpy
  import tensorflow
  import bpy
label_desc: Use image node_id 6 for calling a global function with example usage: main(flags) and returns: objects