Views
No views yet
<weld> equality with soft
solimp to model grip-on-cube without the qpos-teleport "magic grasp"
hack used in earlier checkpoints. Closer to real-robot behavior.episode_success=118, external
Brax Evaluator reports 97-127 on the saved pickle (matches).| File | Purpose |
|---|---|
policy.pkl | Pickled (RunningStatisticsState, policy_params, value_params) tuple from Brax PPO train_fn return. Direct load via pickle.load. |
network_meta.json | Network factory kwargs needed to reconstruct the inference function (obs_size, action_size, hidden layer sizes, activation, normalize_observations). |
eval_results.json | 100-episode external eval: episode_success_rate, mean_min_dist, time_to_first_success, per-episode breakdown. |
1import pickle, json, functools, jax
2from brax.training.agents.ppo import networks as ppo_networks
3from flax.linen import silu
4
5# Load
6with open("policy.pkl", "rb") as f:
7 params = pickle.load(f)
8meta = json.load(open("network_meta.json"))
9
10# Reconstruct
11nets = ppo_networks.make_ppo_networks(
12 observation_size=meta["obs_size"],
13 action_size=meta["action_size"],
14 policy_hidden_layer_sizes=tuple(meta["policy_hidden_layer_sizes"]),
15 value_hidden_layer_sizes=tuple(meta["value_hidden_layer_sizes"]),
16 activation=silu,
17)
18inference_fn = ppo_networks.make_inference_fn(nets)(params, deterministic=True)
19inference_fn = jax.jit(inference_fn)
20
21# Run on a 32-dim obs vector
22action, _ = inference_fn(obs, jax.random.PRNGKey(0))
23# action is 6-dim: 5 arm-joint deltas + 1 gripper delta, scaled by 0.03 radpython pickplace_mjx/train.py --no-normalize-obs --total-timesteps 60000000 in the
VLA-Models repo
at commit 4f8df3e or later.| Hyperparam | Value |
|---|---|
| Algorithm | PPO (Brax) |
| Architecture | MLP 2×256, silu, lecun_uniform init |
| Action distribution | tanh-normal, scalar log_std, init=1.0 |
num_envs | 1024 |
unroll_length | 32 |
num_minibatches | 4 |
num_updates_per_batch | 5 |
learning_rate | 1e-4 |
entropy_cost | 0.01 |
clip_epsilon | 0.2 |
discounting (γ) | 0.99 |
normalize_observations | False (workaround for an Orbax round-trip bug in Brax — see below) |
total_timesteps | 60M env-steps target (overshot via brax counter) |
| Sim backend | mujoco-warp 1.12 (MJX warp impl) |
SO101PickPlace from pickplace_mjx/env.py:mujoco_menagerie/robotstudio_so1012 0.05 0.005,
condim=6, priority=2x ∈ [0.08, 0.18], y ∈ [0.08, 0.22], z ∈ [0.10, 0.14] per episodez = 0.03 (resting on table)<weld> equality between moving_jaw_so101_v1 and box,
active="false" initially. The env activates data.eq_active[weld_id]
when the grasp predicate (gripper_qpos > 0.3 AND ee_to_cube_dist < 0.07)
fires. Soft solimp="0.7 0.9 0.001" lets the cube settle into a fixed
relpose (0, -0.05, 0.02, identity_quat) smoothly without catapult.RunningStatisticsState doesn't round-
trip cleanly through Orbax checkpoints. Enabling normalize-obs gave
the policy training peak success=99-117 but external eval = 0. Using
normalize_observations=False slows learning ~10% but produces a
serializable policy.@misc{kitano_2026_pickplace_mjx_day11,
title = {pickplace_mjx — SO-101 single-arm pick-and-lift PPO baseline},
author = {Rihito Kitano},
year = {2026},
url = {https://huggingface.co/Ripito/pickplace-mjx-day11-weld},
note = {Phase 1 sim baseline of the SOP-VLA project, MJX + Brax PPO}
}