Skip to content

Commit fa44c12

Browse files
Add tests for dtype fix and VecNormalize
test_observation_space_dtype: asserts the continuous observation space uses float64, directly documenting the bug fixed in this PR (was int64, causing float observations to be silently truncated to integers). test_observations_are_float: confirms sub-integer precision is preserved end-to-end after a physics step — the case that was broken before. test_ppo_saves_vecnorm: verifies that do_training() persists the VecNormalize statistics as <model>_vecnorm.pkl alongside the model zip, so inference can reload the same normalisation. test_ppo_vecnorm_updates: confirms the running mean is updated during training (normaliser is actually learning from observations, not stuck at zero).
1 parent 301d50e commit fa44c12

2 files changed

Lines changed: 37 additions & 0 deletions

File tree

tests/test_environment.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ def test_environment(crane: Callable, show: bool, v0: float = 1.0, reward_limit=
7676
assert q_values[obs2.tobytes()][2] == -98.1
7777

7878

79+
def test_observation_space_dtype(crane: Callable):
80+
env = AntiPendulumEnv(crane)
81+
assert env.observation_space.dtype == np.float64
82+
83+
84+
def test_observations_are_float(crane: Callable):
85+
env = AntiPendulumEnv(crane)
86+
env.reset()
87+
obs, _, _, _, _ = env.step(1) # one physics step produces fractional values
88+
assert obs.dtype == np.float64
89+
assert not np.all(obs == obs.astype(int)) # sub-integer precision is preserved
90+
91+
7992
def test_init(crane: Crane, show: bool = False):
8093
"""Test the initialization of the environment."""
8194
env = AntiPendulumEnv(crane, seed=1, start_speed=1.0, render_mode="play-back" if show else "data")

tests/test_ppo.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import logging
2+
from pathlib import Path
23

4+
import numpy as np
35
from py_crane.crane import Crane
46

57
from crane_controller.envs.controlled_crane_pendulum import AntiPendulumEnv
@@ -20,3 +22,25 @@ def test_monitor(crane: Crane, show: bool):
2022
},
2123
)
2224
agent.do_training(1000)
25+
26+
27+
def test_ppo_saves_vecnorm(crane, tmp_path):
28+
save_path = str(tmp_path / "model.zip")
29+
agent = ProximalPolicyOptimizationAgent(
30+
AntiPendulumEnv, # type: ignore[arg-type]
31+
n_envs=1,
32+
env_kwargs={"crane": crane, "start_speed": 1.0},
33+
trained=(save_path, True),
34+
)
35+
agent.do_training(500, progress_bar=False)
36+
assert (tmp_path / "model_vecnorm.pkl").exists()
37+
38+
39+
def test_ppo_vecnorm_updates(crane):
40+
agent = ProximalPolicyOptimizationAgent(
41+
AntiPendulumEnv, # type: ignore[arg-type]
42+
n_envs=1,
43+
env_kwargs={"crane": crane, "start_speed": 1.0},
44+
)
45+
agent.do_training(500, progress_bar=False)
46+
assert not np.allclose(agent.vec_env.obs_rms.mean, 0.0)

0 commit comments

Comments
 (0)