### Setup and Install ManiSkill2 Source: https://github.com/simpler-env/maniskill2_real2sim/blob/main/CONTRIBUTING.md Create a conda environment, clone the repository, and install ManiSkill2 with development dependencies. ```bash conda create -n "ms2_dev" "python==3.9" git clone https://github.com/haosulab/ManiSkill2.git cd ManiSkill2 pip install -e . # install MS2 locally pip install pytest coverage stable-baselines3 # add development dependencies for testing purposes ``` -------------------------------- ### Initialize ManiSkill2-Real2Sim Environments Source: https://github.com/simpler-env/maniskill2_real2sim/blob/main/README.md Examples of initializing various custom environments with specific configurations, robot agents, and control modes. ```python import mani_skill2_real2sim.envs, gymnasium as gym import numpy as np from transforms3d.euler import euler2quat from sapien.core import Pose env1 = gym.make('GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', prepackaged_config=True) obs1, reset_info_1 = env1.reset() instruction1 = env1.get_language_instruction() image1 = obs1['image']['overhead_camera']['rgb'] obs1_alt, reset_info_1_alt = env1.reset(options={'obj_init_options': {'init_xy': [-0.35, -0.02], 'orientation': 'laid_vertically'}}) instruction1_alt = env1.get_language_instruction() image1_alt = obs1_alt['image']['overhead_camera']['rgb'] env2 = gym.make('MoveNearGoogleBakedTexInScene-v0', obs_mode='rgbd', robot='google_robot_static', sim_freq=513, control_freq=3, control_mode='arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner', max_episode_steps=80, scene_name='google_pick_coke_can_1_v4', camera_cfgs={"add_segmentation": True}, rgb_overlay_path='./data/real_inpainting/google_move_near_real_eval_1.png', rgb_overlay_cameras=['overhead_camera'], urdf_version='recolor_tabletop_visual_matching_1' ) # remove "rgb_overlay_path", "rgb_overlay_cameras", and "urdf_version" if you do not want to overlay the real background obs2, reset_info_2 = env2.reset(options={ 'robot_init_options': { 'init_xy': np.array([0.35, 0.21]), 'init_rot_quat': (Pose(q=euler2quat(0, 0, -0.09)) * Pose(q=[0, 0, 0, 1])).q, }, 'obj_init_options': {'episode_id': 0} }) instruction2 = env2.get_language_instruction() image2 = obs2['image']['overhead_camera']['rgb'] env3 = gym.make('CloseDrawerCustomInScene-v0', obs_mode='rgbd', robot='google_robot_static', sim_freq=513, control_freq=3, max_episode_steps=113, control_mode='arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner', scene_name='modern_office_no_roof', station_name='mk_station2', # cabinet model shader_dir='rt', # enable raytracing, slow for non RTX gpus ) obs3, reset_info_3 = env3.reset(options={ 'robot_init_options': { 'init_xy': np.array([0.75, 0.00]), }, }) instruction3 = env3.get_language_instruction() image3 = obs3['image']['overhead_camera']['rgb'] env4 = gym.make('PutSpoonOnTableClothInScene-v0', obs_mode='rgbd', robot='widowx', sim_freq=500, control_freq=5, control_mode='arm_pd_ee_target_delta_pose_align2_gripper_pd_joint_pos', max_episode_steps=60, scene_name='bridge_table_1_v1', camera_cfgs={"add_segmentation": True}, rgb_overlay_path='./data/real_inpainting/bridge_real_eval_1.png', rgb_overlay_cameras=['3rd_view_camera'], ) # remove "rgb_overlay_path", "rgb_overlay_cameras", and "urdf_version" if you do not want to overlay the real background obs4, reset_info_4 = env4.reset(options={ 'obj_init_options': {'episode_id': 0} }) instruction4 = env4.get_language_instruction() image4 = obs4['image']['3rd_view_camera']['rgb'] ``` -------------------------------- ### Install ManiSkill2-Real2Sim Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Install the package using pip and set the asset directory if needed. ```bash pip install -e . # Set asset directory if needed export MS2_REAL2SIM_ASSET_DIR=/path/to/assets ``` -------------------------------- ### Create Basic Grasp Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Creates a basic grasp environment using default visual matching configurations. The environment supports resetting, getting task instructions, and running a simple episode with random actions. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np # Create environment with prepackaged visual matching configuration env = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', prepackaged_config=True # Uses default visual matching settings ) # Reset environment and get initial observation obs, reset_info = env.reset() # Get the task language instruction instruction = env.get_language_instruction() print(f"Task: {instruction}") # Output: "pick coke can" # Access RGB image from overhead camera rgb_image = obs['image']['overhead_camera']['rgb'] print(f"Image shape: {rgb_image.shape}") # (height, width, 3) # Run a simple episode for step in range(80): action = env.action_space.sample() # Random action for demonstration obs, reward, terminated, truncated, info = env.step(action) if terminated: print(f"Success: {info['success']}") break env.close() ``` -------------------------------- ### Install ManiSkill2-Real2Sim Source: https://github.com/simpler-env/maniskill2_real2sim/blob/main/README.md Command to install the package in editable mode. ```bash pip install -e . ``` -------------------------------- ### Reset Environment with Specific Configuration Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Resets the environment with custom robot and object initial positions. Useful for setting up specific starting states for tasks. ```python obs, info = env.reset(options={ 'robot_init_options': { 'init_xy': np.array([0.35, 0.21]), 'init_rot_quat': (Pose(q=euler2quat(0, 0, -0.09)) * Pose(q=[0, 0, 0, 1])).q, }, 'obj_init_options': {'episode_id': 0} # Selects triplet and object positions }) ``` -------------------------------- ### Initialize Environment with RGBD Observation Mode Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Demonstrates how to initialize a ManiSkill2 environment with RGBD observation mode, including camera configurations for segmentation. Shows how to access and interpret agent, extra, camera parameters, and image observations (Color, Position, Segmentation). ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np # RGBD observation mode env = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', camera_cfgs={"add_segmentation": True}, prepackaged_config=True ) ob s, info = env.reset() # Observation structure for 'image' mode print("Observation keys:", obs.keys()) # dict_keys(['agent', 'extra', 'camera_param', 'image']) # Agent observations (proprioception) print("Agent qpos:", obs['agent']['qpos']) print("Agent qvel:", obs['agent']['qvel']) # Extra task-related observations print("TCP pose:", obs['extra']['tcp_pose']) # Camera parameters for each camera for cam_name, params in obs['camera_param'].items(): print(f"{cam_name} intrinsic:\n{params['intrinsic_cv']}") print(f"{cam_name} extrinsic:\n{params['extrinsic_cv']}") # Image observations per camera for cam_name, images in obs['image'].items(): print(f"\n{cam_name} images:") print(f" Color (RGB): {images['Color'].shape}") # (H, W, 4) RGBA print(f" Position: {images['Position'].shape}") # (H, W, 4) XYZ + depth if 'Segmentation' in images: print(f" Segmentation: {images['Segmentation'].shape}") # (H, W, 4) # Segmentation[..., 0]: mesh-level ID # Segmentation[..., 1]: actor-level ID # Extract RGB and depth rgb = obs['image']['overhead_camera']['Color'][..., :3] # (H, W, 3) depth = obs['image']['overhead_camera']['Position'][..., 2] # (H, W) # State observation mode (flattened vector) env_state = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='state', prepackaged_config=True ) ob s_state, _ = env_state.reset() print(f"State observation shape: {obs_state.shape}") # 1D vector env_state.close() env.close() ``` -------------------------------- ### Create Put Spoon on Table Cloth Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Initializes a 'PutSpoonOnTableClothInScene-v0' environment using the WidowX robot. Configures camera settings to add segmentation data and specifies an RGB overlay for the camera view. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np # Put Spoon on Table Cloth environment env = gym.make( 'PutSpoonOnTableClothInScene-v0', obs_mode='rgbd', robot='widowx', sim_freq=500, control_freq=5, control_mode='arm_pd_ee_target_delta_pose_align2_gripper_pd_joint_pos', max_episode_steps=60, scene_name='bridge_table_1_v1', camera_cfgs={"add_segmentation": True}, rgb_overlay_path='./data/real_inpainting/bridge_real_eval_1.png', rgb_overlay_cameras=['3rd_view_camera'], ) obs, info = env.reset(options={ 'obj_init_options': {'episode_id': 0} }) instruction = env.get_language_instruction() print(f"Task: {instruction}") # Output: "put the spoon on the towel" # Access 3rd person view camera image = obs['image']['3rd_view_camera']['rgb'] print(f"Image shape: {image.shape}") env.close() ``` -------------------------------- ### Create Stack Cubes Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Initializes a 'StackGreenCubeOnYellowCubeInScene-v0' environment using the WidowX robot. This environment is pre-configured for a cube stacking task. ```python # Stack cubes environment stack_env = gym.make( 'StackGreenCubeOnYellowCubeInScene-v0', obs_mode='rgbd', robot='widowx', sim_freq=500, control_freq=5, control_mode='arm_pd_ee_target_delta_pose_align2_gripper_pd_joint_pos', max_episode_steps=60, prepackaged_config=True ) obs, info = stack_env.reset() print(f"Task: {stack_env.get_language_instruction()}") # "stack the green block on the yellow block" stack_env.close() ``` -------------------------------- ### Create and Use Open Drawer Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Creates an 'OpenDrawerCustomInScene-v0' environment with ray-traced rendering enabled. Resets the environment with specific robot positioning and interacts with it to open the drawer. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np # Create Open Drawer environment env = gym.make( 'OpenDrawerCustomInScene-v0', obs_mode='rgbd', robot='google_robot_static', sim_freq=513, control_freq=3, max_episode_steps=113, control_mode='arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner', scene_name='modern_office_no_roof', station_name='mk_station2', # Cabinet model variant shader_dir='rt', # Enable ray tracing (requires RTX GPU) ) # Reset with robot positioning obs, info = env.reset(options={ 'robot_init_options': { 'init_xy': np.array([0.75, 0.00]), } }) instruction = env.get_language_instruction() print(f"Task: {instruction}") # Output: "open drawer" print(f"Drawer: {info['station_name']}") # Check drawer state through evaluation for step in range(113): action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) # Drawer qpos indicates how far it's opened print(f"Step {step}: drawer_qpos={info['qpos']:.3f}, success={info['success']}") if info['success']: # qpos >= 0.15 for open drawer print("Drawer successfully opened!") break env.close() ``` -------------------------------- ### Create and Use Close Drawer Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Creates a 'CloseDrawerCustomInScene-v0' environment, initializing the drawer in an open state. The goal is to close the drawer, with success indicated by the drawer's qpos. ```python # Close Drawer environment (starts with drawer open) close_env = gym.make( 'CloseDrawerCustomInScene-v0', obs_mode='rgbd', robot='google_robot_static', sim_freq=513, control_freq=3, max_episode_steps=113, control_mode='arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner', scene_name='dummy_drawer', station_name='mk_station_recolor', ) obs, info = close_env.reset(options={ 'obj_init_options': {'cabinet_init_qpos': 0.2} # Start with drawer open }) # Success when qpos <= 0.05 close_env.close() ``` -------------------------------- ### Manual Control and Visualization Demo in Python Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Provides a programmatic equivalent to the manual control script, allowing interactive debugging with keyboard controls for robot motion and gripper operations. Uses OpenCVViewer for visualization. ```python # Run from command line: # python mani_skill2_real2sim/examples/demo_manual_control_custom_envs.py \ # -e GraspSingleOpenedCokeCanInScene-v0 \ # -c arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner \ # -o rgbd \ # --enable-sapien-viewer \ # prepackaged_config @True \ # robot google_robot_static # Keyboard controls: # xyz position: i/k (+/-x), j/l (+/-y), u/o (+/-z) # rotation rpy: 1/2 (+/-roll), 3/4 (+/-pitch), 5/6 (+/-yaw) # gripper: f (open), g (close) # reset: r # visualization: v (show camera observations) # sapien viewer: 0 (switch to 3D viewer) # Programmatic equivalent: import mani_skill2_real2sim.envs import gymnasium as gym from mani_skill2_real2sim.utils.visualization.cv2_utils import OpenCVViewer env = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', render_mode='cameras', prepackaged_config=True ) obs, info = env.reset() viewer = OpenCVViewer() # Interactive loop while True: render_frame = env.render() key = viewer.imshow(render_frame) if key is None: # Window closed break # Create action based on key input action = np.zeros(7) if key == 'i': action[0] = 0.02 # Forward if key == 'k': action[0] = -0.02 # Backward if key == 'u': action[2] = 0.02 # Up if key == 'o': action[2] = -0.02 # Down if key == 'g': action[6] = 1.0 # Close gripper if key == 'f': action[6] = -1.0 # Open gripper obs, reward, terminated, truncated, info = env.step(action) print(f"TCP pose: {env.tcp.pose.p}, Reward: {reward}, Success: {info['success']}") env.close() ``` -------------------------------- ### Access Robot Agent Methods in Python Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Demonstrates how to access robot agent methods like get_proprioception, get_gripper_closedness, and check_grasp. Ensure the environment is initialized with a supported robot. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np env = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', prepackaged_config=True ) obs, info = env.reset() # Access the robot agent agent = env.agent # Get proprioceptive information (joint positions, velocities) proprioception = agent.get_proprioception() print(f"Joint positions: {proprioception['qpos']}") print(f"Joint velocities: {proprioception['qvel']}") # Get gripper closedness (0=open, 1=closed) gripper_state = agent.get_gripper_closedness() print(f"Gripper closedness: {gripper_state:.2f}") # Get finger positions and velocities fingers_info = agent.get_fingers_info() print(f"Left finger pos: {fingers_info['finger_left_pos']}") print(f"Right finger pos: {fingers_info['finger_right_pos']}") # Check if object is grasped (after stepping with grasp action) # This checks contact impulse between fingers and object target_object = env.obj # The target object actor is_grasped = agent.check_grasp(target_object, max_angle=80) print(f"Object grasped: {is_grasped}") # Get robot base pose base_pose = agent.robot.pose print(f"Robot base position: {base_pose.p}") print(f"Robot base quaternion: {base_pose.q}") # Get TCP (tool center point) pose tcp_pose = env.tcp.pose print(f"TCP position: {tcp_pose.p}") env.close() ``` -------------------------------- ### Build and Upload ManiSkill2 Package Source: https://github.com/simpler-env/maniskill2_real2sim/blob/main/CONTRIBUTING.md Build the project package and upload it to a repository using the build and twine tools. ```bash python3 -m build -s -w python3 -m twine upload --repository testpypi dist/* ``` -------------------------------- ### Create Put Carrot on Plate Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Initializes a 'PutCarrotOnPlateInScene-v0' environment. This environment is pre-configured for the task of placing a carrot on a plate. ```python # Put Carrot on Plate environment carrot_env = gym.make( 'PutCarrotOnPlateInScene-v0', obs_mode='rgbd', prepackaged_config=True ) obs, info = carrot_env.reset() print(f"Task: {carrot_env.get_language_instruction()}") # "put carrot on plate" carrot_env.close() ``` -------------------------------- ### Create Custom Grasp Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Configures a grasp environment with specific robot, scene, control modes, and visual overlay settings. Supports custom object and robot initialization options. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np from transforms3d.euler import euler2quat from sapien.core import Pose # Create fully configured environment env = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', robot='google_robot_static', sim_freq=513, control_freq=3, control_mode='arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner', max_episode_steps=80, scene_name='google_pick_coke_can_1_v4', camera_cfgs={"add_segmentation": True}, rgb_overlay_path='./data/real_inpainting/google_coke_can_real_eval_1.png', rgb_overlay_cameras=['overhead_camera'], urdf_version='recolor_tabletop_visual_matching_1' ) # Reset with custom object and robot initialization obs, info = env.reset(options={ 'obj_init_options': { 'init_xy': [-0.12, 0.2], 'orientation': 'laid_vertically' # Can be 'upright', 'laid_vertically', 'lr_switch' }, 'robot_init_options': { 'init_xy': [0.35, 0.20], 'init_rot_quat': [0, 0, 0, 1] } }) print(f"Scene name: {info['scene_name']}") print(f"Model ID: {info['model_id']}") print(f"Object init pose: {info['obj_init_pose_wrt_robot_base']}") env.close() ``` -------------------------------- ### Action Space and Control Modes in Python Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Explains the action space for end-effector delta pose control and gripper state. Note the different gripper conventions for Google Robot and WidowX. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np env = gym.make( 'GraspSingleOpenedCokeCanInScene-v0', obs_mode='rgbd', prepackaged_config=True ) obs, info = env.reset() # Get action space info print(f"Action space shape: {env.action_space.shape}") print(f"Action space low: {env.action_space.low}") print(f"Action space high: {env.action_space.high}") # Action structure for Google Robot (7D): # [delta_x, delta_y, delta_z, delta_roll, delta_pitch, delta_yaw, gripper] # Position deltas are in meters, rotation deltas in radians # Gripper: positive=close, negative=open (reversed for Google Robot) # Example: Move end-effector forward and down action = np.zeros(7) action[0] = 0.02 # +x (forward) action[2] = -0.02 # -z (down) action[6] = 1.0 # Close gripper (Google Robot convention) obs, reward, terminated, truncated, info = env.step(action) # For WidowX robot (also 7D but different control mode): # Same structure but gripper convention is opposite (positive=open) # Access controller configuration controller = env.agent.controller print(f"Control mode: {env.control_mode}") # Using action dictionary for multi-controller robots action_dict = { 'arm': np.array([0.02, 0.0, -0.02, 0.0, 0.0, 0.0]), # 6D pose delta 'gripper': 1.0 # Gripper action } action = env.agent.controller.from_action_dict(action_dict) env.close() ``` -------------------------------- ### List Available Grasp Environments Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Provides a Python list of environment IDs for various grasping tasks using the Google Robot configuration. These environments are pre-registered and ready for use with gym.make(). ```python import mani_skill2_real2sim.envs import gymnasium as gym # Google Robot environments (grasp single objects) grasp_envs = [ 'GraspSingleOpenedCokeCanInScene-v0', # Pick up opened coke can 'GraspSingleOpenedPepsiCanInScene-v0', # Pick up opened pepsi can 'GraspSingleOpened7upCanInScene-v0', # Pick up opened 7up can 'GraspSingleOpenedSpriteCanInScene-v0', # Pick up opened sprite can 'GraspSingleOpenedFantaCanInScene-v0', # Pick up opened fanta can 'GraspSingleOpenedRedBullCanInScene-v0', # Pick up opened redbull can 'GraspSingleBluePlasticBottleInScene-v0', # Pick up blue plastic bottle 'GraspSingleAppleInScene-v0', # Pick up apple 'GraspSingleOrangeInScene-v0', # Pick up orange 'GraspSingleSpongeInScene-v0', # Pick up sponge 'GraspSingleRandomObjectInScene-v0', # Random object selection 'GraspSingleCustomInScene-v0', # Custom object specification ] # Move Near environments (Google Robot) move_near_envs = [ 'MoveNearGoogleInScene-v0', 'MoveNearGoogleBakedTexInScene-v0', 'MoveNearGoogleBakedTexInScene-v1', ] # Drawer environments (Google Robot) drawer_envs = [ 'OpenDrawerCustomInScene-v0', 'OpenTopDrawerCustomInScene-v0', 'OpenMiddleDrawerCustomInScene-v0', 'OpenBottomDrawerCustomInScene-v0', 'CloseDrawerCustomInScene-v0', 'CloseTopDrawerCustomInScene-v0', 'CloseMiddleDrawerCustomInScene-v0', 'CloseBottomDrawerCustomInScene-v0', ] # Bridge/WidowX environments bridge_envs = [ 'PutSpoonOnTableClothInScene-v0', 'PutCarrotOnPlateInScene-v0', 'StackGreenCubeOnYellowCubeInScene-v0', 'StackGreenCubeOnYellowCubeBakedTexInScene-v0', 'PutEggplantInBasketScene-v0', ] # Example: List environment info for env_id in grasp_envs[:3]: env = gym.make(env_id, obs_mode='state', prepackaged_config=True) obs, info = env.reset() print(f"{env_id}:") print(f" Instruction: {env.get_language_instruction()}") print(f" Action space: {env.action_space.shape}") print(f" Obs space: {env.observation_space.shape}") env.close() ``` -------------------------------- ### Run Environment Step Loop Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Executes a loop to sample actions and step through the environment, collecting observations and evaluation information. The loop breaks if the episode terminates. ```python # Run evaluation loop for step in range(80): action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) # Check detailed evaluation metrics eval_info = info print(f"Step {step}: moved_correct={eval_info['moved_correct_obj']}, " f"near_target={eval_info['near_tgt_obj']}, " f"success={eval_info['success']}") if terminated: break ``` -------------------------------- ### Create Move Near Environment Source: https://context7.com/simpler-env/maniskill2_real2sim/llms.txt Creates a 'Move Near' environment with visual matching, suitable for tasks requiring an object to be moved near a target while avoiding distractors. Uses baked texture assets for visual realism. ```python import mani_skill2_real2sim.envs import gymnasium as gym import numpy as np from transforms3d.euler import euler2quat from sapien.core import Pose # Create Move Near environment with visual matching env = gym.make( 'MoveNearGoogleBakedTexInScene-v0', obs_mode='rgbd', robot='google_robot_static', sim_freq=513, control_freq=3, control_mode='arm_pd_ee_delta_pose_align_interpolate_by_planner_gripper_pd_joint_target_delta_pos_interpolate_by_planner', max_episode_steps=80, scene_name='google_pick_coke_can_1_v4', camera_cfgs={"add_segmentation": True}, rgb_overlay_path='./data/real_inpainting/google_move_near_real_eval_1.png', rgb_overlay_cameras=['overhead_camera'], urdf_version='recolor_tabletop_visual_matching_1' ) ``` -------------------------------- ### Run and Test ManiSkill2 Source: https://github.com/simpler-env/maniskill2_real2sim/blob/main/CONTRIBUTING.md Execute tests using coverage.py and pytest to ensure code quality and measure test coverage. ```bash coverage run --source=mani_skill2_real2sim/ -a -m pytest tests # run tests coverage html --include=mani_skill2_real2sim/**/*.py # see the test coverage results ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.