44
55import torch
66
7+ from genelab .utils .math import quat_from_euler_xyz , quat_mul
8+
79if TYPE_CHECKING :
810 from genelab .envs .manager_based_rl_env import ManagerBasedRlEnv
911
@@ -14,7 +16,13 @@ def reset_root_state_uniform(
1416 pose_range : dict [str , tuple [float , float ]] | None = None ,
1517 velocity_range : dict [str , tuple [float , float ]] | None = None ,
1618) -> None :
17- """Randomize the floating base pose / velocity within the given ranges."""
19+ """Randomize the floating base pose / velocity within the given ranges.
20+
21+ ``pose_range`` accepts ``x``, ``y``, ``z`` (position offsets, m) and ``roll``, ``pitch``,
22+ ``yaw`` (rotation offsets, rad, layered on top of the configured ``init_quat``).
23+ ``velocity_range`` accepts ``x``, ``y``, ``z`` (linear, m/s) and ``roll``, ``pitch``,
24+ ``yaw`` (angular, rad/s).
25+ """
1826 if env_ids is None or env_ids .numel () == 0 :
1927 return
2028 pose_range = pose_range or {}
@@ -31,12 +39,34 @@ def reset_root_state_uniform(
3139 set_pos (init_pos , envs_idx = env_ids )
3240 except TypeError :
3341 set_pos (init_pos )
42+ if any (axis in pose_range for axis in ("roll" , "pitch" , "yaw" )):
43+ base_quat = torch .tensor (env .cfg .robot .init_quat , device = env .device ).expand (n , - 1 ).clone ()
44+ zeros = torch .zeros (n , device = env .device )
45+ rpy = []
46+ for axis in ("roll" , "pitch" , "yaw" ):
47+ if axis in pose_range :
48+ lo , hi = pose_range [axis ]
49+ rpy .append (torch .empty (n , device = env .device ).uniform_ (lo , hi ))
50+ else :
51+ rpy .append (zeros )
52+ rand_quat = quat_from_euler_xyz (rpy [0 ], rpy [1 ], rpy [2 ])
53+ new_quat = quat_mul (base_quat , rand_quat )
54+ set_quat = getattr (env .robot , "set_quat" , None )
55+ if set_quat is not None :
56+ try :
57+ set_quat (new_quat , envs_idx = env_ids )
58+ except TypeError :
59+ set_quat (new_quat )
3460 vel = torch .zeros (n , 3 , device = env .device )
3561 ang = torch .zeros (n , 3 , device = env .device )
3662 for axis , idx in (("x" , 0 ), ("y" , 1 ), ("z" , 2 )):
3763 if axis in velocity_range :
3864 lo , hi = velocity_range [axis ]
3965 vel [:, idx ] = torch .empty (n , device = env .device ).uniform_ (lo , hi )
66+ for axis , idx in (("roll" , 0 ), ("pitch" , 1 ), ("yaw" , 2 )):
67+ if axis in velocity_range :
68+ lo , hi = velocity_range [axis ]
69+ ang [:, idx ] = torch .empty (n , device = env .device ).uniform_ (lo , hi )
4070 set_vel = getattr (env .robot , "set_vel" , None )
4171 set_ang = getattr (env .robot , "set_ang" , None )
4272 if set_vel is not None :
@@ -86,18 +116,30 @@ def push_by_setting_velocity(
86116 env_ids : torch .Tensor | None ,
87117 velocity_range : dict [str , tuple [float , float ]] | None = None ,
88118) -> None :
119+ """Push selected envs by overwriting linear (x/y/z) and angular (roll/pitch/yaw) base velocity."""
89120 if env_ids is None or env_ids .numel () == 0 :
90121 return
91122 velocity_range = velocity_range or {}
92123 n = int (env_ids .numel ())
93124 vel = torch .zeros (n , 3 , device = env .device )
125+ ang = torch .zeros (n , 3 , device = env .device )
94126 for axis , idx in (("x" , 0 ), ("y" , 1 ), ("z" , 2 )):
95127 if axis in velocity_range :
96128 lo , hi = velocity_range [axis ]
97129 vel [:, idx ] = torch .empty (n , device = env .device ).uniform_ (lo , hi )
130+ for axis , idx in (("roll" , 0 ), ("pitch" , 1 ), ("yaw" , 2 )):
131+ if axis in velocity_range :
132+ lo , hi = velocity_range [axis ]
133+ ang [:, idx ] = torch .empty (n , device = env .device ).uniform_ (lo , hi )
98134 set_vel = getattr (env .robot , "set_vel" , None )
135+ set_ang = getattr (env .robot , "set_ang" , None )
99136 if set_vel is not None :
100137 try :
101138 set_vel (vel , envs_idx = env_ids )
102139 except TypeError :
103140 set_vel (vel )
141+ if set_ang is not None :
142+ try :
143+ set_ang (ang , envs_idx = env_ids )
144+ except TypeError :
145+ set_ang (ang )
0 commit comments