|
| 1 | +# Changelog |
| 2 | + |
| 3 | +All notable changes to GeneLab are recorded here. The format follows |
| 4 | +[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project is still on a 0.x |
| 5 | +trajectory so breaking changes can land in any minor release until the 1.0 stabilisation. |
| 6 | + |
| 7 | +## [Unreleased] |
| 8 | + |
| 9 | +### Added |
| 10 | + |
| 11 | +- `docs/concepts/rl-runner.{en,zh}.md`: bilingual concept page for `genelab.rl` |
| 12 | + (`train_task` / `play_task` signatures, `RslRlOnPolicyRunnerCfg` field |
| 13 | + layout, `AgentKind` Literal, `RslRlVecEnvWrapper` adapter, torchrun-based |
| 14 | + `--gpus N` distributed-training relaunch, `maybe_profile` flag/env-var |
| 15 | + matrix, failure modes). |
| 16 | +- `docs/concepts/mdp.{en,zh}.md`: bilingual reference for the reusable MDP term |
| 17 | + library (`genelab.mdp.{actions,commands,observations,rewards,terminations, |
| 18 | + events,curriculums,noise}`). Every re-exported function / class is tabulated |
| 19 | + with its required params, output shape, and a minimal wiring example, plus |
| 20 | + warnings on the `joint_acc_l2` / `feet_air_time` placeholder rewards. |
| 21 | +- `docs/concepts/managers.{en,zh}.md`, `docs/cli/list-info.{en,zh}.md`: bilingual |
| 22 | + manager-system concept page (seven managers + `ManagerTermBaseCfg` + term |
| 23 | + lifecycle + `EventMode` semantics + per-manager wiring examples) and CLI |
| 24 | + discovery page (`list KIND` enumeration, `info NAME` panel anatomy, override |
| 25 | + path lookup workflow, simulation flag shortcuts). |
| 26 | +- `examples/genelab_showcase/`: six play-only TaskCfgs that exercise every M1–M4 |
| 27 | + building block (sensors / ray-cast patterns / contact + air-time / 5 sub-terrains / |
| 28 | + `terrain_levels_vel` curriculum / `IdealPDActuator` arm). Each task dumps |
| 29 | + per-feature evidence (PNG frames, distance histograms, tracking error, terrain |
| 30 | + level histograms) into `logs/showcase/<slug>/` so the visual + numerical behaviour |
| 31 | + of every building block can be eyeballed without launching an RL training run. |
| 32 | +- `InteractiveScene.viewer_closed` / `ManagerBasedRlEnv.viewer_closed`: viewer-closed |
| 33 | + handling moved into the kernel. `InteractiveScene.step` catches Genesis's |
| 34 | + `GenesisException("Viewer closed.")`, flips the flag, and becomes a no-op on |
| 35 | + subsequent calls. Consumers (RL runner, showcase runner, custom rollouts) only |
| 36 | + need to poll `env.viewer_closed` and break; the previous per-consumer |
| 37 | + `try/except gs.GenesisException` boilerplate is no longer required. |
| 38 | +- `InteractiveSceneCfg.batch_render: bool`: when set, `InteractiveScene._build` |
| 39 | + passes `gs.renderers.BatchRenderer(use_rasterizer=False)` to `gs.Scene`. Required |
| 40 | + for `CameraSensor` to produce per-env RGB-D tensors. Defaults to `False` for |
| 41 | + backwards compatibility. |
| 42 | +- `Sensor.pre_build_genesis(gs_scene, entities)`: new no-op hook on the sensor base |
| 43 | + class. `InteractiveScene._build` calls it on every sensor cfg right after entity |
| 44 | + spawn and before `gs_scene.build`, giving sensors a chance to register Genesis |
| 45 | + resources that the renderer snapshots at build time. `CameraSensor` overrides it |
| 46 | + to allocate its camera early — required for BatchRender to register the camera in |
| 47 | + its build-time snapshot. `InteractiveScene.sensors` now exposes the resulting |
| 48 | + instances, and `ManagerBasedRlEnv` binds those instances instead of re-building. |
| 49 | +- `docs/concepts/scene.{en,zh}.md`: bilingual concept page covering the M1 stack — |
| 50 | + `InteractiveScene` lifecycle, `SimulationCfg`, `InteractiveSceneCfg`, `Articulation`, |
| 51 | + `RigidObject`, and the four documented failure modes. |
| 52 | +- `docs/examples/showcase.{en,zh}.md`, `docs/examples/unitree-g1.{en,zh}.md`: |
| 53 | + bilingual examples pages — the showcase index plus a distilled Unitree G1 |
| 54 | + walk-through (velocity tracking, motion imitation, long-run profiling). |
| 55 | +- `CameraSensor` (with `CameraSensorCfg` and `CameraData`): rigid-mount RGB-D probe |
| 56 | + wrapping Genesis's `BatchRenderer` camera. Per-env tensors with shape |
| 57 | + `(num_envs, H, W, 3)` for RGB (uint8) and `(num_envs, H, W)` for depth (float meters); |
| 58 | + both channels independently toggleable via `render_rgb` / `render_depth`. `bind()` |
| 59 | + resolves the named link, builds the 4×4 mounting offset from `offset_pos` / |
| 60 | + `offset_quat`, and calls `cam.attach`; `_compute_data()` runs `cam.move_to_attach()` |
| 61 | + then `cam.render(...)`. Linux x86-64 + CUDA only — Genesis's `BatchRenderer` is the |
| 62 | + only parallel-env camera backend. |
| 63 | +- `genelab.asset_zoo` now ships five built-in robots: `CartpoleCfg`, `FrankaPandaCfg`, |
| 64 | + `UnitreeG1Cfg` (29-DoF humanoid, 6 DCMotor groups mirroring |
| 65 | + `examples/unitree/.../g1/constants.py`), `UnitreeGo1Cfg` (12-DoF quadruped, 3 |
| 66 | + ImplicitPD groups aligned to Isaac Lab Go1 defaults), and `AnymalCCfg` (12-DoF |
| 67 | + quadruped, single ImplicitPD group aligned to Isaac Lab Anymal C defaults). All four |
| 68 | + Menagerie-sourced robots (Franka, G1, Go1, Anymal C) ship as `.tar.gz` bundles in |
| 69 | + `KraHsu/genelab-assets`, preserving the upstream LICENSE and README. |
| 70 | +- `AssetSpec.archive_member`: optional field that switches `fetch_asset` from |
| 71 | + single-file to archive mode. The URL is treated as a `.tar.gz`, the blob's md5 is |
| 72 | + verified end-to-end, and `tarfile`'s `data` filter extracts the contents into |
| 73 | + `<md5>/extracted/` (rejects symlinks, absolute paths, and parent-directory escapes). |
| 74 | + The returned path is `<md5>/extracted/<archive_member>` — Menagerie mesh references |
| 75 | + resolve automatically because the full folder structure is preserved. |
| 76 | +- `genelab.asset_zoo` namespace with the first two built-in robot configurations, |
| 77 | + `CartpoleCfg` and `FrankaPandaCfg`. Both are registered into `ROBOTS` as an import |
| 78 | + side-effect of `load_builtin_registries()`; factories stay lazy so `genelab list |
| 79 | + robots` never touches the network. Cartpole gain values mirror |
| 80 | + `examples/inverted_pendulum` (`stiffness=80`, passive pole); Franka follows Isaac |
| 81 | + Lab's high-PD configuration (`panda_arm` k=400, `panda_hand` k=1e4) with the |
| 82 | + Menagerie home pose. |
| 83 | + |
| 84 | +### Changed |
| 85 | + |
| 86 | +- **Breaking** (asset zoo only — no released API): `FrankaPandaCfg` now sources the full |
| 87 | + MuJoCo Menagerie `franka_emika_panda` model (Apache-2.0) instead of the minimal stub |
| 88 | + shipped during initial M4. Joint regexes drop the `panda_` prefix (`joint[1-7]`, |
| 89 | + `finger_joint.*`) to match the upstream MJCF, and `default_joint_pos` follows the |
| 90 | + Menagerie `home` keyframe (`joint4=-1.57079`, `joint6=1.57079`, `joint7=-0.7853`). |
| 91 | +- `genelab.utils.download.fetch_asset` + `AssetSpec` + `AssetDownloadError`: md5-verified |
| 92 | + download helper for asset zoo entries. Files cache under |
| 93 | + `<project_root>/.cache/assets/<name>/<md5>/<filename>` via atomic stage-and-rename; |
| 94 | + md5 mismatches and `URLError` failures raise `AssetDownloadError` with both expected |
| 95 | + and actual digests in the message. |
| 96 | +- `docs/concepts/asset_zoo.{en,zh}.md`: bilingual concept page covering the asset |
| 97 | + lifecycle, cache layout, md5 verification, and the template for adding new robot |
| 98 | + configurations. |
| 99 | +- `FrameTransformerSensor` (with `FrameTransformerSensorCfg`, `TargetFrameCfg`, and |
| 100 | + `FrameTransformerData`): stateless forward-kinematics probe that outputs the world-frame |
| 101 | + pose AND source-frame pose for one or more target frames relative to a single source |
| 102 | + frame. Both source and target support rigid local-frame offsets (position + quaternion). |
| 103 | + `target_frames` is order-preserving so observation terms can slice by position; the |
| 104 | + matching `target_names: tuple[str, ...]` attribute exposes column identities. `bind` |
| 105 | + rejects unknown link names and empty `target_frames` (mirrors the contact-sensor |
| 106 | + unresolved-link error path). |
| 107 | +- `IMUSensor` (with `IMUSensorCfg` and `IMUData`) sits alongside `BodyVelocitySensor` and |
| 108 | + outputs orientation, body-frame projected unit gravity, and body-frame linear / angular |
| 109 | + acceleration at a site rigidly attached to a link. Accelerations are computed by finite |
| 110 | + difference of the world-frame velocity buffers; the first control step after each |
| 111 | + `reset` returns zero acceleration (deliberate — avoids a spurious spike from a stale |
| 112 | + prev buffer). `gravity_bias=True` (default) follows the real-IMU specific-force |
| 113 | + convention. Per-env `bias_range_lin_acc` / `bias_range_ang_acc` resample on every reset. |
| 114 | +- `RingPattern` and `HemispherePattern` ray-cast patterns alongside the existing |
| 115 | + `GridPattern`. `RingPattern` covers multi-line LIDAR sweeps (`num_horizontal × num_vertical` |
| 116 | + rays, automatic wrap-around handling on a 360° span); `HemispherePattern` distributes rays |
| 117 | + on a spherical cap via a Fibonacci lattice with configurable pole axis and half-angle. |
| 118 | + `RayCastSensorCfg.pattern` is now typed `GridPattern | RingPattern | HemispherePattern`. |
| 119 | +- `genelab.terrains` namespace with `SubTerrainCfg` (abstract) and five concrete |
| 120 | + sub-terrains: `FlatPatchCfg`, `PyramidStairsCfg`, `RandomRoughCfg`, `SlopeCfg`, |
| 121 | + `WaveCfg`. `TerrainGeneratorCfg` composes them into a 2D grid (random by proportion |
| 122 | + or explicit `layout`); `TerrainGenerator` emits Genesis kwargs and per-cell |
| 123 | + `env_origins`; `TerrainImporter` spawns `gs.morphs.Terrain` and exposes the |
| 124 | + post-build `heightfield` for sensors. |
| 125 | +- `InteractiveSceneCfg.terrain` now accepts a `TerrainGeneratorCfg`; `InteractiveScene` |
| 126 | + routes through `TerrainImporter` when set, falling back to the default flat plane |
| 127 | + otherwise. `InteractiveScene.terrain` exposes the active importer to consumers. |
| 128 | +- `RayCastSensor` now samples `scene.terrain.heightfield_tensor` bilinearly when a |
| 129 | + terrain is attached; flat-plane behaviour is preserved when `scene.terrain is None` |
| 130 | + or when the sensor runs against a fake env without a `scene` attribute (unit-test |
| 131 | + surface). `TerrainHeightSensor` inherits the new path through its inner ray-cast. |
| 132 | +- `TerrainImporter` gains `heightfield_tensor(device, dtype)` (device-keyed cache), |
| 133 | + `horizontal_scale`, `vertical_scale`, and `terrain_origin` accessors used by the |
| 134 | + ray-cast sampler. |
| 135 | +- `TerrainImporter` tracks per-env curriculum state via `terrain_levels` / |
| 136 | + `terrain_cols` / `spawn_pos`; `init_per_env_state(num_envs, device)` is called once |
| 137 | + by `InteractiveScene.build()` post-Genesis-build. `update_env_origins(env_ids)` |
| 138 | + recomputes spawn origins after a level change. |
| 139 | +- `genelab.mdp.curriculums.terrain_levels_vel`: curriculum term that promotes / |
| 140 | + demotes each env's terrain level by how far it walked from spawn (XY distance vs |
| 141 | + configurable `distance_threshold` and `demote_ratio`), then writes the new spawn |
| 142 | + pose into the sim via `Articulation.write_root_state`. |
| 143 | +- `docs/concepts/terrains.{en,zh}.md`: bilingual concept page covering the generator, |
| 144 | + importer, sensor integration, curriculum, and known failure modes. |
| 145 | +- `genelab.actuator` namespace with `ActuatorBase` and three concrete electromechanical |
| 146 | + models: `ImplicitPDActuator` (Genesis-internal PD), `IdealPDActuator` (Python-side PD |
| 147 | + via `control_dofs_force`), `DCMotorActuator` (`IdealPD` plus driving-direction torque |
| 148 | + saturation). |
| 149 | +- `ArticulationCfg.actuators: dict[str, ActuatorBaseCfg]` groups joints by regex and |
| 150 | + carries `stiffness` / `damping` / `effort_limit` / `velocity_limit` / `armature` / |
| 151 | + `friction` / `action_scale` per group. |
| 152 | +- `Articulation.write_joint_targets_partial` routes per-step joint targets to each |
| 153 | + actuator group's declared channel (position-target or force). |
| 154 | +- `Articulation.action_scale_tensor` aggregates per-group action scales for inheritance |
| 155 | + by `JointPositionAction` when its `scale` is left `None` (the new default). |
| 156 | +- `docs/concepts/actuators.{en,zh}.md` covers the actuator design and failure modes. |
| 157 | + |
| 158 | +### Changed |
| 159 | + |
| 160 | +- **Breaking**: `ArticulationCfg.joint_kp` / `joint_kv` / `action_scale=dict` are removed; |
| 161 | + configure equivalent groups via `actuators`. The bundled inverted-pendulum and Unitree |
| 162 | + G1 examples migrate accordingly — G1 now ships six `DCMotorActuatorCfg` groups |
| 163 | + (5020 / 7520_14 / 7520_22 / 4010 / waist / ankle). |
| 164 | +- **Breaking**: `Articulation.joint_kp` / `joint_kv` / `action_scale` properties and the |
| 165 | + matching `ManagerBasedRlEnv` delegates are removed. Read actuator parameters through |
| 166 | + `articulation.actuators[name]` instead. |
| 167 | +- **Breaking**: `Articulation.bind` rejects an empty `actuators` dict and any actuator |
| 168 | + configuration that leaves an actuated joint uncovered or covered by more than one |
| 169 | + group. Passive joints need an explicit zero-gain `ImplicitPDActuatorCfg`. |
| 170 | +- `JointPositionActionCfg.scale` defaults to `None`, in which case per-joint scale is |
| 171 | + inherited from `Articulation.action_scale_tensor`. Passing a `float` or `dict` still |
| 172 | + overrides. |
| 173 | + |
| 174 | +### Removed |
| 175 | + |
| 176 | +- `examples/unitree/.../g1/constants.py` no longer exports `ActuatorGroup`, `_fan_out`, |
| 177 | + `G1_JOINT_KP`, `G1_JOINT_KV`, or `G1_ACTION_SCALE` — superseded by `G1_ACTUATORS_CFG`. |
| 178 | + |
| 179 | +## [0.1.0] — 2026-05-14 |
| 180 | + |
| 181 | +- M1 milestone: `InteractiveScene` + `Articulation` / `RigidObject` entities extracted |
| 182 | + from `ManagerBasedRlEnv`; `SimulationCfg` / `InteractiveSceneCfg` split. |
| 183 | +- Sensor abstraction (`Sensor[T]`) with contact, body velocity, ray-cast, and terrain |
| 184 | + height sensors. |
| 185 | +- Mouse-interaction viewer plugin. |
| 186 | +- rsl_rl-based PPO training/replay for the inverted-pendulum and Unitree G1 examples. |
0 commit comments