import json import os import subprocess import shutil from pathlib import Path import argparse def update_robot_json(robot_json_file, camera_position, camera_target, default_position): """Aktualisiert die cameraPosition und defaultPosition in der robot.json-Datei.""" try: with open(robot_json_file, 'r') as f: data = json.load(f) data['renderingInfo']['cameraPosition'] = camera_position data['renderingInfo']['cameraTarget'] = camera_target data['defaultPosition'] = default_position with open(robot_json_file, 'w') as f: json.dump(data, f, indent=2) except FileNotFoundError: print(f"Fehler: Datei {robot_json_file} nicht gefunden.") return False except json.JSONDecodeError: print(f"Fehler: JSON-Datei {robot_json_file} ist ungültig.") return False return True def run_blender(blender_executable, script_path, log_level): """Führt Blender mit dem angegebenen Skript aus.""" try: command = [ blender_executable, "-b", "--python", script_path, "--log-level", str(log_level) ] subprocess.run(command, check=True, capture_output=True, text=True) return True except subprocess.CalledProcessError as e: print(f"Blender-Skript fehlgeschlagen:\n{e.stderr}") return False def copy_and_rename_file(source_file, destination_dir, new_filename): """Kopiert die erstellte Bilddatei in den Zielordner und benennt sie um.""" destination_path = os.path.join(destination_dir, new_filename) try: shutil.copy2(source_file, destination_path) # copy2 behält Metadaten return True except FileNotFoundError: print(f"Fehler: Quelldatei {source_file} nicht gefunden.") return False except Exception as e: print(f"Fehler beim Kopieren/Umbenennen der Datei: {e}") return False def main(): USER_HOME = Path.home() ROBOT_JSON_FILE = str(USER_HOME / "SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering" / "data" / "robot" / "robot.json") OUTPUT_DIR = str(USER_HOME / "SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering" / "data" / "simulation" / "debug" ) BLENDER_EXE = str("C:/Program Files/Blender Foundation/Blender 4.5/blender.exe") RENDER_PY= str(USER_HOME /"SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering"/ "setup"/"generateSets"/"render_robot.py") RENDER_PNG=str(USER_HOME /"SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering"/"data"/"simulation"/"debug"/"render.png") OUTPUT_SET = str(USER_HOME / "SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering" / "data" / "simulation" ) parser = argparse.ArgumentParser(description="Automatisiert die Roboter-Rendering-Pipeline.") parser.add_argument("robot_json", nargs="?", default=ROBOT_JSON_FILE, help="Pfad zur robot.json-Datei.") parser.add_argument("blender_executable",nargs="?", default=BLENDER_EXE, help="Pfad zur Blender-Executable.") parser.add_argument("render_script", default=RENDER_PY, help="Pfad zum render_robot.py-Skript.",nargs="?") parser.add_argument("render_png",nargs="?", default=RENDER_PNG,help="script erzeugte png") parser.add_argument("output_dir", nargs="?", default=OUTPUT_DIR, help="Zielordner für die gerenderten Blender Bilder.") parser.add_argument("output_set", nargs="?", default=OUTPUT_SET, help="Zielordner in dem die Sets abgelegt werden") parser.add_argument("--log_level", type=int, default=2, help="Log-Level für Blender (Standard: 2).") args = parser.parse_args() # Kamerapositions-Dictionary camera_positions = { "a": [-300, -800, 800], "b": [300, -900, 1200], "c": [300, -900, 400], "d": [700, -800, 400], "e": [1200, -900, 400], "f": [500, -300, 1400], "g": [-200, 200, 1400], } camera_targets = { "a": [210, -100, 180], "b": [310, -80, 180], "c": [210, -100, 150], "d": [210, -100, 150], "e": [210, -100, 50], "f": [200, -200, 180], "g": [200, -200, 180], } # Robot-Pose-Dictionary robot_poses = { #"4": {"x": 70, "y": 50,"z": -70,"a": 120,"b": 50,"c": 30,"e": 20}, #"5": {"x": 180,"y": 86,"z": -120,"a": -60,"b": 22,"c": 91,"e": 10}, #"6": {"x": 80, "y": 20, "z": 80, "a": -120, "b": 23, "c": 9, "e": 3}, #"7": {"x": 30, "y": -2, "z": 95, "a": 20, "b": 23, "c": 9, "e": 9}, #"8": {"x": 50, "y": -2, "z": 95, "a": 20, "b": 60, "c": 9, "e": 3}, "9": {"x": 60, "y": -2, "z": 95, "a": 200, "b": 60, "c": 9, "e": 8}, "10": {"x": 120, "y": 60, "z": -110, "a": 20, "b": 30, "c": 180, "e": 4}, #"11": {"x": 50, "y": 4, "z": 176, "a": 20, "b": 60, "c": 9, "e": 5}, #"12": {"x": 50, "y": 0, "z": 178, "a": 210, "b": 80, "c": 90, "e": 6}, } for pose_name, default_position in robot_poses.items(): new_folder = Path(args.output_set) / f"Set{pose_name}" os.makedirs(new_folder, exist_ok=True) pose_file = new_folder / "pose.json" pose_data = {"name": pose_name,"position": default_position, "camera_positions": camera_positions} with open(pose_file, "w") as f: json.dump(pose_data, f, indent=2) for frame_name, camera_position in camera_positions.items(): camera_target = camera_targets[frame_name] # 1. JSON aktualisieren if not update_robot_json(args.robot_json, camera_position, camera_target, default_position): continue # Gehe zum nächsten Schleifendurchlauf # 2. Blender-Skript ausführen if not run_blender(args.blender_executable, args.render_script, args.log_level): continue # Gehe zum nächsten Schleifendurchlauf # 3. Datei kopieren und umbenennen new_filename = f"render_{frame_name}.png" if not copy_and_rename_file(args.render_png, new_folder, new_filename): continue # Gehe zum nächsten Schleifendurchlauf if not copy_and_rename_file(args.render_png.replace(".png",".npz"), new_folder, new_filename.replace(".png",".npz")): continue # Gehe zum nächsten Schleifendurchlauf if not copy_and_rename_file(args.render_png.replace("render.png","markers.json"), new_folder, new_filename.replace(".png",".json")): continue # Gehe zum nächsten Schleifendurchlauf print(f"Rendering für Frame {frame_name}, Set {pose_name} erfolgreich abgeschlossen.") if __name__ == "__main__": main()