def reset_idx(self, env_ids):
        """ Reset some environments.
            Calls self._reset_dofs(env_ids), self._reset_root_states(env_ids), and self._resample_commands(env_ids)
            [Optional] calls self._update_terrain_curriculum(env_ids), self.update_command_curriculum(env_ids) and
            Logs episode info
            Resets some buffers

        Args:
            env_ids (list[int]): List of environment ids which must be reset
        """

        if len(env_ids) == 0:
            return
        # update curriculum

        self._call_train_eval(self._update_terrain_curriculum, env_ids)
        self._call_train_eval(self.update_command_curriculum, env_ids)

        # reset robot states
        if self.cfg.commands.command_curriculum:
            self._resample_commands(env_ids)
        self._call_train_eval(self._randomize_dof_props, env_ids)

        # Randomizing rigid body props seems to have a huge detrimental effect on training
        # self._call_train_eval(self._randomize_rigid_body_props, env_ids)
        for env_id in env_ids:
            props = self.gym.get_actor_dof_properties(self.envs[env_id], 0)
            props = self._process_dof_props(props, env_id)
            self.gym.set_actor_dof_properties(self.envs[env_id], 0, props)
        #     props = self.gym.get_actor_rigid_shape_properties(self.envs[env_id], 0)
        #     props = self._process_rigid_shape_props(props, env_id)
        #     self.gym.set_actor_rigid_shape_properties(self.envs[env_id], 0, props)
        #     # NOTE: seems like isaacgym has a bug with setting rolling_friction and torsion_friction
        
        self._call_train_eval(self._reset_dofs, env_ids)
        self._call_train_eval(self._reset_root_states, env_ids)

        self.extras["train/episode"] = {}
        self.extras["train/episode"]["episode_length"] = torch.mean(self.episode_length_buf[env_ids].float())

        # reset buffersew
        self.last_actions[env_ids] = 0.
        self.last_dof_vel[env_ids] = 0.
        self.feet_air_time[env_ids] = 0.
        self.episode_length_buf[env_ids] = 0
        self.reset_buf[env_ids] = 1
        # fill extras
        train_env_ids = env_ids[env_ids < self.num_train_envs]
        if len(train_env_ids) > 0:
            # self.extras["train/episode"] = {}
            for key in self.episode_sums.keys():
                self.extras["train/episode"]['rew_' + key] = torch.mean(
                    self.episode_sums[key][train_env_ids])  # / self.cfg.env.episode_length_s
                self.episode_sums[key][train_env_ids] = 0.
        eval_env_ids = env_ids[env_ids >= self.num_train_envs]
        if len(eval_env_ids) > 0:
            self.extras["eval/episode"] = {}
            for key in self.episode_sums.keys():
                # save the evaluation rollout result if not already saved
                unset_eval_envs = eval_env_ids[self.episode_sums_eval[key][eval_env_ids] == -1]
                self.episode_sums_eval[key][unset_eval_envs] = self.episode_sums[key][unset_eval_envs]
                self.episode_sums[key][eval_env_ids] = 0.

        self.extras["train/episode"]["base_lin_vel"] = torch.mean(torch.norm(self.base_lin_vel, dim=1))
        self.extras["train/episode"]["base_ang_vel"] = torch.mean(torch.norm(self.base_ang_vel, dim=1))
        self.extras["train/episode"]["forward_base_lin_vel"] = torch.mean(self.base_lin_vel[:, 0])
        self.extras["train/episode"]["forward_global_base_lin_vel"] = torch.mean(self.root_states[:, 7])
        if self.cfg.env.observe_command:
            self.extras["train/episode"]["max_command_lin_vel_x"] = torch.max(self.commands[:, 0])
            self.extras["train/episode"]["min_command_lin_vel_x"] = torch.min(self.commands[:, 0])
            self.extras["train/episode"]["max_command_lin_vel_y"] = torch.max(self.commands[:, 1])
            self.extras["train/episode"]["min_command_lin_vel_y"] = torch.min(self.commands[:, 1])
            self.extras["train/episode"]["max_command_ang_vel_yaw"] = torch.max(self.commands[:, 2])
            self.extras["train/episode"]["min_command_ang_vel_yaw"] = torch.min(self.commands[:, 2])

        # log additional curriculum info
        if self.cfg.terrain.curriculum:
            self.extras["train/episode"]["terrain_level"] = torch.mean(
                self.terrain_levels[:self.num_train_envs].float())
        self.extras["env_bins"] = torch.Tensor(self.env_command_bins)[:self.num_train_envs]
        if self.cfg.commands.command_curriculum:
            self.extras["train/episode"]["command_area"] = np.sum(self.curriculum.weights) / self.curriculum.weights.shape[0]
        if self.cfg.commands.yaw_command_curriculum:
            self.extras["train/episode"]["max_command_yaw"] = self.cfg.command_ranges["ang_vel_yaw"][1]
            if self.eval_cfg is not None:
                self.extras["eval/episode"]["max_command_yaw"] = self.eval_cfg.command_ranges["ang_vel_yaw"][1]
        # send timeout info to the algorithm
        if self.cfg.env.send_timeouts:
            self.extras["time_outs"] = self.time_out_buf[:self.num_train_envs]
 Reset some environments.
            Calls self._reset_dofs(env_ids), self._reset_root_states(env_ids), and self._resample_commands(env_ids)
            [Optional] calls self._update_terrain_curriculum(env_ids), self.update_command_curriculum(env_ids) and
            Logs episode info
            Resets some buffers

        Args:
            env_ids (list[int]): List of environment ids which must be reset
        
forward_locomotion/go1_gym/envs/base/legged_robot.py