Scene Generated

This commit is contained in:
chk
2026-05-31 08:56:10 +02:00
parent 2f98f892e6
commit a6bdbf98f7
195 changed files with 141719 additions and 633 deletions

View File

@@ -0,0 +1,153 @@
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()

View File

@@ -15,6 +15,18 @@ from mathutils import Matrix
ROBOT_JSON_FILE = r"C:\Users\kech\SynologyDrive\2026-AppServer-AppRobot\appRobotRendering\data\robot\robot.json"
OUTPUT_FILE = r"C:\Users\kech\SynologyDrive\2026-AppServer-AppRobot\appRobotRendering\data\simulation\debug\render.png"
from pathlib import Path
# Holt dynamisch den Pfad zum aktuellen Benutzerverzeichnis (z.B. C:\Users\Name)
USER_HOME = Path.home()
# Kombiniert den Benutzerpfad mit dem spezifischen Ordnerpfad und konvertiert direkt zu str
ROBOT_JSON_FILE = str(USER_HOME / "SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering" / "data" / "robot" / "robot.json")
OUTPUT_FILE = str(USER_HOME / "SynologyDrive" / "2026-AppServer-AppRobot" / "appRobotRendering" / "data" / "simulation" / "debug" / "render.png")
print("Using robot JSON file:", ROBOT_JSON_FILE)
print("Using output file:", OUTPUT_FILE)
# ============================================================
# DEFAULT MATERIALS
# ============================================================
@@ -83,6 +95,8 @@ links_def = robot.get("links", {})
if not isinstance(links_def, dict):
raise ValueError("robot.json must contain a top-level 'links' object")
# ============================================================
# HELPERS
# ============================================================
@@ -345,8 +359,11 @@ bg.inputs[1].default_value = float(rendering_info.get("backgroundStrength", 0.20
scene.render.engine = "CYCLES"
scene.view_settings.exposure = float(rendering_info.get("exposure", -1.5))
scene.cycles.samples = 16
scene.cycles.samples = 32
scene.cycles.preview_samples = 32
scene.cycles.use_adaptive_sampling = True
scene.cycles.adaptive_threshold = 0.02
scene.cycles.use_denoising = True
scene.render.resolution_x = RENDER_WIDTH
scene.render.resolution_y = RENDER_HEIGHT
scene.render.resolution_percentage = 100
@@ -931,6 +948,52 @@ create_axis_arrow("AxisX", (1, 0, 0), (1, 0, 0))
create_axis_arrow("AxisY", (0, 1, 0), (0, 1, 0))
create_axis_arrow("AxisZ", (0, 0, 1), (0, 0, 1))
# ============================================================
# AUTO GPU DETECTION (robust, plattformübergreifend)
# ============================================================
def enable_best_device(scene):
prefs = bpy.context.preferences
cycles_prefs = prefs.addons['cycles'].preferences
# Prioritäten (schnell → weniger schnell)
backends = ['OPTIX', 'CUDA', 'HIP', 'METAL', 'ONEAPI']
selected_backend = None
for backend in backends:
try:
cycles_prefs.compute_device_type = backend
cycles_prefs.get_devices()
devices = cycles_prefs.devices
# Prüfen, ob eine GPU dabei ist
gpu_devices = [d for d in devices if d.type != 'CPU']
if gpu_devices:
selected_backend = backend
# Aktiviere alle Geräte (GPU + optional CPU fallback)
for d in devices:
d.use = True
break
except Exception:
continue
if selected_backend:
print(f"[Render] Using GPU via {selected_backend}")
scene.cycles.device = 'GPU'
else:
print("[Render] No GPU found, falling back to CPU")
scene.cycles.device = 'CPU'
enable_best_device(scene)
# ============================================================
# RENDER
# ============================================================

File diff suppressed because it is too large Load Diff

View File

@@ -1,104 +0,0 @@
import json
import os
import subprocess
import shutil
import argparse
def update_robot_json(robot_json_file, camera_position, 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']['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():
parser = argparse.ArgumentParser(description="Automatisiert die Roboter-Rendering-Pipeline.")
parser.add_argument("robot_json", help="Pfad zur robot.json-Datei.")
parser.add_argument("blender_executable", help="Pfad zur Blender-Executable.")
parser.add_argument("render_script", help="Pfad zum render_robot.py-Skript.")
parser.add_argument("output_dir", help="Zielordner für die gerenderten Bilder.")
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, 500],
"b": [300, -700, 500],
"c": [600, -500, 600],
"d": [-10, -800, 500],
"e": [-500, 300, 1200],
"f": [1200, 200, 300]
}
# Robot-Pose-Dictionary
robot_poses = {
"3": {"x": 10, "y": 4, "z": 20, "a": 10, "b": 2, "c": 9, "e": 1},
"4": {"x": 40, "y": 48, "z": -30, "a": 30, "b": 23, "c": 9, "e": 8},
"5": {"x": 80, "y": 93, "z": -120, "a": 120, "b": 23, "c": 9, "e": 3},
"6": {"x": 80, "y": 20, "z": 80, "a": -120, "b": 23, "c": 9, "e": 3}
}
for set_name, camera_position in camera_positions.items():
for pose_name, default_position in robot_poses.items():
# 1. JSON aktualisieren
if not update_robot_json(args.robot_json, camera_position, 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
render_script_dir = os.path.dirname(args.render_script)
render_file = os.path.join(render_script_dir, "render.png")
new_filename = f"render_set{set_name}_{pose_name}.png"
if not copy_and_rename_file(render_file, args.output_dir, new_filename):
continue # Gehe zum nächsten Schleifendurchlauf
print(f"Rendering für Set {set_name}, Pose {pose_name} erfolgreich abgeschlossen.")
if __name__ == "__main__":
main()