Download applications/avoiding/avoiding_baselines/DiRecT/obstacles.py from GlobalMotionPlanning/GlobMP: direct link, hf CLI and curl.
- Browser
- Download file 3.6 kB
-
https://huggingface.co/GlobalMotionPlanning/GlobMP/resolve/main/applications/avoiding/avoiding_baselines/DiRecT/obstacles.py
- Command line
-
hf download hf://GlobalMotionPlanning/GlobMP/applications/avoiding/avoiding_baselines/DiRecT/obstacles.py
-
curl -L -o obstacles.py https://huggingface.co/GlobalMotionPlanning/GlobMP/resolve/main/applications/avoiding/avoiding_baselines/DiRecT/obstacles.py
3.6 kB
| import os | |
| """ | |
| Central obstacle definitions for the avoiding-v0 environment. | |
| All coordinates are in real-world (unnormalized) space. | |
| Import from here — do not duplicate obstacle geometry elsewhere. | |
| """ | |
| from dataclasses import dataclass | |
| class CircularObstacle: | |
| """Circular keep-out zone defined by center and radius.""" | |
| center: tuple # (x, y) | |
| radius: float | |
| class PlanarObstacle: | |
| """Half-plane constraint: slope * x + intercept - y >= 0 is the feasible side.""" | |
| point_a: tuple # (x, y) | |
| point_b: tuple # (x, y) | |
| def slope(self): | |
| return (self.point_b[1] - self.point_a[1]) / (self.point_b[0] - self.point_a[0]) | |
| def intercept(self): | |
| return self.point_b[1] - self.slope * self.point_b[0] | |
| def violated(self, x, y): | |
| return y > self.slope * x + self.intercept | |
| # --------------------------------------------------------------------------- | |
| # Obstacle sets | |
| # --------------------------------------------------------------------------- | |
| PILLARS = [ | |
| CircularObstacle(center=(0.5, -0.1), radius=0.03), | |
| CircularObstacle(center=(0.425, 0.08), radius=0.025), | |
| CircularObstacle(center=(0.575, 0.08), radius=0.025), | |
| CircularObstacle(center=(0.35, 0.26), radius=0.025), | |
| CircularObstacle(center=(0.5, 0.26), radius=0.025), | |
| CircularObstacle(center=(0.65, 0.26), radius=0.025), | |
| ] | |
| NOVEL_CIRCULAR = [ | |
| CircularObstacle(center=(0.5, -0.1), radius=0.08), | |
| ] | |
| # Three further keep-outs that ship commented out in the upstream release. | |
| # They sit in the l2 -> l3 mid-band (y ~ 0.16-0.175), where the demonstrations | |
| # run straight through, and narrow the tightest passage from 0.100 m to | |
| # 0.063 m. Enabled only by D3IL_HARD=1 so that the default constraint set | |
| # stays bit-identical to every number already reported. | |
| NOVEL_CIRCULAR_HARD = [ | |
| CircularObstacle(center=(0.5, 0.16), radius=0.02), | |
| CircularObstacle(center=(0.4, 0.175), radius=0.02), | |
| CircularObstacle(center=(0.6, 0.175), radius=0.02), | |
| ] | |
| if os.environ.get("D3IL_HARD", "0") == "1": | |
| NOVEL_CIRCULAR = NOVEL_CIRCULAR + NOVEL_CIRCULAR_HARD | |
| NOVEL_PLANAR = [ | |
| PlanarObstacle(point_a=(0.8, -0.3), point_b=(0.575, 0.5)), | |
| PlanarObstacle(point_a=(0.2, -0.3), point_b=(0.425, 0.5)), | |
| ] | |
| CONSTRAINT_SETS = { | |
| "novel": { | |
| "circular": PILLARS + NOVEL_CIRCULAR, | |
| "planar": NOVEL_PLANAR, | |
| }, | |
| } | |
| def count_constraints(constraint_name): | |
| if constraint_name == "" or constraint_name not in CONSTRAINT_SETS: | |
| return 0 | |
| cs = CONSTRAINT_SETS[constraint_name] | |
| return len(cs["circular"]) + len(cs["planar"]) | |
| TARGET_Y = 0.35 # y coordinate of the arrival/goal region | |
| def check_violation(observation, constraint_name): | |
| """Check if a single observation violates any constraint in the given set. | |
| Returns 1.0 if violated, 0.0 otherwise. | |
| Constraints are not checked once the agent reaches the target region (y >= TARGET_Y). | |
| """ | |
| import numpy as np | |
| if constraint_name == "": | |
| return 0.0 | |
| if constraint_name not in CONSTRAINT_SETS: | |
| raise NotImplementedError(f"Constraint '{constraint_name}' is not implemented.") | |
| x = observation[2] | |
| y = observation[3] | |
| if y >= TARGET_Y: | |
| return 0.0 | |
| constraints = CONSTRAINT_SETS[constraint_name] | |
| for obs in constraints["circular"]: | |
| distance = np.sqrt((x - obs.center[0]) ** 2 + (y - obs.center[1]) ** 2) | |
| if distance <= obs.radius: | |
| return 1.0 | |
| for obs in constraints["planar"]: | |
| if obs.violated(x, y): | |
| return 1.0 | |
| return 0.0 | |