code: def stage4(object_folder: Path, logger=_DEFAULT_LOGGER):
      # TODO: we should probably use a mixture of model_normalized and model_wateright here?
      source_path = object_folder / "kubric" / "collision_geometry.obj"
      watertight_mesh_path = (
          object_folder / "kubric" / "model_watertight.obj"
      )
      vis_mesh_path = object_folder / "kubric" / "visual_geometry.glb"
      target_urdf_path = object_folder / "kubric" / "object.urdf"
      target_json_path = object_folder / "kubric" / "data.json"
  
      if target_urdf_path.is_file() and target_json_path.is_file():
          return
  
      # --- pre-condition
      if not source_path.is_file():
          logger.error(
              f'stage4 pre-condition failed, file does not exist "{source_path}"'
          )
      if not watertight_mesh_path.is_file():
          logger.error(
              f'stage4 pre-condition failed, file does not exist "{watertight_mesh_path}"'
          )
      if not vis_mesh_path.is_file():
          logger.error(
              f'stage4 pre-condition failed, file does not exist "{vis_mesh_path}"'
          )
  
      logger.debug(f'stage4 running on "{object_folder}"')
  
      # --- body1: object.urdf file
      properties = get_object_properties(source_path, logger)
      properties.update(get_object_volume(watertight_mesh_path))
      properties.update(get_visual_properties(vis_mesh_path))
  
      asset_id, category_id, category_name = get_asset_id_and_category(
          object_folder
      )
      properties["id"] = asset_id
      urdf_str = URDF_TEMPLATE.format(**properties)
      with open(target_urdf_path, "w") as fd:
          fd.write(urdf_str)
  
      # --- body2: data.json file
      asset_entry = {
          "id": asset_id,
          "asset_type": "FileBasedObject",
          "kwargs": {
              "bounds": properties["bounds"],
              "mass": properties["mass"],
              "render_filename": "visual_geometry.glb",
              "simulation_filename": "object.urdf",
          },
          "license": "https://shapenet.org/terms",
          "metadata": {
              "category": category_name,
              "category_id": category_id,
              "watertight_mesh_filename": "model_watertight.obj",
              "nr_faces": properties["nr_faces"],
              "nr_vertices": properties["nr_vertices"],
              "surface_area": properties["surface_area"],
              "volume": properties["volume"],
          },
      }
  
      with open(target_json_path, "w") as fd:
          json.dump(asset_entry, fd, indent=4, sort_keys=True)
  
      # --- post-condition
      if not target_urdf_path.is_file():
          logger.error(
              f'stage4 post-condition failed, file does not exist "{target_urdf_path}"'
          )
      if not target_json_path.is_file():
          logger.error(
              f'stage4 post-condition failed, file does not exist "{target_json_path}"'
          )
  
      return properties
  
imports: import argparse
  import json
  import logging
  from pathlib import Path
  import shutil
  import subprocess
  import sys
  import tarfile
  from typing import Tuple
  import trimesh
  from shapenet_synsets import CATEGORY_NAMES
  from trimesh_utils import get_object_properties
  import trimesh_utils
  from urdf_template import URDF_TEMPLATE
label_desc: Use image node_id 8 for calling a global function with example usage: stage4(object_folder, logger) and returns: properties