This commit is contained in:
wty-yy
2025-12-28 21:25:08 +08:00
parent 9bcee5004a
commit f1040af529
11 changed files with 140 additions and 39 deletions

View File

@@ -1,6 +1,6 @@
from robogauge.utils.task_register import task_register
from robogauge.tasks.simulator.mujoco_config import MujocoConfig
from robogauge.tasks.robots import RobotConfig, Go2Config, Go2MoEConfig, Go2TerrainConfig, Go2MoETerrainConfig
from robogauge.tasks.robots import RobotConfig, Go2Config, Go2MoEConfig, Go2TerrainConfig, Go2MoETerrainConfig, Go2StairsConfig, Go2MoEStairsConfig
from robogauge.tasks.pipeline import BasePipeline
from robogauge.tasks.gauge import BaseGaugeConfig

View File

@@ -30,7 +30,7 @@ class Go2FlatGaugeConfig(FlatGaugeConfig):
cmd_duration = 6.0
class target_pos_velocity(FlatGaugeConfig.goals.target_pos_velocity): # goal to reach a target position by velocity command, config target at assets.target_pos
enabled = True
enabled = False
target_pos = [2, 2, 0] # x y z [m], target position in the environment, used for target position goal
lin_vel_x = 1.0 # +/- m/s
lin_vel_y = 1.0 # +/- m/s

View File

@@ -7,7 +7,6 @@
@Blog : https://wty-yy.github.io/
@Desc : Go2 Wave Task Configuration
'''
from robogauge.tasks.robots import Go2Config, Go2MoEConfig
from robogauge.tasks.gauge import StairsUpGaugeConfig
from robogauge.tasks.simulator.mujoco_config import MujocoConfig

View File

@@ -9,6 +9,8 @@
'''
from robogauge.utils.config import Config
SEARCH_LEVELS_TERRAINS = ['slope', 'wave', 'stairs_up', 'stairs_down', 'obstacle']
class TerrainSearchLevelsConfig(Config):
class flat:
levels = [0]
@@ -91,6 +93,9 @@ class TerrainSearchLevelsConfig(Config):
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
class TerrainEvalLevelsConfig(Config):
class flat:
levels = [0]
class slope:
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
spawns = [
@@ -105,3 +110,63 @@ class TerrainEvalLevelsConfig(Config):
[5.0, 0, 4.2 * (0.57 - 0.047)],
[5.0, 0, 4.2 * 0.57],
]
class wave:
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
spawns = [
[4.55, 0, 0.65 - 0.075 * 9],
[4.55, 0, 0.65 - 0.075 * 8],
[4.55, 0, 0.65 - 0.075 * 7],
[4.55, 0, 0.65 - 0.075 * 6],
[4.55, 0, 0.65 - 0.075 * 5],
[4.55, 0, 0.65 - 0.075 * 4],
[4.55, 0, 0.65 - 0.075 * 3],
[4.55, 0, 0.65 - 0.075 * 2],
[4.55, 0, 0.65 - 0.075 * 1],
[4.55, 0, 0.65],
]
class stairs_up:
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
spawns = [
[5.0, 0.0, 1.35],
[5.0, 0.0, 1.80],
[5.0, 0.0, 2.25 + 0.03],
[5.0, 0.0, 2.70 + 0.08],
[5.0, 0.0, 2.85 + 0.1],
[5.0, 0.0, 3.00 + 0.12],
[5.0, 0.0, 3.15 + 0.14],
[5.0, 0.0, 3.30 + 0.16],
[5.0, 0.0, 3.45 + 0.18],
[5.0, 0.0, 3.60 + 0.2],
]
class stairs_down:
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
spawns = [
[5.1, 0.0, 1.35],
[5.1, 0.0, 1.80 + 0.08],
[5.1, 0.0, 2.25 + 0.15],
[5.1, 0.0, 2.70 + 0.25],
[5.1, 0.0, 2.85 + 0.27],
[5.1, 0.0, 3.00 + 0.30],
[5.1, 0.0, 3.15 + 0.33],
[5.1, 0.0, 3.30 + 0.36],
[5.1, 0.0, 3.45 + 0.39],
[5.1, 0.0, 3.60 + 0.42],
]
class obstacle:
levels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
spawns = [
[5, 0.0, 0.20 - 0.023 * 9],
[5, 0.0, 0.20 - 0.023 * 8],
[5, 0.0, 0.20 - 0.023 * 7],
[5, 0.0, 0.20 - 0.023 * 6],
[5, 0.0, 0.20 - 0.023 * 5],
[5, 0.0, 0.20 - 0.023 * 4],
[5, 0.0, 0.20 - 0.023 * 3],
[5, 0.0, 0.20 - 0.023 * 2],
[5, 0.0, 0.20 - 0.023 * 1],
[5, 0.0, 0.20],
]

