-
Hello, I would like to do reinforcement learning in scene with particles in Isaac Lab. QuestionI would like to know how to reset the particles for reinforcement learning in Isaac Lab. Describe the issueI'm done making particle in scene. (Created with in Isaac Sim, using the way Usd files are imported) I wanted to designate it as cfg, but I didn't have a suitable cfg like ArticulationCfg, so I added it to scene as AssetBaseCfg. However, there was a problem with reset in this case. I think if you look at the Isaac Lab code, it's not cfg format where reset exists as a function like rigid, deformable, and articulation, so I think it's like this, but I'm not sure. The code below is the code that added usd file to the existing humanoid learning code for testing. # Copyright (c) 2022-2024, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
import omni.isaac.lab.sim as sim_utils
from omni.isaac.lab.actuators import ImplicitActuatorCfg
from omni.isaac.lab.assets import ArticulationCfg, AssetBaseCfg
from omni.isaac.lab.envs import ManagerBasedRLEnvCfg
from omni.isaac.lab.managers import EventTermCfg as EventTerm
from omni.isaac.lab.managers import ObservationGroupCfg as ObsGroup
from omni.isaac.lab.managers import ObservationTermCfg as ObsTerm
from omni.isaac.lab.managers import RewardTermCfg as RewTerm
from omni.isaac.lab.managers import SceneEntityCfg
from omni.isaac.lab.managers import TerminationTermCfg as DoneTerm
from omni.isaac.lab.scene import InteractiveSceneCfg
from omni.isaac.lab.terrains import TerrainImporterCfg
from omni.isaac.lab.utils import configclass
from omni.isaac.lab.utils.assets import ISAAC_NUCLEUS_DIR
import omni.isaac.lab_tasks.manager_based.classic.humanoid.mdp as mdp
##
# Scene definition
##
@configclass
class MySceneCfg(InteractiveSceneCfg):
"""Configuration for the terrain scene with a humanoid robot."""
# terrain
terrain = TerrainImporterCfg(
prim_path="/World/ground",
terrain_type="plane",
collision_group=-1,
physics_material=sim_utils.RigidBodyMaterialCfg(static_friction=1.0, dynamic_friction=1.0, restitution=0.0),
debug_vis=False,
)
# robot
robot = ArticulationCfg(
prim_path="{ENV_REGEX_NS}/Robot",
spawn=sim_utils.UsdFileCfg(
usd_path=f"{ISAAC_NUCLEUS_DIR}/Robots/Humanoid/humanoid_instanceable.usd",
rigid_props=sim_utils.RigidBodyPropertiesCfg(
disable_gravity=None,
max_depenetration_velocity=10.0,
enable_gyroscopic_forces=True,
),
articulation_props=sim_utils.ArticulationRootPropertiesCfg(
enabled_self_collisions=True,
solver_position_iteration_count=4,
solver_velocity_iteration_count=0,
sleep_threshold=0.005,
stabilization_threshold=0.001,
),
copy_from_source=False,
),
init_state=ArticulationCfg.InitialStateCfg(
pos=(0.0, 0.0, 1.34),
joint_pos={".*": 0.0},
),
actuators={
"body": ImplicitActuatorCfg(
joint_names_expr=[".*"],
stiffness={
".*_waist.*": 20.0,
".*_upper_arm.*": 10.0,
"pelvis": 10.0,
".*_lower_arm": 2.0,
".*_thigh:0": 10.0,
".*_thigh:1": 20.0,
".*_thigh:2": 10.0,
".*_shin": 5.0,
".*_foot.*": 2.0,
},
damping={
".*_waist.*": 5.0,
".*_upper_arm.*": 5.0,
"pelvis": 5.0,
".*_lower_arm": 1.0,
".*_thigh:0": 5.0,
".*_thigh:1": 5.0,
".*_thigh:2": 5.0,
".*_shin": 0.1,
".*_foot.*": 1.0,
},
),
},
)
# lights
light = AssetBaseCfg(
prim_path="/World/light",
spawn=sim_utils.DistantLightCfg(color=(0.75, 0.75, 0.75), intensity=3000.0),
)
# # pool
# cfg = sim_utils.UsdFileCfg(usd_path=f"omniverse://localhost/Projects/particles.usd")
# cfg.func("/Xform/pool", cfg, translation=(0.0, 0.0, 1.05))
particle = AssetBaseCfg(
prim_path="/World/particles",
spawn=sim_utils.UsdFileCfg(usd_path=f"omniverse://localhost/Projects/particles.usd"),
)
# set to Cfg
##
# MDP settings
##
@configclass
class CommandsCfg:
"""Command terms for the MDP."""
# no commands for this MDP
null = mdp.NullCommandCfg()
@configclass
class ActionsCfg:
"""Action specifications for the MDP."""
joint_effort = mdp.JointEffortActionCfg(
asset_name="robot",
joint_names=[".*"],
scale={
".*_waist.*": 67.5,
".*_upper_arm.*": 67.5,
"pelvis": 67.5,
".*_lower_arm": 45.0,
".*_thigh:0": 45.0,
".*_thigh:1": 135.0,
".*_thigh:2": 45.0,
".*_shin": 90.0,
".*_foot.*": 22.5,
},
)
@configclass
class ObservationsCfg:
"""Observation specifications for the MDP."""
@configclass
class PolicyCfg(ObsGroup):
"""Observations for the policy."""
base_height = ObsTerm(func=mdp.base_pos_z)
base_lin_vel = ObsTerm(func=mdp.base_lin_vel)
base_ang_vel = ObsTerm(func=mdp.base_ang_vel, scale=0.25)
base_yaw_roll = ObsTerm(func=mdp.base_yaw_roll)
base_angle_to_target = ObsTerm(func=mdp.base_angle_to_target, params={"target_pos": (1000.0, 0.0, 0.0)})
base_up_proj = ObsTerm(func=mdp.base_up_proj)
base_heading_proj = ObsTerm(func=mdp.base_heading_proj, params={"target_pos": (1000.0, 0.0, 0.0)})
joint_pos_norm = ObsTerm(func=mdp.joint_pos_limit_normalized)
joint_vel_rel = ObsTerm(func=mdp.joint_vel_rel, scale=0.1)
feet_body_forces = ObsTerm(
func=mdp.body_incoming_wrench,
scale=0.01,
params={"asset_cfg": SceneEntityCfg("robot", body_names=["left_foot", "right_foot"])},
)
actions = ObsTerm(func=mdp.last_action)
def __post_init__(self):
self.enable_corruption = False
self.concatenate_terms = True
# observation groups
policy: PolicyCfg = PolicyCfg()
@configclass
class EventCfg:
"""Configuration for events."""
reset_base = EventTerm(
func=mdp.reset_root_state_uniform,
mode="reset",
params={"pose_range": {}, "velocity_range": {}},
)
reset_robot_joints = EventTerm(
func=mdp.reset_joints_by_offset,
mode="reset",
params={
"position_range": (-0.2, 0.2),
"velocity_range": (-0.1, 0.1),
},
)
@configclass
class RewardsCfg:
"""Reward terms for the MDP."""
# (1) Reward for moving forward
progress = RewTerm(func=mdp.progress_reward, weight=1.0, params={"target_pos": (1000.0, 0.0, 0.0)})
# (2) Stay alive bonus
alive = RewTerm(func=mdp.is_alive, weight=2.0)
# (3) Reward for non-upright posture
upright = RewTerm(func=mdp.upright_posture_bonus, weight=0.1, params={"threshold": 0.93})
# (4) Reward for moving in the right direction
move_to_target = RewTerm(
func=mdp.move_to_target_bonus, weight=0.5, params={"threshold": 0.8, "target_pos": (1000.0, 0.0, 0.0)}
)
# (5) Penalty for large action commands
action_l2 = RewTerm(func=mdp.action_l2, weight=-0.01)
# (6) Penalty for energy consumption
energy = RewTerm(
func=mdp.power_consumption,
weight=-0.005,
params={
"gear_ratio": {
".*_waist.*": 67.5,
".*_upper_arm.*": 67.5,
"pelvis": 67.5,
".*_lower_arm": 45.0,
".*_thigh:0": 45.0,
".*_thigh:1": 135.0,
".*_thigh:2": 45.0,
".*_shin": 90.0,
".*_foot.*": 22.5,
}
},
)
# (7) Penalty for reaching close to joint limits
joint_limits = RewTerm(
func=mdp.joint_limits_penalty_ratio,
weight=-0.25,
params={
"threshold": 0.98,
"gear_ratio": {
".*_waist.*": 67.5,
".*_upper_arm.*": 67.5,
"pelvis": 67.5,
".*_lower_arm": 45.0,
".*_thigh:0": 45.0,
".*_thigh:1": 135.0,
".*_thigh:2": 45.0,
".*_shin": 90.0,
".*_foot.*": 22.5,
},
},
)
@configclass
class TerminationsCfg:
"""Termination terms for the MDP."""
# (1) Terminate if the episode length is exceeded
time_out = DoneTerm(func=mdp.time_out, time_out=True)
# (2) Terminate if the robot falls
torso_height = DoneTerm(func=mdp.root_height_below_minimum, params={"minimum_height": 0.8})
@configclass
class CurriculumCfg:
"""Curriculum terms for the MDP."""
pass
@configclass
class HumanoidEnvCfg(ManagerBasedRLEnvCfg):
"""Configuration for the MuJoCo-style Humanoid walking environment."""
# Scene settings
scene: MySceneCfg = MySceneCfg(num_envs=4, env_spacing=5.0)
# Basic settings
observations: ObservationsCfg = ObservationsCfg()
actions: ActionsCfg = ActionsCfg()
commands: CommandsCfg = CommandsCfg()
# MDP settings
rewards: RewardsCfg = RewardsCfg()
terminations: TerminationsCfg = TerminationsCfg()
events: EventCfg = EventCfg()
curriculum: CurriculumCfg = CurriculumCfg()
def __post_init__(self):
"""Post initialization."""
# general settings
self.decimation = 2
self.episode_length_s = 16.0
# simulation settings
self.sim.dt = 1 / 120.0
self.sim.render_interval = self.decimation
self.sim.physx.bounce_threshold_velocity = 0.2
# default friction material
self.sim.physics_material.static_friction = 1.0
self.sim.physics_material.dynamic_friction = 1.0
self.sim.physics_material.restitution = 0.0 If you know how to reset the particles while learning, please share them. Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
I believe that the particle and liquid workflows are CPU only, and are not currently supported by the asset base class, so you may have a little trouble setting this up as MangerBasedRLEnv without any modifications. However, there are existing workarounds. For more info see: |
Beta Was this translation helpful? Give feedback.
-
Hi @NAMHAUK, I found a way to reset the particles on my script, which however works on the Direct RL workflow. I saw you are using the Manager based one, I don't know if it does apply there too. If you do not find a way to make it work I suggest you look up the Direct workflow which I found much simpler for custom assets such as liquids, but that's your choice. Regarding the reset, I used the two following functions to get the particles' position: from pxr import UsdGeom, Gf
def get_particles_position(self)->tuple[Gf.Vec3f, Gf.Vec3f]:
# Gets particles' positions and velocities
particles = UsdGeom.Points(self.stage.GetPrimAtPath(self.default_prim_path.AppendPath("envs/env_0/particles")))
particles_pos = particles.GetPointsAttr().Get()
particles_vel = particles.GetVelocitiesAttr().Get()
return particles_pos, particles_vel And then to set the position: def set_particles_position(self, particles_pos:Gf.Vec3f, particles_vel:Gf.Vec3f, env_id:int):
# Sets the particles' position and velocities to the given arrays
particles = UsdGeom.Points(self.stage.GetPrimAtPath(self.default_prim_path.AppendPath("envs/env_%d/particles" % env_id)))
particles_pos = particles.GetPointsAttr().Set(particles_pos)
particles_vel = particles.GetVelocitiesAttr().Set(particles_vel) In which env_id is the environment number. As I said, this was written to run in the Direct workflow, the idea being that inside the _setup_scene(self) function the first function needs to be called to obtain the initial positions of the particles, and then inside the _reset_idx(self, env_ids) the second one is called. The function that is actually performing the reset is the second one, while thee first is only used to obtain the initial positions once the fluid is spawned. I did this because it was simple but if you have another way to get the positions you want to impose to the particles you can just use the second function directly. Hope this helps Edit: I forgot that you need to define the default prim path before, somewhere in the script or inside the functions. A way to do it is: from omni.isaac.core.utils.stage import get_current_stage
self.stage = get_current_stage()
self.default_prim = UsdGeom.Xform.Define(self.stage, Sdf.Path("/World")).GetPrim()
self.stage.SetDefaultPrim(self.default_prim)
self.default_prim_path = self.stage.GetDefaultPrim().GetPath() |
Beta Was this translation helpful? Give feedback.
Hi @NAMHAUK,
I found a way to reset the particles on my script, which however works on the Direct RL workflow. I saw you are using the Manager based one, I don't know if it does apply there too. If you do not find a way to make it work I suggest you look up the Direct workflow which I found much simpler for custom assets such as liquids, but that's your choice.
Regarding the reset, I used the two following functions to get the particles' position: