Unverified Commit c346ac84 authored by Kelly Guo's avatar Kelly Guo Committed by GitHub

Removes pickle dependency for cfg load and dump (#3709)

# Description

We have been supporting both pickle and yaml storing for configuration.
However, pickle has some security vulnerabilities and we have been
preferring the use of yaml in most cases. Thus, we are removing the
pickle utilities for saving and loading configs.

For more info on pickle: https://docs.python.org/3/library/pickle.html


## Type of change

- Breaking change (existing functionality will not work without user
modification)


## Checklist

- [x] I have read and understood the [contribution
guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html)
- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

---------
Signed-off-by: 's avatarKelly Guo <kellyg@nvidia.com>
Co-authored-by: 's avatarMayank Mittal <12863862+Mayankm96@users.noreply.github.com>
parent 9808b6b8
...@@ -75,7 +75,7 @@ from rl_games.torch_runner import Runner ...@@ -75,7 +75,7 @@ from rl_games.torch_runner import Runner
from isaaclab.envs import DirectMARLEnvCfg, DirectRLEnvCfg, ManagerBasedRLEnvCfg from isaaclab.envs import DirectMARLEnvCfg, DirectRLEnvCfg, ManagerBasedRLEnvCfg
from isaaclab.utils.dict import print_dict from isaaclab.utils.dict import print_dict
from isaaclab.utils.io import dump_pickle, dump_yaml from isaaclab.utils.io import dump_yaml
from isaaclab_rl.rl_games import RlGamesGpuEnv, RlGamesVecEnvWrapper from isaaclab_rl.rl_games import RlGamesGpuEnv, RlGamesVecEnvWrapper
...@@ -168,8 +168,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen ...@@ -168,8 +168,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen
# dump the configuration into log-directory # dump the configuration into log-directory
dump_yaml(os.path.join(log_root_path, log_dir, "params", "env.yaml"), env_cfg) dump_yaml(os.path.join(log_root_path, log_dir, "params", "env.yaml"), env_cfg)
dump_yaml(os.path.join(log_root_path, log_dir, "params", "agent.yaml"), agent_cfg) dump_yaml(os.path.join(log_root_path, log_dir, "params", "agent.yaml"), agent_cfg)
dump_pickle(os.path.join(log_root_path, log_dir, "params", "env.pkl"), env_cfg)
dump_pickle(os.path.join(log_root_path, log_dir, "params", "agent.pkl"), agent_cfg)
# read configurations about the agent-training # read configurations about the agent-training
rl_device = agent_cfg["params"]["config"]["device"] rl_device = agent_cfg["params"]["config"]["device"]
......
...@@ -75,7 +75,7 @@ from rsl_rl.runners import OnPolicyRunner ...@@ -75,7 +75,7 @@ from rsl_rl.runners import OnPolicyRunner
from isaaclab.envs import DirectMARLEnvCfg, DirectRLEnvCfg, ManagerBasedRLEnvCfg from isaaclab.envs import DirectMARLEnvCfg, DirectRLEnvCfg, ManagerBasedRLEnvCfg
from isaaclab.utils.dict import print_dict from isaaclab.utils.dict import print_dict
from isaaclab.utils.io import dump_pickle, dump_yaml from isaaclab.utils.io import dump_yaml
from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlVecEnvWrapper from isaaclab_rl.rsl_rl import RslRlOnPolicyRunnerCfg, RslRlVecEnvWrapper
...@@ -207,8 +207,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen ...@@ -207,8 +207,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen
# dump the configuration into log-directory # dump the configuration into log-directory
dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg) dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg)
dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg) dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg)
dump_pickle(os.path.join(log_dir, "params", "env.pkl"), env_cfg)
dump_pickle(os.path.join(log_dir, "params", "agent.pkl"), agent_cfg)
benchmark.set_phase("sim_runtime") benchmark.set_phase("sim_runtime")
......
...@@ -79,7 +79,7 @@ from isaaclab.envs import ( ...@@ -79,7 +79,7 @@ from isaaclab.envs import (
) )
from isaaclab.utils.assets import retrieve_file_path from isaaclab.utils.assets import retrieve_file_path
from isaaclab.utils.dict import print_dict from isaaclab.utils.dict import print_dict
from isaaclab.utils.io import dump_pickle, dump_yaml from isaaclab.utils.io import dump_yaml
from isaaclab_rl.rl_games import MultiObserver, PbtAlgoObserver, RlGamesGpuEnv, RlGamesVecEnvWrapper from isaaclab_rl.rl_games import MultiObserver, PbtAlgoObserver, RlGamesGpuEnv, RlGamesVecEnvWrapper
...@@ -146,8 +146,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen ...@@ -146,8 +146,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen
# dump the configuration into log-directory # dump the configuration into log-directory
dump_yaml(os.path.join(log_root_path, log_dir, "params", "env.yaml"), env_cfg) dump_yaml(os.path.join(log_root_path, log_dir, "params", "env.yaml"), env_cfg)
dump_yaml(os.path.join(log_root_path, log_dir, "params", "agent.yaml"), agent_cfg) dump_yaml(os.path.join(log_root_path, log_dir, "params", "agent.yaml"), agent_cfg)
dump_pickle(os.path.join(log_root_path, log_dir, "params", "env.pkl"), env_cfg)
dump_pickle(os.path.join(log_root_path, log_dir, "params", "agent.pkl"), agent_cfg)
# read configurations about the agent-training # read configurations about the agent-training
rl_device = agent_cfg["params"]["config"]["device"] rl_device = agent_cfg["params"]["config"]["device"]
......
...@@ -88,7 +88,7 @@ from isaaclab.envs import ( ...@@ -88,7 +88,7 @@ from isaaclab.envs import (
multi_agent_to_single_agent, multi_agent_to_single_agent,
) )
from isaaclab.utils.dict import print_dict from isaaclab.utils.dict import print_dict
from isaaclab.utils.io import dump_pickle, dump_yaml from isaaclab.utils.io import dump_yaml
from isaaclab_rl.rsl_rl import RslRlBaseRunnerCfg, RslRlVecEnvWrapper from isaaclab_rl.rsl_rl import RslRlBaseRunnerCfg, RslRlVecEnvWrapper
...@@ -196,8 +196,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen ...@@ -196,8 +196,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen
# dump the configuration into log-directory # dump the configuration into log-directory
dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg) dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg)
dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg) dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg)
dump_pickle(os.path.join(log_dir, "params", "env.pkl"), env_cfg)
dump_pickle(os.path.join(log_dir, "params", "agent.pkl"), agent_cfg)
# run training # run training
runner.learn(num_learning_iterations=agent_cfg.max_iterations, init_at_random_ep_len=True) runner.learn(num_learning_iterations=agent_cfg.max_iterations, init_at_random_ep_len=True)
......
...@@ -91,7 +91,7 @@ from isaaclab.envs import ( ...@@ -91,7 +91,7 @@ from isaaclab.envs import (
multi_agent_to_single_agent, multi_agent_to_single_agent,
) )
from isaaclab.utils.dict import print_dict from isaaclab.utils.dict import print_dict
from isaaclab.utils.io import dump_pickle, dump_yaml from isaaclab.utils.io import dump_yaml
from isaaclab_rl.sb3 import Sb3VecEnvWrapper, process_sb3_cfg from isaaclab_rl.sb3 import Sb3VecEnvWrapper, process_sb3_cfg
...@@ -130,8 +130,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen ...@@ -130,8 +130,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen
# dump the configuration into log-directory # dump the configuration into log-directory
dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg) dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg)
dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg) dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg)
dump_pickle(os.path.join(log_dir, "params", "env.pkl"), env_cfg)
dump_pickle(os.path.join(log_dir, "params", "agent.pkl"), agent_cfg)
# save command used to run the script # save command used to run the script
command = " ".join(sys.orig_argv) command = " ".join(sys.orig_argv)
......
...@@ -104,7 +104,7 @@ from isaaclab.envs import ( ...@@ -104,7 +104,7 @@ from isaaclab.envs import (
) )
from isaaclab.utils.assets import retrieve_file_path from isaaclab.utils.assets import retrieve_file_path
from isaaclab.utils.dict import print_dict from isaaclab.utils.dict import print_dict
from isaaclab.utils.io import dump_pickle, dump_yaml from isaaclab.utils.io import dump_yaml
from isaaclab_rl.skrl import SkrlVecEnvWrapper from isaaclab_rl.skrl import SkrlVecEnvWrapper
...@@ -168,8 +168,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen ...@@ -168,8 +168,6 @@ def main(env_cfg: ManagerBasedRLEnvCfg | DirectRLEnvCfg | DirectMARLEnvCfg, agen
# dump the configuration into log-directory # dump the configuration into log-directory
dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg) dump_yaml(os.path.join(log_dir, "params", "env.yaml"), env_cfg)
dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg) dump_yaml(os.path.join(log_dir, "params", "agent.yaml"), agent_cfg)
dump_pickle(os.path.join(log_dir, "params", "env.pkl"), env_cfg)
dump_pickle(os.path.join(log_dir, "params", "agent.pkl"), agent_cfg)
# get checkpoint path (to resume training) # get checkpoint path (to resume training)
resume_path = retrieve_file_path(args_cli.checkpoint) if args_cli.checkpoint else None resume_path = retrieve_file_path(args_cli.checkpoint) if args_cli.checkpoint else None
......
[package] [package]
# Note: Semantic Versioning is used: https://semver.org/ # Note: Semantic Versioning is used: https://semver.org/
version = "0.46.5" version = "0.47.0"
# Description # Description
title = "Isaac Lab framework for Robot Learning" title = "Isaac Lab framework for Robot Learning"
......
Changelog Changelog
--------- ---------
0.47.0 (2025-10-14)
~~~~~~~~~~~~~~~~~~~
Changed
^^^^^^^
* Removed pickle utilities for saving and loading configurations as pickle contains security vulnerabilities in its APIs.
Configurations can continue to be saved and loaded through yaml.
0.46.5 (2025-10-14) 0.46.5 (2025-10-14)
~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~
Added
^^^^^
* Exposed parameter :attr:`~isaaclab.sim.spawners.PhysxCfg.solve_articulation_contact_last` * Exposed parameter :attr:`~isaaclab.sim.spawners.PhysxCfg.solve_articulation_contact_last`
to configure USD attribute ``physxscene:solveArticulationContactLast``. This parameter may to configure USD attribute ``physxscene:solveArticulationContactLast``. This parameter may
help improve solver stability with grippers, which previously required reducing simulation time-steps. help improve solver stability with grippers, which previously required reducing simulation time-steps.
......
...@@ -7,5 +7,4 @@ ...@@ -7,5 +7,4 @@
Submodules for files IO operations. Submodules for files IO operations.
""" """
from .pkl import dump_pickle, load_pickle
from .yaml import dump_yaml, load_yaml from .yaml import dump_yaml, load_yaml
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Utilities for file I/O with pickle."""
import os
import pickle
from typing import Any
def load_pickle(filename: str) -> Any:
"""Loads an input PKL file safely.
Args:
filename: The path to pickled file.
Raises:
FileNotFoundError: When the specified file does not exist.
Returns:
The data read from the input file.
"""
if not os.path.exists(filename):
raise FileNotFoundError(f"File not found: {filename}")
with open(filename, "rb") as f:
data = pickle.load(f)
return data
def dump_pickle(filename: str, data: Any):
"""Saves data into a pickle file safely.
Note:
The function creates any missing directory along the file's path.
Args:
filename: The path to save the file at.
data: The data to save.
"""
# check ending
if not filename.endswith("pkl"):
filename += ".pkl"
# create directory
if not os.path.exists(os.path.dirname(filename)):
os.makedirs(os.path.dirname(filename), exist_ok=True)
# save data
with open(filename, "wb") as f:
pickle.dump(data, f)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment