def post_physics_step(self):
        """ check terminations, compute observations and rewards
            calls self._post_physics_step_callback() for common computations 
            calls self._draw_debug_vis() if needed
        """
        self.last_contact_forces[:] = self.contact_forces[:]

        self.gym.refresh_actor_root_state_tensor(self.sim)
        self.gym.refresh_net_contact_force_tensor(self.sim)
        self.gym.refresh_rigid_body_state_tensor(self.sim)
        if self.record_now:
            self.gym.step_graphics(self.sim)
            self.gym.render_all_camera_sensors(self.sim)

        if self.cfg.ball.limit_movement:
            # Limit ball to only roll and move along x axis
            self.root_states[self.object_actor_idxs, 8] = 0.0
            self.root_states[self.object_actor_idxs, 9] = 0.0
            self.root_states[self.object_actor_idxs, 10] = 0.0
            self.root_states[self.object_actor_idxs, 12] = 0.0
            self.gym.set_actor_root_state_tensor(self.sim, gymtorch.unwrap_tensor(self.root_states))
            self.gym.refresh_actor_root_state_tensor(self.sim)

        self.episode_length_buf += 1
        self.common_step_counter += 1
        
        # prepare quantities
        self.base_pos[:] = self.root_states[self.robot_actor_idxs, 0:3]
        self.base_quat[:] = self.root_states[self.robot_actor_idxs, 3:7]
        self.base_lin_vel[:] = quat_rotate_inverse(self.base_quat, self.root_states[self.robot_actor_idxs, 7:10])
        self.base_ang_vel[:] = quat_rotate_inverse(self.base_quat, self.root_states[self.robot_actor_idxs, 10:13])
        self.projected_gravity[:] = quat_rotate_inverse(self.base_quat, self.gravity_vec)

        self.foot_velocities = self.rigid_body_state.view(self.num_envs, self.num_bodies, 13
                                                          )[:, self.feet_indices, 7:10]
        self.foot_positions = self.rigid_body_state.view(self.num_envs, self.num_bodies, 13)[:, self.feet_indices,
                              0:3]
        
        # self.randomize_ball_state()

        self.object_pos_world_frame[:] = self.root_states[self.object_actor_idxs, 0:3] 
        robot_object_vec = self.asset.get_local_pos()
        true_object_local_pos = quat_rotate_inverse(self.base_quat, robot_object_vec)
        true_object_local_pos[:, 2] = 0.0*torch.ones(self.num_envs, dtype=torch.float,
                                    device=self.device, requires_grad=False)

        # simulate observation delay
        self.object_local_pos = self.simulate_ball_pos_delay(true_object_local_pos, self.object_local_pos)
        self.object_lin_vel = self.asset.get_lin_vel()
        self.object_ang_vel = self.asset.get_ang_vel()

        self._post_physics_step_callback()

        # compute observations, rewards, resets, ...
        self.check_termination()
        self.compute_reward()
        env_ids = self.reset_buf.nonzero(as_tuple=False).flatten()
        self.reset_idx(env_ids)
        self.compute_observations()

        self.last_last_actions[:] = self.last_actions[:]
        self.last_actions[:, :] = self.actions[:, :self.num_actuated_dof]
        self.last_last_joint_pos_target[:] = self.last_joint_pos_target[:]
        self.last_joint_pos_target[:] = self.joint_pos_target[:]
        self.last_dof_vel[:] = self.dof_vel[:]
        self.last_root_vel[:] = self.root_states[self.robot_actor_idxs, 7:13]

        self._render_headless()
 check terminations, compute observations and rewards
            calls self._post_physics_step_callback() for common computations 
            calls self._draw_debug_vis() if needed
        
globe_walking/go1_gym/envs/base/legged_robot.py