Level 12 (after Lessons 12.1 and 12.2) · Time 4 hours · Difficulty 3 of 5
A gymnasium.Env for the push task, written from scratch on models/push.xml, with three action spaces: joint torques, joint targets and end-effector deltas. Every quantity in the observation must have a real-robot source. The environment is reviewed by machine: Gymnasium’s own checker, the course’s five further checks (mjcourse.capstone), and tests of what the actions and observations mean.
terminated versus truncated, seeding through self.np_random).mjcourse.kinematics is the course’s version.starter.py declares PushEnv(action_mode, max_episode_steps, frame_skip, render_mode); its docstring is the specification. Do not subclass mjcourse.envs. Follow the course’s conventions so the checker can inspect your environment: attributes model, data, max_episode_steps and observation_sources, and a method _get_obs().
The reference passes mjcourse.capstone.check in all three modes, in 0.1 to 0.2 s each. Its actions do what the docstring says:
terminated=True, truncated=False on the first step.MJC_IMPL=starter pytest projects/p10_gym_env
pytest projects/p10_gym_env
Ten tests:
check_env, observations that are copies, truncation at the time limit, bit-identical replay from a seed, every source a real sensor, and no change in the observation when the puck’s velocity, mass, friction or contact stiffness changes;python tools/mutate_project.py p10_gym_env checks the seven mutants in mutants.json.
mj_resetData, without mj_forward, the first observation puts the tool at the origin: mj_resetData zeroes the derived fields. After mj_step, without mj_kinematics, the tool position is the one from before the last substep, 0.42 mm behind at most in this environment. Neither breaks reproducibility, so check_env and the replay test pass. The forward-kinematics test catches both.mj_forward, and all four perturbations were reported as leaks. mjcourse.envs.checks.perturbation_leaks now calls mj_forward first, so staleness is reported only by the test that names it.self.np_random. Two environments reset with the same seed differ. The replay test catches it.gymnasium.vector.AsyncVectorEnv over 16 processes, started with spawn); measure steps per second against the single environment.overview camera, with its source declared, and make the checker accept it.solution.py, about 140 lines.