Files
chenlin 438e56bcc8
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
feat(training): release V0.9.1 避障训练与基础策略迁移
2026-09-08 10:50:13 +08:00

84 lines
3.8 KiB
Python

import json
import math
import sys
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from task_config import ( # noqa: E402
FLAT_TASK,
OBSTACLE_TASK,
TERRAIN_PRESETS,
build_terrain_layout,
deployment_metadata,
navigation_candidates,
validate_task_config,
)
class TaskConfigTest(unittest.TestCase):
def test_flat_legacy_request_does_not_override_environment(self):
self.assertIsNone(validate_task_config(FLAT_TASK, {}, 42))
self.assertNotIn("terrain", deployment_metadata(FLAT_TASK, None, 42))
def test_layouts_are_bounded_finite_and_leave_flat_spawn_goal(self):
for preset in (p for p in TERRAIN_PRESETS if p != "custom_boxes"):
with self.subTest(preset=preset):
custom = validate_task_config(OBSTACLE_TASK, {"terrainPreset": preset}, 42)
layout = build_terrain_layout(custom)
self.assertLessEqual(len(layout["boxes"]), 257)
self.assertLess(len(json.dumps(layout)), 64 * 1024)
self.assertEqual(layout["spawn"], [-5, 0, 0.32])
self.assertEqual(layout["target"], [5, 0])
for box in layout["boxes"]:
self.assertTrue(all(math.isfinite(v) for v in box["pos"] + box["size"]))
self.assertTrue(all(v > 0 for v in box["size"]))
self.assertEqual(box["yaw"], 0)
for box in layout["boxes"][1:]:
self.assertGreaterEqual(box["pos"][0] - box["size"][0], -4)
self.assertLessEqual(box["pos"][0] + box["size"][0], 4)
def test_layout_is_deterministic_and_export_is_authoritative(self):
custom = validate_task_config(OBSTACLE_TASK, {}, 42)
original = build_terrain_layout(custom)
self.assertEqual(original, build_terrain_layout(custom))
self.assertNotEqual(original, build_terrain_layout({**custom, "seed": 43}))
metadata = deployment_metadata(OBSTACLE_TASK, custom, 42)
self.assertEqual(metadata["terrain"], original)
self.assertEqual(metadata["observationSize"], 47 + 32 + 2)
self.assertEqual(metadata["jointNames"][0], "FL_hip_joint")
self.assertEqual(metadata["navigation"]["distanceScale"], 12)
self.assertTrue(metadata["sensorCfg"]["includeGround"])
self.assertEqual(metadata["navigation"]["trainingReset"], "random-connected-free-pair")
def test_navigation_candidates_are_safe_connected_and_have_distant_fallbacks(self):
layout = build_terrain_layout(validate_task_config(OBSTACLE_TASK, {}, 42))
candidates = navigation_candidates(layout)
self.assertGreater(len(candidates["points"]), 2)
self.assertEqual(len(candidates["componentStarts"]), len(candidates["fallbackPairs"]))
for point in candidates["points"]:
self.assertTrue(all(abs(value) <= layout["size"] / 2 - 0.55 for value in point))
for box in layout["boxes"][1:]:
distance = math.hypot(
max(abs(point[0] - box["pos"][0]) - box["size"][0], 0),
max(abs(point[1] - box["pos"][1]) - box["size"][1], 0),
)
self.assertGreater(distance, candidates["clearance"])
for first, second in candidates["fallbackPairs"]:
self.assertGreaterEqual(math.dist(first, second), candidates["minDistance"])
def test_obstacle_count_is_capped_by_spacing_capacity(self):
custom = validate_task_config(
OBSTACLE_TASK,
{
"terrainParams": {"size": 8, "spacing": 3, "obstacle_count": 100},
},
0,
)
layout = build_terrain_layout(custom)
self.assertEqual(layout["actualObstacleCount"], 2)
if __name__ == "__main__":
unittest.main()