| from __future__ import annotations |
|
|
| import numpy as np |
|
|
| from driftwm.sim.env import SurfaceBoatEnv |
| from driftwm.sim.flow import UniformFlow |
|
|
|
|
| def test_noflow_drag_reduces_speed() -> None: |
| env = SurfaceBoatEnv(boat="twin", flow_type="noflow", boundary="bounce", randomize_params=False, seed=1) |
| env.reset(random_velocity=False) |
| env.state[:6] = np.array([5.0, 5.0, 0.2, 0.8, -0.25, 0.0], dtype=np.float32) |
| initial = np.linalg.norm(env.state[3:5]) |
| speeds = [] |
| for _ in range(120): |
| env.step(np.zeros(env.action_dim, dtype=np.float32)) |
| speeds.append(np.linalg.norm(env.state[3:5])) |
| assert speeds[-1] < 0.45 * initial |
| assert np.mean(np.diff(speeds) <= 1e-4) > 0.9 |
|
|
|
|
| def test_uniform_flow_zero_action_converges_to_flow_velocity() -> None: |
| flow_vec = np.array([0.22, -0.08], dtype=np.float32) |
| flow = UniformFlow(flow_vec, flow_id=7) |
| env = SurfaceBoatEnv( |
| boat="twin", |
| flow_type="uniform", |
| boundary="bounce", |
| randomize_params=False, |
| seed=2, |
| workspace=(0.0, 40.0, 0.0, 40.0), |
| ) |
| env.reset(flow=flow, random_velocity=False) |
| env.state[:6] = np.array([20.0, 20.0, 0.0, 0.0, 0.0, 0.0], dtype=np.float32) |
| for _ in range(500): |
| env.step(np.zeros(env.action_dim, dtype=np.float32)) |
| assert np.linalg.norm(env.state[3:5] - flow_vec) < 0.08 |
|
|
|
|
| def test_twin_thruster_torque_signs_are_opposite() -> None: |
| env_l = SurfaceBoatEnv(boat="twin", flow_type="noflow", boundary="bounce", randomize_params=False, seed=3) |
| env_r = SurfaceBoatEnv(boat="twin", flow_type="noflow", boundary="bounce", randomize_params=False, seed=4) |
| env_l.reset(random_velocity=False) |
| env_r.reset(random_velocity=False) |
| env_l.state[:6] = np.array([5.0, 5.0, 0.0, 0.0, 0.0, 0.0], dtype=np.float32) |
| env_r.state[:6] = env_l.state[:6].copy() |
| for _ in range(25): |
| env_l.step(np.array([1.0, 0.0], dtype=np.float32)) |
| env_r.step(np.array([0.0, 1.0], dtype=np.float32)) |
| assert env_l.state[5] * env_r.state[5] < 0.0 |
|
|