View File

@@ -25,6 +25,7 @@ from robogauge.utils.logger import Logger
from robogauge.utils.process_utils import NoDaemonPool
from robogauge.utils.progress_monitor import report_progress, ProgressTypes, ProgressData
from robogauge.utils.file_utils import compress_directory
from robogauge.tasks.gauge.gauge_configs.terrain_levels_config import SEARCH_LEVELS_TERRAINS
multi_logger = Logger() # MultiPipeline logger
@@ -132,7 +133,7 @@ class MultiPipeline:
""" Process results from all processes and aggregate them. """
multi_logger.info("📊 Aggregating Results from all runs...")
summary = {'success': {}, **self.static_info, 'summary': {}}
summary = {'success': {}, **self.static_info, 'summary': {}, 'quality_score': {}, 'terrain_quality_score': {}}
finish_msg = (
f"""\n{'='*20} Run Finish Summary {'='*20}\n"""
f"""{'Seed':^10}{'Base Mass':^15}{'Friction':^15}{'Status':^10}\n"""
@@ -151,6 +152,7 @@ class MultiPipeline:
multi_logger.error("No results to aggregate.")
return
quality_score, terrain_quality_score = summary['quality_score'], summary['terrain_quality_score']
value_collections = defaultdict(lambda: defaultdict(list))
for result in all_results:
for goal, metrics in result['results'].items():
@@ -159,11 +161,22 @@ class MultiPipeline:
for metric, means in metrics.items():
for mean_name, mean_value in means.items():
value_collections[metric][mean_name].append(float(mean_value.split(' ')[0]))
quality_score[mean_name] = 1
for metric, means in value_collections.items():
summary['summary'][metric] = {}
for mean_name, values in means.items():
summary['summary'][metric][mean_name] = f"{float(np.mean(values)):.4f} ± {float(np.std(values)):.4f}"
v = float(np.mean(values))
summary['summary'][metric][mean_name] = f"{v:.4f} ± {float(np.std(values)):.4f}"
weight = 1
if metric in ['ang_vel_err', 'lin_vel_err']:
weight = 2
quality_score[mean_name] *= min(max(1e-9, v), 1.0) ** weight
for mean_name in quality_score:
quality_score[mean_name] = quality_score[mean_name] ** (1 / 8) # 2 + 2 + 1 * 4
terrain_quality_score[mean_name] = quality_score[mean_name]
if summary['terrain_name'] in SEARCH_LEVELS_TERRAINS:
terrain_quality_score[mean_name] = 0.09 * (summary['terrain_level'] - 1) + 0.19 * quality_score[mean_name]
save_path = multi_logger.log_dir / "aggregated_results.yaml"
with open(save_path, 'w') as file:

View File

@@ -27,7 +27,7 @@ from robogauge.utils.logger import Logger
from robogauge.utils.process_utils import NoDaemonPool
from robogauge.utils.progress_monitor import report_progress, ProgressTypes, start_progress_monitor_thread, ProgressData
from robogauge.tasks.pipeline import MultiPipeline, LevelPipeline
from robogauge.tasks.gauge.gauge_configs.terrain_levels_config import TerrainSearchLevelsConfig
from robogauge.tasks.gauge.gauge_configs.terrain_levels_config import SEARCH_LEVELS_TERRAINS
from robogauge.utils.file_utils import compress_directory
stress_logger = Logger() # StressPipeline logger
@@ -57,6 +57,7 @@ def run_pipeline(args, progress_queue, data):
if search is True:
args.goals = GOALS['level_pipeline']
args.spawn_type = "level_search"
level, level_results = LevelPipeline(args, console_output=False, progress_data=progress_data).run()
if level == 0: # no valid level found
report_progress(progress_data, ProgressTypes.FINISH, desc=f"❌ Failed (Lv 0)")
@@ -76,6 +77,7 @@ def run_pipeline(args, progress_queue, data):
args.level = level
args.goals = GOALS['multi_pipeline']
args.spawn_type = "level_eval"
results = {
'success': True,
'results': MultiPipeline(args, console_output=False, progress_data=progress_data).run(),
@@ -113,12 +115,9 @@ class StressPipeline:
### Build worker data ###
workers_data = []
terrain_search_levels_config = TerrainSearchLevelsConfig()
for terrain_name in terrain_names:
search_max_level = True
terrain_level_cfg = getattr(terrain_search_levels_config, terrain_name, None)
assert terrain_level_cfg is not None, f"Terrain '{terrain_name}' not found in TerrainSearchLevelsConfig."
if len(terrain_level_cfg.levels) == 1: # Flattened terrain
if terrain_name not in SEARCH_LEVELS_TERRAINS: # Flattened terrain
search_max_level = False
data = {
'task_robot_model': self.task_robot_model,
@@ -179,8 +178,9 @@ class StressPipeline:
stress_logger.error("No results to aggregate.")
return
summary = {**self.static_info, 'summary': {}, 'final_score': {}}
value_collections = defaultdict(lambda: defaultdict(list))
summary = {**self.static_info, 'summary': {}, 'robust_score': {}, 'benchmark_score': 0.0}
metric_collections = defaultdict(lambda: defaultdict(list))
terrain_collections = defaultdict(lambda: defaultdict(list))
zero_terrain_count = 0
for result in all_results:
terrain_name = result['data']['terrain_name']
@@ -194,21 +194,27 @@ class StressPipeline:
summary[key] = result['results']
for metric, means in result['results']['summary'].items():
for mean_name, mean_value in means.items():
value = float(mean_value.split(' ')[0])
if terrain_level is not None: # level terrain
value = (terrain_level - 1) * 0.1 + value * 0.1
value_collections[metric][mean_name].append(value)
for mean_name, value_str in means.items():
value = float(value_str.split(' ± ')[0])
metric_collections[metric][mean_name].append(value)
for mean_name, value in result['results']['terrain_quality_score'].items():
terrain_collections[terrain_name][mean_name].append(value)
final_metrics = defaultdict(list)
for metric, means in value_collections.items():
for metric, means in metric_collections.items():
summary['summary'][metric] = {}
for mean_name, values in means.items():
values.extend([0.0] * zero_terrain_count) # include zero terrains
summary['summary'][metric][mean_name] = f"{float(np.mean(values)):.4f} ± {float(np.std(values)):.4f}"
final_metrics[mean_name].append(np.mean(values))
for mean_name, values in final_metrics.items():
summary['final_score'][mean_name] = float(np.mean(values))
robust_score = defaultdict(dict)
robust_scores = []
for terrain_name, means in terrain_collections.items():
for mean_name, values in means.items():
values.extend([0.0] * zero_terrain_count) # include zero terrains
robust_score[terrain_name][mean_name] = float(np.mean(values))
robust_scores.append(robust_score[terrain_name][mean_name])
summary['robust_score'] = dict(robust_score)
summary['benchmark_score'] = float(np.mean(robust_scores))
save_path = stress_logger.log_dir / "stress_benchmark_results.yaml"
with open(save_path, 'w') as file:

View File

@@ -1,6 +1,6 @@
from .base_robot_config import RobotConfig
from .base_robot import BaseRobot
from .go2.go2_config import Go2Config, Go2TerrainConfig
from .go2.go2_config import Go2Config, Go2TerrainConfig, Go2StairsConfig
from .go2.go2 import Go2
from .go2.go2_moe_config import Go2MoEConfig, Go2MoETerrainConfig
from .go2.go2_moe_config import Go2MoEConfig, Go2MoETerrainConfig, Go2MoEStairsConfig
from .go2.go2_moe import Go2MoE