This commit is contained in:
wty-yy
2025-12-27 17:42:30 +08:00
parent 0a3985445a
commit f92f34ac14
28 changed files with 452 additions and 22 deletions

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
'''
@File : file_utils.py
@Time : 2025/12/27 17:14:29
@Author : wty-yy
@Version : 1.0
@Blog : https://wty-yy.github.io/
@Desc : Common File Utilities
'''
import tarfile
import shutil
import os
from pathlib import Path
import logging
def log_msg(logger: logging.Logger, msg: str, level: str):
if logger:
getattr(logger, level)(msg)
else:
print(msg)
def compress_directory(source_dir, output_filename=None, delete_original=True, logger: logging.Logger=None):
"""
Compress a directory into a .tar.xz file using LZMA compression.
Args:
source_dir (str | Path): Path to the directory to compress.
output_filename (str | Path, optional): Output path. Defaults to source_dir + ".tar.xz".
delete_original (bool): Whether to delete the source directory after successful compression.
"""
source_dir = Path(source_dir)
if not source_dir.exists():
log_msg(logger, f"⚠️ Source directory for compression not found: {source_dir}", "warning")
return
if output_filename is None:
output_filename = source_dir.with_suffix('.tar.xz')
else:
output_filename = Path(output_filename)
log_msg(logger, f"📦 Compressing logs: {source_dir.name} -> {output_filename.name} ...", "info")
try:
with tarfile.open(output_filename, "w:xz") as tar:
tar.add(source_dir, arcname=source_dir.name)
log_msg(logger, f"✅ Compression finished: {output_filename}", "info")
if delete_original:
shutil.rmtree(source_dir)
log_msg(logger, f"🗑️ Deleted original directory: {source_dir}", "info")
except Exception as e:
log_msg(logger, f"❌ Failed to compress directory {source_dir}: {e}", "error")
# If compression failed, ensure we don't leave a half-baked file
if output_filename.exists():
os.remove(output_filename)

View File

@@ -76,6 +76,7 @@ def parse_args():
{"name": "--base-mass", "type": float, "default": 0.0, "help": "Set the base mass of the robot."},
{"name": "--friction", "type": float, "default": 1.0, "help": "Set the ground friction coefficient."},
{"name": "--level", "type": int, "help": "Set the difficulty level of the environment, range 1-10 (flat is 0)."},
{"name": "--goals", "type": str, "nargs": "+", "help": "List of goal names to evaluate."},
# Multiprocessing parameters, with different seeds
{"name": "--multi", "action": "store_true", "default": False, "help": "Enable multiprocessing."},
@@ -91,6 +92,8 @@ def parse_args():
{"name": "--stress-benchmark", "action": "store_true", "default": False, "help": "Use stress pipeline to benchmark model robustness."},
{"name": "--stress-terrain-names", "type": str, "nargs": "+", "default": ["flat", "slope", "wave", "stairs_up", "stairs_down"], "help": "List of terrain names for stress benchmark."},
{"name": "--stress-num-processes", "type": int, "default": 2, "help": "Number of parallel processes for stress benchmark."},
{"name": "--compress-logs", "action": "store_true", "default": False, "help": "Compress and delete logs after run."},
]
for param in parameters:
parser.add_argument(param['name'], **{k: v for k, v in param.items() if k != 'name'})

View File

@@ -58,7 +58,8 @@ class Logger:
experiment_name,
run_name,
console_output=True, color_output=True,
log_level=logging.DEBUG, save_file_mode='a'
log_level=logging.DEBUG, save_file_mode='a',
parent_log_dir=None
):
"""
Create customed Logger
@@ -69,6 +70,7 @@ class Logger:
color_output (bool, optional): Whether use color output. Defaults to True.
log_level (int, optional): Defaults to logging.DEBUG.
save_file_mode (str, optional): The mode of saving to path_log_file
parent_log_dir (Path | str, optional): If specified, log_dir will be created under this directory.
Returns:
logging.Logger: logger
@@ -102,7 +104,11 @@ class Logger:
sh.setFormatter(console_formatter)
self.logger.addHandler(sh)
self.log_dir = Path(ROBOGAUGE_LOGS_DIR) / experiment_name / self.tag
if parent_log_dir:
baes_dir = Path(parent_log_dir)
else:
baes_dir = Path(ROBOGAUGE_LOGS_DIR)
self.log_dir = baes_dir / experiment_name / self.tag
self.log_dir.mkdir(parents=True, exist_ok=True)
path_log_file = self.log_dir / "stdout.log"
if path_log_file:

View File

@@ -9,7 +9,7 @@
'''
from robogauge import ROBOGAUGE_ROOT_DIR
from robogauge.utils.logger import logger
from robogauge.utils.helpers import parse_args, set_seed
from robogauge.utils.helpers import parse_args, set_seed, class_to_dict
from robogauge.tasks.gauge.gauge_configs.terrain_levels_config import TerrainSearchLevelsConfig
class TaskRegister():
@@ -73,14 +73,23 @@ class TaskRegister():
if args.level is not None:
gauger_cfg.assets.terrain_level = args.level
levels_cfg = TerrainSearchLevelsConfig()
cfg = getattr(levels_cfg, gauger_cfg.assets.terrain_name)
cfg = getattr(levels_cfg, gauger_cfg.assets.terrain_name, None)
assert cfg is not None, f"Level {args.level} configuration not found in TerrainLevelsConfig."
assert args.level in cfg.levels, f"Level must be in {cfg.levels}."
gauger_cfg.goals.target_pos_velocity.target_pos = cfg.targets[cfg.levels.index(args.level)]
if hasattr(cfg, 'targets'):
gauger_cfg.goals.target_pos_velocity.target_pos = cfg.targets[cfg.levels.index(args.level)]
if hasattr(cfg, 'spawns'):
gauger_cfg.assets.terrain_spawn_pos = cfg.spawns[cfg.levels.index(args.level)]
xml = gauger_cfg.assets.terrain_xmls[0]
xml = xml.rsplit('/', 1)[0] + f"/{gauger_cfg.assets.terrain_name}_{args.level}.xml"
gauger_cfg.assets.terrain_xmls[0] = xml
if args.goals is not None:
keys = class_to_dict(gauger_cfg.goals).keys()
enable_count = 0
for key in keys:
flag = key in args.goals
getattr(gauger_cfg.goals, key).enabled = flag
enable_count += int(flag)
assert enable_count > 0, f"At least one goal must be enabled from '{args.goals}', available goals are {list(keys)}."
task_register = TaskRegister()