diff --git a/.gitattributes b/.gitattributes index 6403e157687037f322c2965f96989441551dc9a1..b7ecafc94f7edbf68db2547d5e6d061601e95ecb 100644 --- a/.gitattributes +++ b/.gitattributes @@ -791,3 +791,367 @@ GR00T-WholeBodyControl/decoupled_wbc/dexmg/gr00trobocasa/robocasa/models/assets/ GR00T-WholeBodyControl/decoupled_wbc/dexmg/gr00trobocasa/robocasa/models/assets/robots/unitree_g1/meshes/logo_link.STL filter=lfs diff=lfs merge=lfs -text GR00T-WholeBodyControl/decoupled_wbc/dexmg/gr00trobocasa/robocasa/models/assets/robots/unitree_g1/meshes/right_shoulder_yaw_link.STL filter=lfs diff=lfs merge=lfs -text GR00T-WholeBodyControl/decoupled_wbc/dexmg/gr00trobocasa/robocasa/models/assets/robots/unitree_g1/meshes/waist_yaw_link_rev_1_0.STL filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/videos/mixed_pickup_lamp_01_pickup_success.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/yellow_linen_wall_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/smooth_light_gray_plaster.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/brown_ceramic_tile.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/martin_novak_wood_table.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_floor.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/white_marble_floor.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/new_light_gray_plaster.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_storage_box/ceramic.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/black_book_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack_stand/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/metal_diff.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/rubber_black.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light-wood.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light_yellow_metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/ceramic.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/red_coffee_mug_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/white_yellow_mug_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/porcelain_mug_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/white_linen_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wooden_tray/crate_mat_BaseColor.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/cork_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/label_wine.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/button_dark_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/base/visual/base_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/basin_faucet_base/visual/basin_faucet_base_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/base/dark-wood.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_low/visual/drawer_low_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_middle/visual/drawer_middle_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_high/visual/drawer_high_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/Cork_Texture_by_faycop.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/desk_caddy_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/visual/desk_caddy_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/visual/wine_bottle_red_main_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/visual/dining_set_utensils_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/visual/porcelain_mug_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/visual/white_yellow_mug_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/visual/red_coffee_mug_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/visual/bowl_drainer_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/visual/moka_pot_body_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/yellow_book/visual/yellow_book_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/visual/black_book_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/ceramic.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/white_wood.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/button_dark_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/steel-scratched.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_top_handle/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_middle_handle/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_base/steel-scratched.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/steel-scratched.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/visual/model_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basin_faucet_base/visual/basin_faucet_base_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/simple_rack/visual/simple_rack_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/visual/glazed_rim_porcelain_ramekin_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/visual/akita_black_bowl_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/visual/model_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/visual/model_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/visual/chefmate_8_frypan_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/visual/basket_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/texture_map.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/visual/bbq_sauce_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/visual/popcorn_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/visual/butter_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/visual/cream_cheese_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/visual/cookies_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/visual/textured_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/short_coffee_table/Marble062_COL_4K.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/FabricLeatherBuffaloRustic001_COL_VAR1_4K.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/desk_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/black_book_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/study_background.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/kitchen_background.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/plant_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/metal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/steel-scratched.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/living_room_table_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_wall_painting/study_wall_painting.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/office_book_shelf/ceramic.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_hot_pot/visual/kitchen_background_hot_pot_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/collision/living_room_table_ch.stl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/visual/living_room_table_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/visual/fridge_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/collision/kitchen_background_pot_ch.stl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/visual/plant_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_stove/visual/kitchen_background_stove_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/visual/kitchen_background_pot_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/visual/study_background_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/visual/kitchen_background_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/collision/floor_lamp_ch.stl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/visual/floor_lamp_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/visual/black_book_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room/visual/living_room_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/visual/desk_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/collision/coffee_table_seats_ch.stl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/visual/coffee_table_seats_vis.msh filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.pdf filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/robocasa/docs/images/styles.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/robocasa/docs/images/layouts.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/robocasa/docs/images/robocasa-banner.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000002.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000004.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000003.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000001.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000002.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000004.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000001.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000003.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000002.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000001.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.wrist/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.front/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000001.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000002.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000000.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000001.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000002.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/scripts/deployment/spark/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/scripts/deployment/dgpu/wheels/torchcodec-0.8.0-cp312-cp312-linux_aarch64.whl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/scripts/deployment/orin/wheels/torchcodec-0.10.0a0-cp310-cp310-linux_aarch64.whl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/scripts/deployment/thor/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/scripts/deployment/spark/wheels/flash_attn-2.8.3-cp312-cp312-linux_aarch64.whl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/fSpy_calibration_example.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/teaser.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c0.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a0.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_sink.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b0.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/google_move_near_real_eval_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2.mp4 filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/frl_apartment_stage_simple.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet2_h870.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background_2.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_no_roof.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v2.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/minimalistic_modern_bedroom.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet1_h870.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj73_table.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj11_table.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_bedroom_no_roof.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office_no_roof.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/73_table_brighter.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup_no_coke_can.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup_no_coke_can.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/another_counter_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup_no_coke_can.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup_no_coke_can.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1257_0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup_no_coke_can.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_sink_calibrate.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_1_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_calibration.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/stack_cube_1st_frame.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/debug.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_standing_coke_can_c0_cleanup.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_coke_can_real_eval_1_brighter.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/stone_tabletop.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/7up_can/Pepsi1.001_baseColor.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_coke_can/Image_2.004.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_spoon_generated_modified/Image_0.003.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/coke_can/Image_2.004.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_0.004.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_3.002.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.vis.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_objaverse/Image_14.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/pepsi_can/Image_0.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_2.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_0.005.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_2.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated/Image_0.005.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_0.005.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/apple/Image_0.001.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated_shorter/Image_0.001.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_pepsi_can/Image_0.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated/Image_0.001.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge_v2/textured.baked.zero123plus.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/orange/Image_2.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/jasmine_tea_3.jpg.002.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_7up_can/Pepsi1.001_baseColor.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/textured.dae filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_0.004.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_3.002.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated_modified/Image_0.005.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_0.004.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_3.002.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_3.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_0.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_cand1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_toobright.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_bkup.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/manual/Image_2.004.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_0.004.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_3.002.jpg filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/maniskill2-scene-2.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_ao_roughness_metalness.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_normal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_diffuse.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_ao_roughness_metalness.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_normal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_ao_roughness_metalness.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_normal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_ao_roughness_metalness.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_normal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_diffuse.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/link_base.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_1.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_2.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_rear_wheel.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_5.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_4.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_3.glb filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_ao_roughness_metalness.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_normal.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/widowx_description/meshes_wx250s/WXSA-250-M-5-LF.stl filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_carrot_on_plate_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_basket_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_pick_random_object.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_coke_can_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_open_drawer_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_put_apple_in_closed_top_drawer.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_spoon_on_towel_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_close_drawer_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_open_drawer.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_stack_cube_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_sink_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_close_drawer.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_move_near_visual_matching.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/SimplerEnv/simpler_env/utils/fonts/UbuntuMono-R.ttf filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/images/fig1.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_cream_cheese_box_and_the_butter_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_alphabet_soup_and_the_tomato_sauce_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_tomato_sauce_and_put_it_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_orange_juice_and_put_it_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_butter_and_put_it_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_milk_and_put_it_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_alphabet_soup_and_put_it_in_the_basket.init filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/gray_ceramic_tile.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_grey_plaster.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_gray_plaster.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_floor_texture.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_blue_wall.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/seamless_wood_planks_floor.png filter=lfs diff=lfs merge=lfs -text +Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/cream-plaster.png filter=lfs diff=lfs merge=lfs -text diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000000.parquet b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000000.parquet new file mode 100644 index 0000000000000000000000000000000000000000..4d23996833e0c2ddef51d03ffcd18e2acb87dc58 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000000.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:037ef9dacbe35d080286f7c2b7e551d4a337b206df03d2f9c88d4c46ac408082 +size 28581 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000001.parquet b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000001.parquet new file mode 100644 index 0000000000000000000000000000000000000000..7b188d598e971c8248cf59b1fa8a5b685455306b --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000001.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:716f7fd62c64072b948a82fde9c83ff61d33caf29e1455d9816d41dc6b055d26 +size 34031 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000002.parquet b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000002.parquet new file mode 100644 index 0000000000000000000000000000000000000000..01f101aadd5265503016f1bf4c4f8b1ecffd27d9 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000002.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9033b86ad77934df1193fb998a16e27b9fa7bdd6e0a522a35d6169b4c2c2d6ae +size 26150 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000003.parquet b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000003.parquet new file mode 100644 index 0000000000000000000000000000000000000000..822ba1c8cadecd5e8992929cc3402a0f49f2f1a0 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/data/chunk-000/episode_000003.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4492790aec5ff414eb45f195d9639d6f58ce445289fbdb3d21038fd1fc7437c8 +size 37131 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000000.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..682ec5dcfa1df60582da317218113bde9fea14a4 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c9a00cb6e2706b8dbc573e3ac2b05402cf6e667ec61786be971e104cac81605 +size 2414613 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000001.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000001.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1515399db407783763246c9da27fc837d05831a3 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000001.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f1c9a635d037856f8ecfb9cc8db41b34441aff15feaa81bd1492f5919f853f3 +size 3158057 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000002.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000002.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..28ab24b5828aabaa0b2b2122cd8c8f98bfe6eb5a --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000002.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:378605259ff8508322985d5f346b7876d07d96b79d35176dc4bf041b3a3e3214 +size 1973577 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000003.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000003.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..0e950ea2b65c15a2f94f0d01762c0ac1b79f552d --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000003.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc28f6fd54be1d04a76d2b739698308bb5eacefe1ebddbc0d592674a6d78f93b +size 7328851 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000004.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000004.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..98d713aec75cc18c53b0c69edc58455eb04799b3 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.front/episode_000004.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf89d6dbc888277cdcd8318c46c91b35841b8dccb37d3c40c5d2c7d2a16865e2 +size 2501708 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000000.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..bd5808da4c86da46dac00de702712c6721afd9a9 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33f42924b0e6f603fb91ffc856430b0abd2c182f1eaf2324f2a3906a60452f06 +size 1442621 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000001.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000001.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..0c3deb8d3a0bc18c00c3ad8b5f7e14f8757df60d --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000001.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92fa46f856f4643dbdb857e8bd1344fbe2d4d5d206a164ed80cae0a768577460 +size 2066389 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000002.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000002.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..4cfd6bd95a9466802fa7d032b37fe8e21b4257c6 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000002.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdf0618a70f633985975aeb554f39ca2588fa7be409b9642b90d668a24a29b33 +size 1230068 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000003.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000003.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..145cd64deb0c2d35e66f866e40397780e447d11d --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000003.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1a658fbfc8601768579e2572ac08a307c7ccf7e17a6457636a5e663e34d29be5 +size 5734830 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000004.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000004.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..138bfc85c545a7aaafd5a3cf5e108e43e2a80d2c --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5/videos/chunk-000/observation.images.wrist/episode_000004.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d362fd9d101fda5f3aa999e6b235d97d97f2cf42514fee6d464a39fe373d75a +size 1498450 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/data/chunk-000/episode_000000.parquet b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/data/chunk-000/episode_000000.parquet new file mode 100644 index 0000000000000000000000000000000000000000..4d23996833e0c2ddef51d03ffcd18e2acb87dc58 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/data/chunk-000/episode_000000.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:037ef9dacbe35d080286f7c2b7e551d4a337b206df03d2f9c88d4c46ac408082 +size 28581 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/masks/chunk-000/observation.images.front/episode_000000_masks.npz b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/masks/chunk-000/observation.images.front/episode_000000_masks.npz new file mode 100644 index 0000000000000000000000000000000000000000..c68c509116907b95e6838769f503913d40768c70 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/masks/chunk-000/observation.images.front/episode_000000_masks.npz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7d2840a15639385914803b6a2c0c7fc2f7485fcad6e9683fdb4e8bbafe6e756 +size 1930481 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/masks/chunk-000/observation.images.wrist/episode_000000_masks.npz b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/masks/chunk-000/observation.images.wrist/episode_000000_masks.npz new file mode 100644 index 0000000000000000000000000000000000000000..8701ee7949601dcb3c3243e404e5d4016f8fdbfd --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/masks/chunk-000/observation.images.wrist/episode_000000_masks.npz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:511e00dbaaca29953ee717d76071e36c1905ac7350200173b308e48c7e434a6a +size 2075699 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.front/episode_000000.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.front/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..682ec5dcfa1df60582da317218113bde9fea14a4 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.front/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c9a00cb6e2706b8dbc573e3ac2b05402cf6e667ec61786be971e104cac81605 +size 2414613 diff --git a/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.wrist/episode_000000.mp4 b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.wrist/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..bd5808da4c86da46dac00de702712c6721afd9a9 --- /dev/null +++ b/Isaac-GR00T/demo_data/cube_to_bowl_5_with_mask/videos/chunk-000/observation.images.wrist/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33f42924b0e6f603fb91ffc856430b0abd2c182f1eaf2324f2a3906a60452f06 +size 1442621 diff --git a/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000000.parquet b/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000000.parquet new file mode 100644 index 0000000000000000000000000000000000000000..92ad90564a1a1e89f5f6cbac8797d2d9d8d3baf1 --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000000.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:137c8556829ffeb4cbc7c41369d0e0c3cd485c2ce4f576d0a0c9b0e83eb0314f +size 140159 diff --git a/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000001.parquet b/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000001.parquet new file mode 100644 index 0000000000000000000000000000000000000000..f7a1f2bc2d94620b97dd3f71f8493f46997c301e --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000001.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14f86cfe04380c5ba8e876cab6e0532b9231af5cd4e5ddcd8e019e458f79d709 +size 211230 diff --git a/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000002.parquet b/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000002.parquet new file mode 100644 index 0000000000000000000000000000000000000000..8f42cc2dcb62d5049171834be989f98d2bea69f1 --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/data/chunk-000/episode_000002.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c22df4dca06122846d4ea0848751d734a211ed008d2bd63e29b66a8ce67222c6 +size 308481 diff --git a/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000000.mp4 b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..cbb42fae5ef49920516712b5f062fd58e02675d4 --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d90ec069d7cb36b47fcd5e7c18dd528235a814dfc965511833f05b5674f5fec +size 946024 diff --git a/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000001.mp4 b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000001.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d9e8231145163679b26789154ee9b01b33f553d3 --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000001.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89f71cb8289f565fe2b6b405909b6810dc0e51166ee409e95cc8e84ed3f9199f +size 1329966 diff --git a/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000002.mp4 b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000002.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..caec15b60f4ef9f2168ec7fc6073f83561112b6a --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.exterior_1_left/episode_000002.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6d575be937d4259dac4f3d33529d7a81ecda5b22b6c1159ae7222a5adfbd80e +size 2604859 diff --git a/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000000.mp4 b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..8919f675e82c718c13dbb1cee3e393641b2c13a7 --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ec4045dbeb4c544b8456fadca6bd0bc2392f25d9cb961942aa613fa3e7205b9 +size 625361 diff --git a/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000001.mp4 b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000001.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..7fef6179529208ce64dbc434db95821d209754e7 --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000001.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b01e89c75c74ac90b518656e49a7033d249ca4a3213aeae8c388a2db3d17b91 +size 1058453 diff --git a/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000002.mp4 b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000002.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..f8b484e7e2563e079e72abf642c9d10401b4aa6c --- /dev/null +++ b/Isaac-GR00T/demo_data/droid_sample/videos/chunk-000/observation.images.wrist_left/episode_000002.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82eeeb20596dae59bd7074c7e44f4dd8c292551d5bd1b2d9948a765523a1f541 +size 1585838 diff --git a/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000000.parquet b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000000.parquet new file mode 100644 index 0000000000000000000000000000000000000000..e2bc7d53effdb042f9bcd7f70aa1de3efede4ed6 --- /dev/null +++ b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000000.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14ef3d742724ad34701136e1dd4709c965ae98066b2fc88a7a26e960d55520a8 +size 5733 diff --git a/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000001.parquet b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000001.parquet new file mode 100644 index 0000000000000000000000000000000000000000..cd270bb521a88bde02c8b354ced122b75d31104a --- /dev/null +++ b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000001.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3abcb7f3f611a415afe5acd5e4b7d0d10e83726db76a1f9f24aacd3397a7c0af +size 7329 diff --git a/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000002.parquet b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000002.parquet new file mode 100644 index 0000000000000000000000000000000000000000..6c865c94932aebb6800ad78901a92275bf97cf0c --- /dev/null +++ b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/data/chunk-000/episode_000002.parquet @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df1d7c6118a0042c9087a4670b795fe34760390fbc9f34ba2a4d422607d47b7b +size 7315 diff --git a/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000000.mp4 b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000000.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..d1898700d00b94a31beeec249925132ce697d22a --- /dev/null +++ b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000000.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12b0e84423d31ff615262dc4943f56aa293cb0b4c0d193fc188916e629006ed1 +size 254345 diff --git a/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000001.mp4 b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000001.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..c2399c17e48e6847b1f362d3a4af1557a0605d64 --- /dev/null +++ b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000001.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7f9653cb282d67d1dde50c356dd5a0fdefee0777f7767232b04c7bde1e94a4e +size 292606 diff --git a/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000002.mp4 b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000002.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..086a1d79b89b067f3d5a4c8f63e7fcce851bcd31 --- /dev/null +++ b/Isaac-GR00T/demo_data/simplerenv_bridge_sample/videos/chunk-000/observation.images.image_0/episode_000002.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac0ebe099566dae4f41a83c67d215ac2dc47baabb8c5a4728c1b82273feb416 +size 258747 diff --git a/Isaac-GR00T/examples/DROID/README.md b/Isaac-GR00T/examples/DROID/README.md new file mode 100644 index 0000000000000000000000000000000000000000..94fcc7cffc1c0d8c13937413f6127bb2aafcedde --- /dev/null +++ b/Isaac-GR00T/examples/DROID/README.md @@ -0,0 +1,110 @@ +# GR00T DROID + +The N1.7 base model supports DROID inference out of the box via the `OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT` pretrain tag. A finetuned checkpoint is also available at [`nvidia/GR00T-N1.7-DROID`](https://huggingface.co/nvidia/GR00T-N1.7-DROID). + +> **Note:** The DROID dataset contains multiple language instruction paraphrases per episode (`language_instruction`, `language_instruction_2`, `language_instruction_3`). These are used for language augmentation during training. At inference time, only the first language key is used. + +## Data Format + +The DROID embodiment expects the following modality structure: + +| Modality | Keys | Dimensions | +|----------|------|------------| +| Video | `exterior_image_1_left`, `wrist_image_left` | 2 cameras | +| State | `eef_9d`, `gripper_position`, `joint_position` | 9D + 1D + 7D = 17D | +| Action | `eef_9d`, `gripper_position`, `joint_position` | 9D + 1D + 7D = 17D | +| Language | `annotation.language.language_instruction` | text | + +Action representations: +- `eef_9d`: relative end-effector (XYZ + rotation 6D) +- `gripper_position`: absolute (1D) +- `joint_position`: relative joint positions (7D) + +### Preparing DROID Demo Data + +The full DROID dataset ([lerobot/droid_1.0.1](https://huggingface.co/datasets/lerobot/droid_1.0.1)) is ~358 GB with 95k+ episodes in LeRobot v3.0 format. To create a small sample for testing: + +```bash +uv pip install jsonlines # one-time dependency +python scripts/download_droid_sample.py +``` + +This downloads the first data/video chunk (~170 MB) and extracts 3 episodes into `demo_data/droid_sample/` in GR00T LeRobot v2.0 format. + +**Key conversion notes:** +- Source is LeRobot v3.0 (consolidated parquet + concatenated videos) — the script converts to v2.0 (per-episode parquet + per-episode mp4). +- Video keys in the raw dataset (`exterior_1_left`, `wrist_left`) differ from the model config keys (`exterior_image_1_left`, `wrist_image_left`). The data loader auto-maps by position — no manual renaming needed. +- Language instructions are loaded via the `task_index` column mapped through `tasks.jsonl`. + +## 1. Standalone Inference (with demo data) + +After preparing demo data, run inference directly (no server needed): + +```bash +uv run python scripts/deployment/standalone_inference_script.py \ + --model-path nvidia/GR00T-N1.7-3B \ + --dataset-path demo_data/droid_sample \ + --embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \ + --traj-ids 0 1 \ + --inference-mode pytorch \ + --execution-horizon 8 +``` + +> **Note:** Episode 0 may have an empty language instruction. If inference fails on episode 0, try `--traj-ids 1 2`. + +Expected zero-shot performance on the base model (not finetuned): + +| Metric | Value | +|--------|-------| +| Average MSE | ~0.0149 | +| Average MAE | ~0.0753 | +| Inference per step (base) | ~262 ms (H100) | +| Inference per step (finetuned) | ~253 ms (H100) | + +## 2. Inference Server (for real-world deployment) + +### Using the base model (zero-shot): + +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path nvidia/GR00T-N1.7-3B \ + --embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT +``` + +### Using the finetuned model: + +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path nvidia/GR00T-N1.7-DROID \ + --embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT +``` + +## 3. Fine-tuning + +Fine-tune the base model on DROID data using the shared launcher: + +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=640 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path demo_data/droid_sample \ + --embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \ + --output-dir /tmp/droid_finetune +``` + +> **Note:** The above uses the small `demo_data/droid_sample` (3 episodes) for quick validation. For production training, replace `--dataset-path` with the full DROID dataset. + +## 4. Robot Control Script + +1. Install the DROID package on the robot control laptop/workstation — [instructions](https://droid-dataset.github.io/droid/software-setup/host-installation.html#configuring-the-laptopworkstation) + +2. Install dependencies for the GR00T control script in the environment from step 1: +```bash +pip install tyro pydantic numpy==1.26.4 +``` + +3. Enter the camera IDs for your ZED cameras in `examples/DROID/main_gr00t.py`. + +4. Start the control script: +```bash +python examples/DROID/main_gr00t.py --external-camera="left" # or "right" +``` diff --git a/Isaac-GR00T/examples/DROID/main_gr00t.py b/Isaac-GR00T/examples/DROID/main_gr00t.py new file mode 100644 index 0000000000000000000000000000000000000000..e56ca6fc3687122b065c16a313d5a48ad988af1e --- /dev/null +++ b/Isaac-GR00T/examples/DROID/main_gr00t.py @@ -0,0 +1,503 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ruff: noqa +# NOTE: this requires installation of the droid repo. +# Adapted from https://github.com/Physical-Intelligence/openpi/blob/main/examples/droid/main.py + +from __future__ import annotations + +import contextlib +import dataclasses +import datetime +import faulthandler +import os +import signal +import time +from collections import deque + +import cv2 +import numpy as np +import pandas as pd +import tqdm +import tyro +from PIL import Image + +from scipy.spatial.transform import Rotation + +faulthandler.enable() + +# DROID data collection frequency -- we slow down execution to match this frequency +DROID_CONTROL_FREQUENCY = 15 +RESOLUTION = (180, 320) # resize images to this resolution before sending to the policy server + +# Egocentric frame correction: R_euler is post-multiplied by this matrix +# to match the OXE DROID training pipeline (TFG convention). +# audit: mirror of gr00t/data/state_action/droid_frame.py — this example runs on +# a slim DROID install without the gr00t package, so it cannot import the +# canonical source. Keep this matrix and compute_eef_9d in sync with it. +DROID_EEF_ROTATION_CORRECT = np.array( + [[0, 0, -1], [-1, 0, 0], [0, 1, 0]], + dtype=np.float64, +) + + +def compute_eef_9d(cartesian_position: np.ndarray) -> np.ndarray: + """Convert cartesian_position (XYZ + euler 3D) to eef_9d (XYZ + rot6d). + + Uses extrinsic XYZ Euler convention (scipy ``"XYZ"``, equivalent to + ``tfg.rotation_matrix_3d.from_euler``) and post-multiplies by + ``DROID_EEF_ROTATION_CORRECT`` to match the pretrained model. + """ + c = np.asarray(cartesian_position, dtype=np.float64).reshape(6) + xyz = c[:3] + euler = c[3:6] + rot_robot = Rotation.from_euler("XYZ", euler).as_matrix() + rot_mat = rot_robot @ DROID_EEF_ROTATION_CORRECT + rot6d = rot_mat[:2, :].reshape(6) + return np.concatenate([xyz, rot6d]).astype(np.float32) + + +@dataclasses.dataclass +class Args: + # Hardware parameters + + left_camera_id: str = "" # e.g., "24259877" + right_camera_id: str = "" # e.g., "24514023" + wrist_camera_id: str = "" # e.g., "13062452" + + # Policy parameters + policy_host: str = "localhost" + policy_port: int = 5555 + policy_api_token: str = None + + results_dir: str = None # if None, will use the current timestamp as the results directory + + # Rollout parameters + max_timesteps: int = 600 # how many steps to run each rollout + + # How many actions to execute from a predicted action chunk before querying policy server again + open_loop_horizon: int = 15 + external_camera: str = ( + "left" # which exterior camera to use for the policy server, choose from ["left", "right"] + ) + render_camera: str = "left" # which camera to render saved video from + render_fps: int = 50 + + debug: bool = False + vis_cameras: bool = False + + delay_seconds: int = 5 + + +def _load_runtime_deps(): + """Load robot-only dependencies after CLI parsing so --help stays usable.""" + try: + import imageio + from droid.robot_env import RobotEnv + from server_client import PolicyClient + from utils import resize_with_pad + except ModuleNotFoundError as exc: + raise ModuleNotFoundError( + "examples/DROID/main_gr00t.py requires the DROID robot-control environment. " + "Follow examples/DROID/README.md and install the DROID package plus " + "`pip install tyro pydantic numpy==1.26.4` before running." + ) from exc + + return RobotEnv, PolicyClient, imageio, resize_with_pad + + +# We are using Ctrl+C to optionally terminate rollouts early -- however, if we press Ctrl+C while the policy server is +# waiting for a new action chunk, it will raise an exception and the server connection dies. +# This context manager temporarily prevents Ctrl+C and delays it after the server call is complete. +@contextlib.contextmanager +def prevent_keyboard_interrupt(): + """Temporarily prevent keyboard interrupts by delaying them until after the protected code.""" + interrupted = False + original_handler = signal.getsignal(signal.SIGINT) + + def handler(signum, frame): + nonlocal interrupted + interrupted = True + + signal.signal(signal.SIGINT, handler) + try: + yield + finally: + signal.signal(signal.SIGINT, original_handler) + if interrupted: + raise KeyboardInterrupt + + +def main(args: Args): + RobotEnv, PolicyClient, imageio, resize_with_pad = _load_runtime_deps() + + assert args.external_camera in ["left", "right"], ( + f"Invalid exterior camera: {args.exterior_camera}" + ) + + if args.results_dir is None: + results_dir = f"results_gr00t_{datetime.datetime.now().strftime('%Y_%m_%d')}" + else: + results_dir = args.results_dir + + # Initialize the Panda environment. + env = RobotEnv(action_space="joint_position", gripper_action_space="position") + print("Created the droid env!") + + os.makedirs(results_dir, exist_ok=True) + + policy_client = PolicyClient( + host=args.policy_host, port=args.policy_port, api_token=args.policy_api_token + ) + + modality_config = policy_client.get_modality_config() + video_delta = modality_config["video"].delta_indices + video_T = len(video_delta) + video_history_len = max(-min(video_delta), 0) + 1 if video_delta else 1 + video_keys = modality_config["video"].modality_keys + state_keys = modality_config["state"].modality_keys + state_T = len(modality_config["state"].delta_indices) + # Action chunk size is dictated by the policy (server) side. open_loop_horizon + # is the only locally-authored horizon; it is a deliberate receding-horizon + # choice and MAY be < the chunk, but it must never exceed it, otherwise + # `pred_action_chunk[actions_from_chunk_completed]` indexes past the + # predicted chunk and IndexErrors mid-rollout. Source the chunk size from + # the policy and validate the contract up-front instead of crashing deep in + # the loop. + action_chunk_size = len(modality_config["action"].delta_indices) + if not (1 <= args.open_loop_horizon <= action_chunk_size): + raise ValueError( + f"open_loop_horizon={args.open_loop_horizon} must satisfy " + f"1 <= open_loop_horizon <= action_chunk_size={action_chunk_size} " + "(= len(policy.action.delta_indices)). A larger value would index " + "past the predicted action chunk and IndexError mid-rollout." + ) + print( + f"Model config — video T={video_T} (delta={video_delta}), " + f"state T={state_T}, action chunk={action_chunk_size}, " + f"open_loop_horizon={args.open_loop_horizon}, " + f"keys: video={video_keys}, state={state_keys}" + ) + + df = pd.DataFrame(columns=["success", "duration", "video_filename"]) + + if args.debug: + debug_dir = os.path.join(results_dir, "debug_data") + os.makedirs(debug_dir, exist_ok=True) + os.makedirs(os.path.join(debug_dir, "videos/wrist_image/"), exist_ok=True) + os.makedirs(os.path.join(debug_dir, "videos/exterior_image_1_left/"), exist_ok=True) + + instruction = None + while True: + if instruction is None: + instruction = input("Enter instruction: ") + else: + if input("Change instruction? (enter y or n) ").lower() == "y": + instruction = input("Enter instruction: ") + + time.sleep(args.delay_seconds) + + # Rollout parameters + actions_from_chunk_completed = 0 + pred_action_chunk = None + + # Prepare to save video of rollout + timestamp = datetime.datetime.now().strftime("%Y_%m_%d_%H:%M:%S") + video = [] + if args.debug: + model_wrist_image_writer = imageio.get_writer( + os.path.join( + debug_dir, "videos/wrist_image/", f"model_wrist_image_{timestamp}.mp4" + ), + fps=5, + ) + model_exterior_image_1_left_writer = imageio.get_writer( + os.path.join( + debug_dir, + "videos/exterior_image_1_left/", + f"model_exterior_image_1_left_{timestamp}.mp4", + ), + fps=5, + ) + + bar = tqdm.tqdm(range(args.max_timesteps)) + print("Running rollout... press Ctrl+C to stop early.") + + # Profiling variables (reset for each rollout) + rollout_start_time = time.time() + obs_times = deque(maxlen=50) # Track observation collection times + server_times = deque(maxlen=50) # Track server response times + action_count = 0 + frame_buffer = deque(maxlen=video_history_len) + + for t_step in bar: + step_start_time = time.time() + try: + # Get the current observation + obs_start_time = time.time() + curr_obs = _extract_observation( + args, + env.get_observation(), + # Save the first observation to disk + save_to_disk=t_step == 0, + ) + obs_time = time.time() - obs_start_time + obs_times.append(obs_time) + + video.append(curr_obs[f"{args.render_camera}_image"]) + + # Resize every step so the rolling frame buffer stays current. + left_image = resize_with_pad(curr_obs["left_image"], RESOLUTION[0], RESOLUTION[1]) + right_image = resize_with_pad(curr_obs["right_image"], RESOLUTION[0], RESOLUTION[1]) + wrist_image = resize_with_pad(curr_obs["wrist_image"], RESOLUTION[0], RESOLUTION[1]) + + if args.external_camera == "left": + ext_image = left_image + elif args.external_camera == "right": + ext_image = right_image + + frame_buffer.append({"ext": ext_image, "wrist": wrist_image}) + + # Send websocket request to policy server if it's time to predict a new chunk + if ( + actions_from_chunk_completed == 0 + or actions_from_chunk_completed >= args.open_loop_horizon + ): + actions_from_chunk_completed = 0 + + if args.debug: + model_wrist_image_writer.append_data(wrist_image) + model_exterior_image_1_left_writer.append_data(ext_image) + + # Build video tensor with T frames derived from the model's + # delta_indices (e.g. [-15, 0] -> T=2, [0] -> T=1). + if video_T == 1: + video_dict = { + "exterior_image_1_left": ext_image[None, None, ...], + "wrist_image_left": wrist_image[None, None, ...], + } # (B=1, T=1, H, W, C) + else: + hist_frame = frame_buffer[0] + cur_frame = frame_buffer[-1] + video_dict = { + "exterior_image_1_left": np.stack( + [hist_frame["ext"], cur_frame["ext"]] + )[None, ...], + "wrist_image_left": np.stack([hist_frame["wrist"], cur_frame["wrist"]])[ + None, ... + ], + } # (B=1, T=video_T, H, W, C) + + # Build state dict from the model's reported state keys. + state_dict = {} + state_source = { + "eef_9d": curr_obs["eef_9d"], + "gripper_position": curr_obs["gripper_position"], + "joint_position": curr_obs["joint_position"], + } + for key in state_keys: + state_dict[key] = state_source[key][None, None, ...].astype( + np.float32 + ) # (B=1, T=1, D) + + lang_key = modality_config["language"].modality_keys[0] + request_data = { + "video": video_dict, + "state": state_dict, + "language": {lang_key: [[instruction]]}, + } + + if args.vis_cameras: + # viz the left image 1 and wrist image and use cv2 to display them side by side + left_image_display = cv2.resize( + left_image, (wrist_image.shape[1], wrist_image.shape[0]) + ) + combined_display = np.concatenate([left_image_display, wrist_image], axis=1) + # convert to bgr + combined_display = combined_display[..., ::-1] + cv2.imshow("Camera Views", combined_display) + cv2.waitKey(1) + + # Wrap the server call in a context manager to prevent Ctrl+C from interrupting it + # Ctrl+C will be handled after the server call is complete + server_start_time = time.time() + with prevent_keyboard_interrupt(): + # this returns action chunk [N, 8] of joint position actions (7) + gripper position (1) + response = policy_client.get_action(request_data) + server_time = time.time() - server_start_time + server_times.append(server_time) + + pred_action_chunk = np.concatenate( + ( + response[0]["joint_position"][0], + response[0]["gripper_position"][0], + ), + axis=1, + ) + + # Select current action to execute from chunk + action = pred_action_chunk[actions_from_chunk_completed] + actions_from_chunk_completed += 1 + + # Binarize gripper action + if action[-1].item() > 0.5: + action = np.concatenate([action[:-1], np.ones((1,))]) + else: + action = np.concatenate([action[:-1], np.zeros((1,))]) + + env.step(action) + action_count += 1 + + # Sleep to match DROID data collection frequency + elapsed_time = time.time() - step_start_time + if elapsed_time < 1 / DROID_CONTROL_FREQUENCY: + time.sleep(1 / DROID_CONTROL_FREQUENCY - elapsed_time) + + # profiling stats + if obs_times: + avg_obs_time = np.mean(obs_times) * 1000 + min_obs_time = np.min(obs_times) * 1000 + max_obs_time = np.max(obs_times) * 1000 + else: + avg_obs_time = min_obs_time = max_obs_time = 0 + + if server_times: + avg_server_time = np.mean(server_times) * 1000 + min_server_time = np.min(server_times) * 1000 + max_server_time = np.max(server_times) * 1000 + else: + avg_server_time = min_server_time = max_server_time = 0 + + total_elapsed = time.time() - rollout_start_time + actions_per_sec = action_count / total_elapsed if total_elapsed > 0 else 0 + + bar.set_description( + f"Obs: {avg_obs_time:.1f}ms [{min_obs_time:.1f}-{max_obs_time:.1f}] | " + f"Server: {avg_server_time:.1f}ms [{min_server_time:.1f}-{max_server_time:.1f}] | " + f"Actions/sec: {actions_per_sec:.2f}" + ) + except KeyboardInterrupt: + break + + os.makedirs(os.path.join(results_dir, "videos"), exist_ok=True) + video = np.stack(video) + # replace whitespace with underscores in instruction + sanitized_instruction = instruction.replace(" ", "_") + save_filename = os.path.join( + results_dir, "videos", f"{sanitized_instruction}_video_" + timestamp + ) + with imageio.get_writer(save_filename + ".mp4", fps=args.render_fps) as writer: + for frame in video: + writer.append_data(frame) + + if args.debug: + model_wrist_image_writer.close() + model_exterior_image_1_left_writer.close() + + success: str | float | None = None + while not isinstance(success, float): + success = input( + "Did the rollout succeed? (enter y for 100%, n for 0%), or a numeric value 0-100 based on the evaluation spec" + ) + if success == "y": + success = 1.0 + elif success == "n": + success = 0.0 + + success = float(success) / 100 + if not (0 <= success <= 1): + print(f"Success must be a number in [0, 100] but got: {success * 100}") + + new_row = { + "success": success, + "duration": t_step, + "video_filename": save_filename, + } + new_index = len(df) + df.loc[new_index] = new_row + + if input("Do one more eval? (enter y or n) ").lower() != "y": + break + env.reset(randomize=False) + + timestamp = datetime.datetime.now().strftime("%I:%M%p_%B_%d_%Y") + csv_filename = os.path.join(results_dir, f"eval_{timestamp}.csv") + df.to_csv(csv_filename) + print(f"Results saved to {csv_filename}") + + +def _extract_observation(args: Args, obs_dict, *, stereo_camera="left", save_to_disk=False): + image_observations = obs_dict["image"] + key_left = f"{args.left_camera_id}_{stereo_camera}" + key_right = f"{args.right_camera_id}_{stereo_camera}" + key_wrist = f"{args.wrist_camera_id}_{stereo_camera}" + + left_image = image_observations.get(key_left) + right_image = image_observations.get(key_right) + wrist_image = image_observations.get(key_wrist) + + available = list(image_observations.keys()) + assert left_image is not None, ( + f"Left camera not found for key {key_left!r}. Available keys: {available}. " + "Set --left-camera-id to the ZED serial used in observation keys." + ) + assert right_image is not None, ( + f"Right camera not found for key {key_right!r}. Available keys: {available}. " + "Set --right-camera-id to the ZED serial used in observation keys." + ) + assert wrist_image is not None, ( + f"Wrist camera not found for key {key_wrist!r}. Available keys: {available}. " + "Set --wrist-camera-id to the ZED serial used in observation keys." + ) + + # Drop the alpha dimension + left_image = left_image[..., :3] + right_image = right_image[..., :3] + wrist_image = wrist_image[..., :3] + + # Convert to RGB + left_image = left_image[..., ::-1] + right_image = right_image[..., ::-1] + wrist_image = wrist_image[..., ::-1] + + # In addition to image observations, also capture the proprioceptive state + robot_state = obs_dict["robot_state"] + cartesian_position = np.array(robot_state["cartesian_position"]) + joint_position = np.array(robot_state["joint_positions"]) + gripper_position = np.array([robot_state["gripper_position"]]) + eef_9d = compute_eef_9d(cartesian_position) + + # Save the images to disk so that they can be viewed live while the robot is running + # Create one combined image to make live viewing easy + if save_to_disk: + combined_image = np.concatenate([left_image, wrist_image, right_image], axis=1) + combined_image = Image.fromarray(combined_image) + combined_image.save("robot_camera_views.png") + + return { + "left_image": left_image, + "right_image": right_image, + "wrist_image": wrist_image, + "cartesian_position": cartesian_position, + "eef_9d": eef_9d, + "joint_position": joint_position, + "gripper_position": gripper_position, + } + + +if __name__ == "__main__": + args: Args = tyro.cli(Args) + main(args) diff --git a/Isaac-GR00T/examples/DROID/server_client.py b/Isaac-GR00T/examples/DROID/server_client.py new file mode 100644 index 0000000000000000000000000000000000000000..51a4c149de94b8776478893b14f57b4e46cf1436 --- /dev/null +++ b/Isaac-GR00T/examples/DROID/server_client.py @@ -0,0 +1,395 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +from abc import ABC, abstractmethod +from dataclasses import asdict, dataclass, is_dataclass +from enum import Enum +import io +from typing import Any + +import msgpack +import numpy as np +import zmq + + +def to_json_serializable(obj: Any) -> Any: + """ + Recursively convert dataclasses and numpy arrays to JSON-serializable format. + + Args: + obj: Object to convert (can be dataclass, numpy array, dict, list, etc.) + + Returns: + JSON-serializable representation of the object + """ + if is_dataclass(obj) and not isinstance(obj, type): + # Convert dataclass to dict, then recursively process the dict + return to_json_serializable(asdict(obj)) + elif isinstance(obj, np.ndarray): + # Convert numpy array to list + return obj.tolist() + elif isinstance(obj, np.integer): + # Convert numpy integers to Python int + return int(obj) + elif isinstance(obj, np.floating): + # Convert numpy floats to Python float + return float(obj) + elif isinstance(obj, np.bool_): + # Convert numpy bool to Python bool + return bool(obj) + elif isinstance(obj, dict): + # Recursively process dictionary values + return {key: to_json_serializable(value) for key, value in obj.items()} + elif isinstance(obj, (list, tuple)): + # Recursively process list/tuple elements + return [to_json_serializable(item) for item in obj] + elif isinstance(obj, set): + # Convert set to list + return [to_json_serializable(item) for item in obj] + elif isinstance(obj, (str, int, float, bool, type(None))): + # Already JSON-serializable + return obj + elif isinstance(obj, Enum): + return obj.name + else: + # For other types, try to convert to string as fallback + # You might want to handle specific types differently + return str(obj) + + +class MessageType(Enum): + START_OF_EPISODE = "start_of_episode" + END_OF_EPISODE = "end_of_episode" + EPISODE_STEP = "episode_step" + IMAGE = "image" + TEXT = "text" + + +class ActionRepresentation(Enum): + RELATIVE = "relative" + DELTA = "delta" + ABSOLUTE = "absolute" + + +class ActionType(Enum): + EEF = "eef" + NON_EEF = "non_eef" + + +class ActionFormat(Enum): + DEFAULT = "default" + XYZ_ROT6D = "xyz+rot6d" + XYZ_ROTVEC = "xyz+rotvec" + + +@dataclass +class ActionConfig: + rep: ActionRepresentation + type: ActionType + format: ActionFormat + state_key: str | None = None + + +@dataclass +class ModalityConfig: + """Configuration for a modality defining how data should be sampled and loaded. + + This class specifies which indices to sample relative to a base index and which + keys to load for a particular modality (e.g., video, state, action). + """ + + delta_indices: list[int] + """Delta indices to sample relative to the current index. The returned data will correspond to the original data at a sampled base index + delta indices.""" + modality_keys: list[str] + """The keys to load for the modality in the dataset.""" + sin_cos_embedding_keys: list[str] | None = None + """Optional list of keys to apply sin/cos encoding. If None or empty, use min/max normalization for all keys.""" + mean_std_embedding_keys: list[str] | None = None + """Optional list of keys to apply mean/std normalization. If None or empty, use min/max normalization for all keys.""" + action_configs: list[ActionConfig] | None = None + + def __post_init__(self): + """Set default values for action-related fields if not specified.""" + if self.action_configs is not None: + assert len(self.action_configs) == len(self.modality_keys), ( + f"Number of action configs ({len(self.action_configs)}) must match number of modality keys ({len(self.modality_keys)})" + ) + parsed_action_configs = [] + for action_config in self.action_configs: + if isinstance(action_config, dict): + action_config = ActionConfig( + rep=ActionRepresentation[action_config["rep"]], + type=ActionType[action_config["type"]], + format=ActionFormat[action_config["format"]], + state_key=action_config.get("state_key", None), + ) + parsed_action_configs.append(action_config) + self.action_configs = parsed_action_configs + + +class MsgSerializer: + @staticmethod + def to_bytes(data: Any) -> bytes: + return msgpack.packb(data, default=MsgSerializer.encode_custom_classes) + + @staticmethod + def from_bytes(data: bytes) -> Any: + return msgpack.unpackb(data, object_hook=MsgSerializer.decode_custom_classes) + + @staticmethod + def decode_custom_classes(obj): + if not isinstance(obj, dict): + return obj + if "__ModalityConfig_class__" in obj: + return ModalityConfig(**obj["as_json"]) + if "__ndarray_class__" in obj: + return np.load(io.BytesIO(obj["as_npy"]), allow_pickle=False) + return obj + + @staticmethod + def encode_custom_classes(obj): + if isinstance(obj, ModalityConfig): + # Convert to dict and let msgpack recursively handle nested objects + return {"__ModalityConfig_class__": True, "as_json": to_json_serializable(obj)} + if isinstance(obj, np.ndarray): + output = io.BytesIO() + np.save(output, obj, allow_pickle=False) + return {"__ndarray_class__": True, "as_npy": output.getvalue()} + return obj + + +class BasePolicy(ABC): + """Abstract base class for robotic control policies. + + This class defines the interface that all policies must implement, including + methods for action computation, input/output validation, and state management. + + Subclasses must implement: + - check_observation(): Validate observation format + - check_action(): Validate action format + - _get_action(): Core action computation logic + - reset(): Reset policy to initial state + """ + + def __init__(self, *, strict: bool = True): + self.strict = strict + + @abstractmethod + def check_observation(self, observation: dict[str, Any]) -> None: + """Check if the observation is valid. + + Args: + observation: Dictionary containing the current state/observation of the environment + + Raises: + AssertionError: If the observation is invalid. + """ + pass + + @abstractmethod + def check_action(self, action: dict[str, Any]) -> None: + """Check if the action is valid. + + Args: + action: Dictionary containing the action to be executed + + Raises: + AssertionError: If the action is invalid. + """ + pass + + @abstractmethod + def _get_action( + self, observation: dict[str, Any], options: dict[str, Any] | None = None + ) -> tuple[dict[str, Any], dict[str, Any]]: + """Compute and return the next action based on current observation. + + This method should be overridden by subclasses to implement policy-specific + action computation. Input validation is handled by the public get_action() method. + + Args: + observation: Dictionary containing the current state/observation + options: Optional configuration dict for action computation + + Returns: + Tuple of (action, info): + - action: Dictionary containing the action to be executed + - info: Dictionary containing additional metadata (e.g., confidence scores) + """ + pass + + def get_action( + self, observation: dict[str, Any], options: dict[str, Any] | None = None + ) -> tuple[dict[str, Any], dict[str, Any]]: + """Compute and return the next action based on current observation with validation. + + This is the main public interface. It validates the observation, calls + the internal _get_action(), and validates the resulting action. + + Args: + observation: Dictionary containing the current state/observation + options: Optional configuration dict for action computation + + Returns: + Tuple of (action, info): + - action: Dictionary containing the validated action + - info: Dictionary containing additional metadata + + Raises: + AssertionError/ValueError: If observation or action validation fails + """ + if self.strict: + self.check_observation(observation) + action, info = self._get_action(observation, options) + if self.strict: + self.check_action(action) + return action, info + + @abstractmethod + def reset(self, options: dict[str, Any] | None = None) -> dict[str, Any]: + """Reset the policy to its initial state. + + Args: + options: Dictionary containing the options for the reset + + Returns: + Dictionary containing the info after resetting the policy + """ + pass + + +class PolicyClient(BasePolicy): + def __init__( + self, + host: str = "localhost", + port: int = 5555, + timeout_ms: int = 15000, + api_token: str = None, + strict: bool = False, + ): + super().__init__(strict=strict) + self._closed = False + self.context = zmq.Context() + self.host = host + self.port = port + self.timeout_ms = timeout_ms + self.api_token = api_token + self._init_socket() + + def _init_socket(self): + """Initialize or reinitialize the socket with current settings""" + self.socket = self.context.socket(zmq.REQ) + self.socket.connect(f"tcp://{self.host}:{self.port}") + + def ping(self) -> bool: + try: + self.call_endpoint("ping", requires_input=False) + return True + except zmq.error.ZMQError: + self._init_socket() # Recreate socket for next attempt + return False + + def kill_server(self): + """ + Kill the server. + """ + self.call_endpoint("kill", requires_input=False) + + def call_endpoint( + self, endpoint: str, data: dict | None = None, requires_input: bool = True + ) -> Any: + """ + Call an endpoint on the server. + + Args: + endpoint: The name of the endpoint. + data: The input data for the endpoint. + requires_input: Whether the endpoint requires input data. + """ + request: dict = {"endpoint": endpoint} + if requires_input: + request["data"] = data + if self.api_token: + request["api_token"] = self.api_token + + self.socket.send(MsgSerializer.to_bytes(request)) + message = self.socket.recv() + if message == b"ERROR": + raise RuntimeError("Server error. Make sure we are running the correct policy server.") + response = MsgSerializer.from_bytes(message) + + if isinstance(response, dict) and "error" in response: + raise RuntimeError(f"Server error: {response['error']}") + return response + + def close(self) -> None: + """Release the REQ socket and ZMQ context. Idempotent. + + Mirrors ``gr00t.policy.server_client.PolicyClient.close()`` so the + DROID example demonstrates the explicit-lifecycle pattern. + """ + if getattr(self, "_closed", True): + return + self._closed = True + socket = getattr(self, "socket", None) + if socket is not None: + try: + socket.close(linger=0) + except Exception: + pass + context = getattr(self, "context", None) + if context is not None: + try: + context.term() + except Exception: + pass + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + self.close() + + def __del__(self): + try: + self.close() + except Exception: + pass + + def _get_action( + self, observation: dict[str, Any], options: dict[str, Any] | None = None + ) -> tuple[dict[str, Any], dict[str, Any]]: + response = self.call_endpoint( + "get_action", {"observation": observation, "options": options} + ) + return tuple(response) # Convert list (from msgpack) to tuple of (action, info) + + def reset(self, options: dict[str, Any] | None = None) -> dict[str, Any]: + return self.call_endpoint("reset", {"options": options}) + + def get_modality_config(self) -> dict[str, ModalityConfig]: + return self.call_endpoint("get_modality_config", requires_input=False) + + def check_observation(self, observation: dict[str, Any]) -> None: + raise NotImplementedError( + "check_observation is not implemented. Please use `strict=False` to disable strict mode or implement this method in the subclass." + ) + + def check_action(self, action: dict[str, Any]) -> None: + raise NotImplementedError( + "check_action is not implemented. Please use `strict=False` to disable strict mode or implement this method in the subclass." + ) diff --git a/Isaac-GR00T/examples/DROID/utils.py b/Isaac-GR00T/examples/DROID/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f62e7494e366cee4a3fe0e6f1ed4187327b491d2 --- /dev/null +++ b/Isaac-GR00T/examples/DROID/utils.py @@ -0,0 +1,81 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Taken from https://github.com/Physical-Intelligence/openpi/tree/main/packages/openpi-client/src/openpi_client +""" + +import numpy as np +from PIL import Image + + +def convert_to_uint8(img: np.ndarray) -> np.ndarray: + """Converts an image to uint8 if it is a float image. + + This is important for reducing the size of the image when sending it over the network. + """ + if np.issubdtype(img.dtype, np.floating): + img = (255 * img).astype(np.uint8) + return img + + +def resize_with_pad( + images: np.ndarray, height: int, width: int, method=Image.BILINEAR +) -> np.ndarray: + """Replicates tf.image.resize_with_pad for multiple images using PIL. Resizes a batch of images to a target height. + + Args: + images: A batch of images in [..., height, width, channel] format. + height: The target height of the image. + width: The target width of the image. + method: The interpolation method to use. Default is bilinear. + + Returns: + The resized images in [..., height, width, channel]. + """ + # If the images are already the correct size, return them as is. + if images.shape[-3:-1] == (height, width): + return images + + original_shape = images.shape + + images = images.reshape(-1, *original_shape[-3:]) + resized = np.stack( + [_resize_with_pad_pil(Image.fromarray(im), height, width, method=method) for im in images] + ) + return resized.reshape(*original_shape[:-3], *resized.shape[-3:]) + + +def _resize_with_pad_pil(image: Image.Image, height: int, width: int, method: int) -> Image.Image: + """Replicates tf.image.resize_with_pad for one image using PIL. Resizes an image to a target height and + width without distortion by padding with zeros. + + Unlike the jax version, note that PIL uses [width, height, channel] ordering instead of [batch, h, w, c]. + """ + cur_width, cur_height = image.size + if cur_width == width and cur_height == height: + return image # No need to resize if the image is already the correct size. + + ratio = max(cur_width / width, cur_height / height) + resized_height = int(cur_height / ratio) + resized_width = int(cur_width / ratio) + resized_image = image.resize((resized_width, resized_height), resample=method) + + zero_image = Image.new(resized_image.mode, (width, height), 0) + pad_height = max(0, int((height - resized_height) / 2)) + pad_width = max(0, int((width - resized_width) / 2)) + zero_image.paste(resized_image, (pad_width, pad_height)) + assert zero_image.size == (width, height) + return zero_image diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/README.md b/Isaac-GR00T/examples/GR00TWholeBodyControl/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7f1d35e80a220823f8de9c87c87257ddc9b73231 --- /dev/null +++ b/Isaac-GR00T/examples/GR00TWholeBodyControl/README.md @@ -0,0 +1,115 @@ +# GR00T Whole-Body Control Real-World Benchmark + +This example reports a real-world Unitree G1 evaluation using **Isaac GR00T N1.7** together with **GR00T Whole-Body Control / GEAR-SONIC**. The benchmark focuses on everyday mobile-manipulation tasks that require walking, table approach, grasping, foot placement, and whole-body pickup motions. + +## Summary + +GR00T N1.7 with SONIC can execute closed-loop whole-body skills on a real humanoid robot. The main targeted task is **walk to a table and pick up an object**. A single mixed-object policy was trained from demonstrations covering about 50 table-top objects, then evaluated systematically across 8 representative objects in the training set. This follows the object-pickup setting studied in the [SONIC paper](https://nvlabs.github.io/GEAR-SONIC/static/pdf/sonic_paper.pdf), where the robot walks to a table, locates a target object, and grasps it under randomized table heights and object positions. A second task-specific policy was trained for walking to a small table, picking up a soda can, stepping on a trash-can trigger, and dropping the can inside. + +For more GR00T Whole-Body Control task examples, see the [GEAR-SONIC project page](https://nvlabs.github.io/GEAR-SONIC/). + +## Evaluation Results + +| Task Family | Policy Setup | Task Specification | Logged Trials | Successes | Success Rate | +| --- | --- | --- | ---: | ---: | ---: | +| Walk to table and pick up object | Single mixed-object pickup policy | Walk to the table, localize a target object, grasp it, and lift it. Evaluated on 8 objects across 3 table heights and 9 object placements. Autonomous retries count as success. | 216 | 159 | 73.6% | +| Soda can from small table to trash can | Task-specific soda-can policy | Walk toward a small table, pick up a soda can, rotate toward the trash can, step on the trigger, and drop the can inside. | 12 | 8 | 66.7% | + +For object pickup, each object was evaluated with 27 trials: 3 table heights (24, 27, and 30 inches) crossed with a 3 by 3 grid of object placements on the table (left/middle/right and front/middle/back). The failures were mostly grasp failures: the gripper missed the object, contacted it from an unstable grasp point, pushed it out of reach, or dropped it into a pose that the policy could not recover from. The soda-can failures were similarly dominated by missed grasps, unstable grasps, or missed trigger steps. + +### Object Pickup Breakdown + +| Object | Trials | Successes | Success Rate | +| --- | ---: | ---: | ---: | +| Towel | 27 | 24 | 88.9% | +| Shoe | 27 | 14 | 51.9% | +| Apple | 27 | 19 | 70.4% | +| Scoop | 27 | 18 | 66.7% | +| Lamp | 27 | 17 | 63.0% | +| Flashlight | 27 | 20 | 74.1% | +| Fruit | 27 | 26 | 96.3% | +| Sock | 27 | 21 | 77.8% | + +## Demo Videos + +The MP4 samples below are attached as video files in this repository. Click any preview image to open the corresponding MP4. The source tree intentionally keeps only a curated sample set; full per-trial review videos are better shared as supplementary material through a stable gallery or archive. For more task demos beyond these two quantified results, see the [GEAR-SONIC project page](https://nvlabs.github.io/GEAR-SONIC/). + +### Walk To Table And Pick Up Objects + +Representative examples are included for the evaluated object pickup task. Captions describe the behavior visible in the clip; some successful clips include retries, regrasping, object contact, or small recovery motions because autonomous recovery was counted as success during evaluation. A trial is considered failure when it stucks for over 30s without progress. + +| Object | Example 1 | Example 2 | +| --- | --- | --- | +| Lamp | [Lamp pickup from a 24-inch table placement](media/g1_real_eval/videos/mixed_pickup_lamp_01_pickup_success.mp4)
Picks up the lamp from a 24-inch table | [Lamp base grasp after contact at a 30-inch table placement](media/g1_real_eval/videos/mixed_pickup_lamp_02_base_grasp_success.mp4)
Contacts the lamp, then grasps the base | +| Towel | [Towel pickup from a 24-inch table placement](media/g1_real_eval/videos/mixed_pickup_towel_01_pickup_success.mp4)
Picks up the towel | [Towel grasp, drop, and regrasp sequence](media/g1_real_eval/videos/mixed_pickup_towel_02_regrasp_success.mp4)
Grasps, drops, and regrasps | +| Apple | [Apple pickup after a retry grasp](media/g1_real_eval/videos/mixed_pickup_apple_01_retry_success.mp4)
Retries the grasp and succeeds | [Apple pickup after gripper adjustment over the object](media/g1_real_eval/videos/mixed_pickup_apple_02_adjust_success.mp4)
Adjusts over the apple before lifting | +| Shoe | [Shoe pickup after multiple grasp attempts](media/g1_real_eval/videos/mixed_pickup_shoe_01_many_attempts_success.mp4)
Succeeds after several attempts | [Shoe drop and regrasp success](media/g1_real_eval/videos/mixed_pickup_shoe_02_regrasp_success.mp4)
Drops the shoe, then regrasps | +| Scoop | [Scoop pickup from a 27-inch table placement](media/g1_real_eval/videos/mixed_pickup_scoop_01_pickup_success.mp4)
Picks up the scoop | [Scoop pickup with noisy approach motion](media/g1_real_eval/videos/mixed_pickup_scoop_02_noisy_success.mp4)
Noisy approach, successful pickup | +| Flashlight | [Smooth flashlight pickup](media/g1_real_eval/videos/mixed_pickup_flashlight_01_smooth_success.mp4)
Smooth pickup | [Flashlight pickup from a 27-inch table placement](media/g1_real_eval/videos/mixed_pickup_flashlight_02_pickup_success.mp4)
Picks up the flashlight | +| Fruit | [Fruit pickup from a 24-inch table placement](media/g1_real_eval/videos/mixed_pickup_fruit_01_pickup_success.mp4)
Picks up the fruit | [Fruit grasp, drop, and regrasp success](media/g1_real_eval/videos/mixed_pickup_fruit_02_regrasp_success.mp4)
Grasps, drops, and regrasps | +| Sock | [Sock top-down grasp success](media/g1_real_eval/videos/mixed_pickup_sock_01_top_grasp_success.mp4)
Top-down grasp succeeds | [Sock grasp, drop, and regrasp success](media/g1_real_eval/videos/mixed_pickup_sock_02_regrasp_success.mp4)
Drops once, then regrasps | + +### Soda Can From Small Table To Trash Can + +| Task | Example 1 | Example 2 | Example 3 | +| --- | --- | --- | --- | +| Soda can to trash | [Soda can picked up and dropped into the trash can in one smooth sequence](media/g1_real_eval/videos/soda_can_table_trash_01_smooth_success.mp4)
Smooth full sequence | [Soda can succeeds after a second grasp and second trigger step](media/g1_real_eval/videos/soda_can_table_trash_02_second_grasp_step_success.mp4)
Second grasp and trigger step | [Soda can picked up and dropped into the trash can without a visible retry](media/g1_real_eval/videos/soda_can_table_trash_03_clean_success.mp4)
Single-attempt full sequence | + +## Data Collection Experience + +We followed the [GR00T Whole-Body Control data collection tutorial](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/data_collection.html) to collect G1 whole-body manipulation datasets. + +Training a good policy depends on both collecting high-quality data and configuring training properly. Each demonstration should ideally complete the task on the first attempt, without corrective motions such as re-grasping after a failed grasp or redoing a missed stepping trigger. For the mixed object pickup policy, we trained for 60k iterations at batch size 256 on roughly 18k episodes covering about 50 different objects; for the soda-can-to-trash policy, we trained for 20k iterations at batch size 32 on roughly 150 episodes of this single task. + +### Notes + +1. The mixed pickup result uses one policy trained from a combined object dataset and evaluated across multiple table-top objects. +2. For the pickup task, we used an in-house UMI gripper design. Similar tasks may require users to build task-appropriate gripper designs for their own hardware setup. + +## Data-Train-Eval Workflow + +This benchmark used the public GR00T N1.7 and GR00T Whole-Body Control workflow: + +1. Collect G1 demonstrations with SONIC teleoperation. +2. Fine-tune GR00T N1.7 with `UNITREE_G1_SONIC`. +3. Run the GR00T policy server and the SONIC robot-side controller. +4. Evaluate in closed loop on the real robot with video recording. + +Fine-tuning used the SONIC embodiment tag: + +```bash +bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path /path/to/your/lerobot_dataset \ + --embodiment-tag UNITREE_G1_SONIC \ + --output-dir /path/to/output_checkpoint \ + --experiment-name g1-sonic-task +``` + +Closed-loop evaluation used a GR00T policy server: + +```bash +python gr00t/eval/run_gr00t_server.py \ + --model-path /path/to/output_checkpoint/checkpoint- \ + --embodiment-tag UNITREE_G1_SONIC \ + --device cuda:0 \ + --host 0.0.0.0 \ + --port 5550 +``` + +The robot-side controller follows the GR00T Whole-Body Control VLA inference workflow. + +### Notes + +- The data format should be LeRobot V2 already and ready to train the model. +- It would be beneficial to check open-loop robot joint trajectory matching against training set/validation set before deploying on real robot. +- As suggested in Data Collection Experience, data quality is preferred than quantity during post-training. + +## References + +- [NVIDIA Isaac GR00T](https://github.com/NVIDIA/Isaac-GR00T) +- [SONIC paper](https://nvlabs.github.io/GEAR-SONIC/static/pdf/sonic_paper.pdf) +- [GR00T Whole-Body Control documentation](https://nvlabs.github.io/GR00T-WholeBodyControl/) +- [GEAR-SONIC project page](https://nvlabs.github.io/GEAR-SONIC/) +- [GR00T data preparation guide](../../getting_started/data_preparation.md) +- [GR00T policy server/client guide](../../getting_started/policy.md) diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_apple_01_retry_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_apple_01_retry_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f6da6db912f3ff776620614a871adb5cda5f2086 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_apple_01_retry_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_apple_02_adjust_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_apple_02_adjust_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..caf56915de2887c6198d0f20a955b35925dda363 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_apple_02_adjust_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_flashlight_01_smooth_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_flashlight_01_smooth_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7fbfd229c987302767e8973dd0d89827e2f0b9bf Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_flashlight_01_smooth_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_flashlight_02_pickup_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_flashlight_02_pickup_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f876346b95b736a05554d6c0fc5ada59d661294c Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_flashlight_02_pickup_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_fruit_01_pickup_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_fruit_01_pickup_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e7c3dd63b961882d7cb22fe517cc2c207010c77c Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_fruit_01_pickup_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_fruit_02_regrasp_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_fruit_02_regrasp_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4c1c0bb7de0d0db93a2893a36e19de037b4d0ad7 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_fruit_02_regrasp_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_lamp_01_pickup_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_lamp_01_pickup_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5d35e82b5e2af388b536a967631ba592293504bb Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_lamp_01_pickup_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_lamp_02_base_grasp_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_lamp_02_base_grasp_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d4aa617197e8b83610edfbf96a7dee7fea951d4d Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_lamp_02_base_grasp_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_scoop_01_pickup_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_scoop_01_pickup_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..de4bdda4f328afa043b054f3b306297144d72d33 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_scoop_01_pickup_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_scoop_02_noisy_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_scoop_02_noisy_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..308413e2b501331050a7010c47844e0d8a653137 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_scoop_02_noisy_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_shoe_01_many_attempts_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_shoe_01_many_attempts_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8d0444f25ca5ef011abe680d540a4cfc5023c8e0 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_shoe_01_many_attempts_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_shoe_02_regrasp_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_shoe_02_regrasp_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4a29be37aa78829ff98dfbbe005b3c2de47f664c Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_shoe_02_regrasp_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_sock_01_top_grasp_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_sock_01_top_grasp_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d63333af362a41523b1cd2447e9383362a0322ef Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_sock_01_top_grasp_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_sock_02_regrasp_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_sock_02_regrasp_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ebf104cd5d5887aa70717dfab42a3c45cbe27cd7 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_sock_02_regrasp_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_towel_01_pickup_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_towel_01_pickup_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e43e03a35bdf593587d87760525844f359bec168 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_towel_01_pickup_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_towel_02_regrasp_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_towel_02_regrasp_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f9050113500d65c159f440e766f0ab74ad4c4890 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/mixed_pickup_towel_02_regrasp_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_01_smooth_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_01_smooth_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e2ee2f3d380ede7060a7cc92847a1167b7b3775d Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_01_smooth_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_02_second_grasp_step_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_02_second_grasp_step_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b89208ad909a34c3ea8fcc55615b63d2673d430f Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_02_second_grasp_step_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_03_clean_success.jpg b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_03_clean_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0efeaeffb7abd3a8367fe7284ce50d040dfbffc0 Binary files /dev/null and b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/posters/soda_can_table_trash_03_clean_success.jpg differ diff --git a/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/videos/mixed_pickup_lamp_01_pickup_success.mp4 b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/videos/mixed_pickup_lamp_01_pickup_success.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..391eda02be8b6b870f53df87663178d39645aa4e --- /dev/null +++ b/Isaac-GR00T/examples/GR00TWholeBodyControl/media/g1_real_eval/videos/mixed_pickup_lamp_01_pickup_success.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75207cf68b802ede873eebfc91d7e84f7348a4fe6e05b65314d890ee1464c918 +size 2180902 diff --git a/Isaac-GR00T/examples/LIBERO/README.md b/Isaac-GR00T/examples/LIBERO/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1b992c84542b1b3a4a5e735dddf075d13850048c --- /dev/null +++ b/Isaac-GR00T/examples/LIBERO/README.md @@ -0,0 +1,194 @@ +# LIBERO + +Benchmark for studying knowledge transfer in lifelong robot learning. Includes multiple suites: **Spatial** (spatial reasoning), **Object** (object generalization), **Goal** (goal-conditioned learning), and **10 Long** (long-horizon multi-step tasks). Provides RGB images, proprioception data, and language task specifications. + +For more information, see the [official website](https://libero-project.github.io/main.html). + +--- + +# LIBERO evaluation benchmark result + +> **Note:** The full task list is attached at the end of this document. + +All four suites were finetuned with the same hyper-parameters, including +`--state-dropout-prob 0.2` (the finetune CLI default from +`gr00t/configs/finetune_config.py`). + +| Task | Success rate | max_steps | grad_accum_steps | batch_size | +|-----------|--------------------|-----------|------------------|------------| +| Spatial | 195/200 (97.65%) | 20K | 1 | 640 | +| Goal | 195/200 (97.5%) | 20K | 1 | 640 | +| Object | 197/200 (98.45%) | 20K | 1 | 640 | +| 10 (Long) | 189/200 (94.35%) | 20K | 1 | 640 | + +# Fine-tune LIBERO 10 (long) + +To reproduce our finetune results, use the following commands to setup dataset and launch finetune experiments. Please remember to set `WANDB_API_KEY` since W&B logging is on by default (`USE_WANDB=1` in `examples/finetune.sh`). If you don't have a WANDB account, prepend `USE_WANDB=0` to the launch command to disable it: + +```bash +uv run hf download \ + --repo-type dataset IPEC-COMMUNITY/libero_10_no_noops_1.0.0_lerobot \ + --local-dir examples/LIBERO/libero_10_no_noops_1.0.0_lerobot/ + +# Copy the patches and run the finetune script +cp -r examples/LIBERO/modality.json examples/LIBERO/libero_10_no_noops_1.0.0_lerobot/meta/ +``` + +Run the shared finetune launcher: +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=640 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/LIBERO/libero_10_no_noops_1.0.0_lerobot/ \ + --embodiment-tag LIBERO_PANDA \ + --output-dir /tmp/libero_10 \ + --state-dropout-prob 0.2 +``` + +# Fine-tune LIBERO goal + +```bash +uv run hf download \ + --repo-type dataset IPEC-COMMUNITY/libero_goal_no_noops_1.0.0_lerobot \ + --local-dir examples/LIBERO/libero_goal_no_noops_1.0.0_lerobot/ + +# Copy the patches and run the finetune script +cp -r examples/LIBERO/modality.json examples/LIBERO/libero_goal_no_noops_1.0.0_lerobot/meta/ +## This is a patch for one of the episode where the image seems to be corrupted. +cp examples/LIBERO/patches/episode_000082.mp4 examples/LIBERO/libero_goal_no_noops_1.0.0_lerobot/videos/chunk-000/observation.images.wrist_image/ +``` + +Run the shared finetune launcher: +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=640 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/LIBERO/libero_goal_no_noops_1.0.0_lerobot/ \ + --embodiment-tag LIBERO_PANDA \ + --output-dir /tmp/libero_goal +``` + +# Fine-tune LIBERO object + +```bash +uv run hf download \ + --repo-type dataset IPEC-COMMUNITY/libero_object_no_noops_1.0.0_lerobot \ + --local-dir examples/LIBERO/libero_object_no_noops_1.0.0_lerobot/ + +# Copy the patches and run the finetune script +cp -r examples/LIBERO/modality.json examples/LIBERO/libero_object_no_noops_1.0.0_lerobot/meta/ +``` + +Run the shared finetune launcher: +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=640 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/LIBERO/libero_object_no_noops_1.0.0_lerobot/ \ + --embodiment-tag LIBERO_PANDA \ + --output-dir /tmp/libero_object +``` + +# Fine-tune LIBERO spatial + +```bash +uv run hf download \ + --repo-type dataset IPEC-COMMUNITY/libero_spatial_no_noops_1.0.0_lerobot \ + --local-dir examples/LIBERO/libero_spatial_no_noops_1.0.0_lerobot/ + +# Copy the patches and run the finetune script +cp -r examples/LIBERO/modality.json examples/LIBERO/libero_spatial_no_noops_1.0.0_lerobot/meta/ +``` + +Run the shared finetune launcher: +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=640 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/LIBERO/libero_spatial_no_noops_1.0.0_lerobot/ \ + --embodiment-tag LIBERO_PANDA \ + --output-dir /tmp/libero_spatial +``` + +# Evaluate checkpoint + +First, complete the [one-time simulation environment setup](../../README.md#one-time-simulation-environment-setup), then run this benchmark's setup script (only needed once per benchmark): + +```bash +bash gr00t/eval/sim/LIBERO/setup_libero.sh +``` + +Then, download the finetuned model to a local directory (HuggingFace does not support nested repo paths directly): +```bash +uv run hf download nvidia/GR00T-N1.7-LIBERO --include "libero_10/config.json" "libero_10/embodiment_id.json" "libero_10/model-*.safetensors" "libero_10/model.safetensors.index.json" "libero_10/processor_config.json" "libero_10/statistics.json" --local-dir checkpoints/GR00T-N1.7-LIBERO +``` + +Run client server evaluation under the project root directory in separate terminals: + +**Terminal 1 - Server:** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path checkpoints/GR00T-N1.7-LIBERO/libero_10 \ + --embodiment-tag LIBERO_PANDA \ + --use-sim-policy-wrapper +``` + +> **Note:** Replace `checkpoints/GR00T-N1.7-LIBERO/libero_10` with your own checkpoint path (e.g., `/tmp/libero_10/checkpoint-20000/`) if evaluating a locally finetuned model. + +**Terminal 2 - Client:** +```bash +gr00t/eval/sim/LIBERO/libero_uv/.venv/bin/python gr00t/eval/rollout_policy.py \ + --n-episodes 10 \ + --policy-client-host 127.0.0.1 \ + --policy-client-port 5555 \ + --max-episode-steps 720 \ + --env-name libero_sim/KITCHEN_SCENE3_turn_on_the_stove_and_put_the_moka_pot_on_it \ + --n-action-steps 8 \ + --n-envs 5 +``` + +# Full task list + +## Libero 10 (Long) +- `libero_sim/LIVING_ROOM_SCENE2_put_both_the_alphabet_soup_and_the_tomato_sauce_in_the_basket` +- `libero_sim/LIVING_ROOM_SCENE2_put_both_the_cream_cheese_box_and_the_butter_in_the_basket` +- `libero_sim/KITCHEN_SCENE3_turn_on_the_stove_and_put_the_moka_pot_on_it` +- `libero_sim/KITCHEN_SCENE4_put_the_black_bowl_in_the_bottom_drawer_of_the_cabinet_and_close_it` +- `libero_sim/LIVING_ROOM_SCENE5_put_the_white_mug_on_the_left_plate_and_put_the_yellow_and_white_mug_on_the_right_plate` +- `libero_sim/STUDY_SCENE1_pick_up_the_book_and_place_it_in_the_back_compartment_of_the_caddy` +- `libero_sim/LIVING_ROOM_SCENE6_put_the_white_mug_on_the_plate_and_put_the_chocolate_pudding_to_the_right_of_the_plate` +- `libero_sim/LIVING_ROOM_SCENE1_put_both_the_alphabet_soup_and_the_cream_cheese_box_in_the_basket` +- `libero_sim/KITCHEN_SCENE8_put_both_moka_pots_on_the_stove` +- `libero_sim/KITCHEN_SCENE6_put_the_yellow_and_white_mug_in_the_microwave_and_close_it` + +## Libero Goal +- `libero_sim/open_the_middle_drawer_of_the_cabinet` +- `libero_sim/put_the_bowl_on_the_stove` +- `libero_sim/put_the_wine_bottle_on_top_of_the_cabinet` +- `libero_sim/open_the_top_drawer_and_put_the_bowl_inside` +- `libero_sim/put_the_bowl_on_top_of_the_cabinet` +- `libero_sim/push_the_plate_to_the_front_of_the_stove` +- `libero_sim/put_the_cream_cheese_in_the_bowl` +- `libero_sim/turn_on_the_stove` +- `libero_sim/put_the_bowl_on_the_plate` +- `libero_sim/put_the_wine_bottle_on_the_rack` + +## Libero Object +- `libero_sim/pick_up_the_alphabet_soup_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_cream_cheese_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_salad_dressing_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_bbq_sauce_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_ketchup_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_tomato_sauce_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_butter_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_milk_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_chocolate_pudding_and_place_it_in_the_basket` +- `libero_sim/pick_up_the_orange_juice_and_place_it_in_the_basket` + +## Libero Spatial +- `libero_sim/pick_up_the_black_bowl_between_the_plate_and_the_ramekin_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_next_to_the_ramekin_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_from_table_center_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_on_the_cookie_box_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_in_the_top_drawer_of_the_wooden_cabinet_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_on_the_ramekin_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_next_to_the_cookie_box_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_on_the_stove_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_next_to_the_plate_and_place_it_on_the_plate` +- `libero_sim/pick_up_the_black_bowl_on_the_wooden_cabinet_and_place_it_on_the_plate` \ No newline at end of file diff --git a/Isaac-GR00T/examples/LIBERO/modality.json b/Isaac-GR00T/examples/LIBERO/modality.json new file mode 100644 index 0000000000000000000000000000000000000000..a54063ee5fc391aaf6d4865cd6fcd8dedb5ed83b --- /dev/null +++ b/Isaac-GR00T/examples/LIBERO/modality.json @@ -0,0 +1,75 @@ +{ + "state": { + "x": { + "start": 0, + "end": 1 + }, + "y": { + "start": 1, + "end": 2 + }, + "z": { + "start": 2, + "end": 3 + }, + "roll": { + "start": 3, + "end": 4 + }, + "pitch": { + "start": 4, + "end": 5 + }, + "yaw": { + "start": 5, + "end": 6 + }, + "gripper": { + "start": 6, + "end": 8 + } + }, + "action": { + "x": { + "start": 0, + "end": 1 + }, + "y": { + "start": 1, + "end": 2 + }, + "z": { + "start": 2, + "end": 3 + }, + "roll": { + "start": 3, + "end": 4 + }, + "pitch": { + "start": 4, + "end": 5 + }, + "yaw": { + "start": 5, + "end": 6 + }, + "gripper": { + "start": 6, + "end": 7 + } + }, + "video": { + "image": { + "original_key": "observation.images.image" + }, + "wrist_image": { + "original_key": "observation.images.wrist_image" + } + }, + "annotation": { + "human.action.task_description": { + "original_key": "task_index" + } + } +} diff --git a/Isaac-GR00T/examples/RoboLab/README.md b/Isaac-GR00T/examples/RoboLab/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ee6467d4efc9d730e443391a6e702f83cd32e442 --- /dev/null +++ b/Isaac-GR00T/examples/RoboLab/README.md @@ -0,0 +1,276 @@ +# GR00T N1.7 on RoboLab + +This guide shows the validated path for running the finetuned GR00T N1.7 DROID checkpoint on RoboLab tasks through the GR00T policy server. + +## Why the DROID Checkpoint + +RoboLab directly uses the DROID checkpoint published with the GR00T N1.7 General Availability (GA) release, without any RoboLab-specific finetuning. + +## Validation Snapshot + +The current release baseline uses the public GR00T N1.7 DROID checkpoint and RoboLab's built-in GR00T client: + +- GR00T model: `nvidia/GR00T-N1.7-DROID` +- Embodiment tag: `OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT` +- RoboLab execution horizon: `--open-loop-horizon 8` +- Diffusion inference timesteps: model/release default, 4 denoising steps +- Episodes: 40 per task, 120 tasks + +| Setup | Tasks | Episodes | Successes | Success rate | +| --- | ---: | ---: | ---: | ---: | +| GR00T N1.7 DROID + RoboLab ([client](https://github.com/NVlabs/RoboLab/tree/main/policies/gr00t)) | 120 | 4,800 | 412 | 8.58% | +| N1.6 reference ([branch](https://github.com/nadunRanawaka1/Isaac-GR00T-n16-droid)) | 120 | 1,200 | 87 | 7.25% | + +`--open-loop-horizon 8` is part of the reproduced result. It controls how many rows from each predicted action chunk RoboLab executes before querying the GR00T server again. It is separate from the model checkpoint action horizon. + +## Successful Tasks + +The N1.7 full-suite wins are concentrated in visually clear pick/place and short-horizon manipulation tasks: + +| Task | Successes | +| --- | ---: | +| `BananaOnPlateTask` | 40/40 | +| `BananasInBinThreeTotalTask` | 38/40 | +| `UnstackRubiksCubeTask` | 38/40 | +| `SauceBottlesCrateTask` | 33/40 | +| `RubiksCubeOrBananaTask` | 32/40 | +| `BananaInBowlTask` | 31/40 | +| `BananasInBinOneMoreTask` | 31/40 | +| `RubiksCubeTask` | 25/40 | +| `RubiksCubeThenBananaTask` | 19/40 | +| `BananasInCrateTask` | 18/40 | +| `FoodPacking1CansTask` | 16/40 | +| `RedDishesInBinTask` | 15/40 | +| `TakeMeasuringSpoonOutTask` | 12/40 | + +Failures are more common on cluttered scenes, long-horizon packing, precise shelf placement, and sequential tasks that need recovery after a poor grasp. + +## Video Showcases + +The final full-suite run used `--video-mode none`, so the success-rate table above is the authoritative quantitative result but not the source of MP4s. The videos below are all unique task families with at least one confirmed successful trial in the recovered diagnostic video runs. Some high-success tasks from the final table are not shown because their video shards were not recoverable. + +Click any preview image to open the corresponding MP4. + +| Task | Demo | +| --- | --- | +| Rubik's Cube in Bowl | [Rubik's cube is picked and placed into the bowl](media/robolab/videos/robolab_rubiks_cube_success.mp4)
Fast single-object grasp and bowl placement. | +| Unstack Rubik's Cubes | [Rubik's cube tower is unstacked](media/robolab/videos/robolab_unstack_rubiks_cube_success.mp4)
Short-horizon unstacking behavior. | +| Sauce Bottle to Crate | [Red sauce bottle is moved into the crate](media/robolab/videos/robolab_sauce_bottle_crate_success.mp4)
Bottle grasp and placement into a constrained crate. | +| Rubik's Cube and Banana | [Rubik's cube and banana are placed into the bowl](media/robolab/videos/robolab_rubiks_cube_and_banana_success.mp4)
Two-object bowl placement. | +| Rubik's Cube then Banana | [Rubik's cube and banana are placed into the bowl in sequence](media/robolab/videos/robolab_rubiks_cube_then_banana_success.mp4)
Sequential cube-and-banana bowl placement. | +| Red Dishware to Bin | [Red dishware is moved into the grey bin](media/robolab/videos/robolab_red_dishes_bin_success.mp4)
Color-conditioned dishware sorting. | +| Measuring Spoon Out | [Measuring spoon is taken out of the bowl and placed on the table](media/robolab/videos/robolab_take_measuring_spoon_out_success.mp4)
Extracts the measuring spoon from the bowl and places it on the table. | +| Butter on Raisin Box | [Butter box is placed on top of the raisin box](media/robolab/videos/robolab_butter_above_raisin_success.mp4)
Places one boxed object on top of another. | +| Mustard on Raisin Box | [Mustard bottle is placed on top of the raisin box](media/robolab/videos/robolab_mustard_above_raisin_success.mp4)
Longer placement sequence with a tall object. | +| Plastic Bottles to Pail | [Small plastic bottles are placed into the square pail](media/robolab/videos/robolab_plastic_bottles_square_pail_success.mp4)
Multi-object pail placement. | +| Bowl to Shelf | [Serving bowl is placed on the shelf](media/robolab/videos/robolab_put_bowl_on_shelf_success.mp4)
Places a bowl onto the shelf. | + +## N1.6 Reference + +The N1.6 comparison used the RoboLab author's N1.6 DROID branch: + +- Code reference: [`nadunRanawaka1/Isaac-GR00T-n16-droid`](https://github.com/nadunRanawaka1/Isaac-GR00T-n16-droid) +- Model: [`nvidia/GR00T-N1.6-DROID`](https://huggingface.co/nvidia/GR00T-N1.6-DROID) +- Embodiment: `OXE_DROID` / `oxe_droid:16` +- Dashboard reference: `87/1200 = 7.25%` +- Local reproduction: `94/1200 = 7.83%` + +The N1.6 runs used 10 trials per task. The N1.7 release run above used 40 trials per task, so compare success rates rather than raw success counts. + +## Reproduction Steps + +### Parameters + +| Setting | Value | +| --- | --- | +| Model | `nvidia/GR00T-N1.7-DROID` | +| Embodiment tag | `OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT` | +| GR00T server wrapper | `--use-sim-policy-wrapper` | +| Inference timesteps | Release default, 4, tried 8, giving similar result | +| RoboLab execution horizon | `--open-loop-horizon 8` | +| Observation cameras | left exterior + left wrist | +| Image transport | HWC `uint8`, no letterbox or black padding, `180x320` | + +### Install + +Set up Isaac-GR00T and RoboLab in separate environments. First, install Isaac-GR00T for the policy server. See the main [environment setup guide](../../README.md#set-up-the-environment) for platform-specific system requirements: + +```bash +git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T.git +cd Isaac-GR00T +curl -LsSf https://astral.sh/uv/install.sh | sh +uv sync --python 3.12 +``` + +GR00T N1.7 requires access to the gated [`nvidia/Cosmos-Reason2-2B`](https://huggingface.co/nvidia/Cosmos-Reason2-2B) backbone. Request access on the model page, then authenticate: + +```bash +uv run huggingface-cli login +``` + +In a separate terminal, install RoboLab for the simulation client. RoboLab's `uv sync` installs Isaac Sim, Isaac Lab, and the GR00T client dependencies: + +```bash +git clone https://github.com/NVlabs/RoboLab.git +cd RoboLab +sudo apt install ffmpeg +uv venv --python 3.11 +source .venv/bin/activate +uv sync +``` + +RoboLab should provide the GR00T runner: + +```bash +uv run python policies/gr00t/run.py --help +``` + +### Start GR00T + +Start one GR00T server: + +```bash +cd Isaac-GR00T + +CUDA_VISIBLE_DEVICES=0 uv run python gr00t/eval/run_gr00t_server.py \ + --model-path nvidia/GR00T-N1.7-DROID \ + --embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \ + --device cuda \ + --host 127.0.0.1 \ + --port 5555 \ + --use-sim-policy-wrapper +``` + +The server is ready when it prints: + +```text +Server is ready and listening on tcp://127.0.0.1:5555 +``` + +The command above assumes the server and client run on the same host. For a separate server host, bind the server to an appropriate private interface, pass its reachable hostname to RoboLab's `--remote-host`, and restrict port `5555` to the intended network boundary. + +### Run RoboLab + +Isaac Sim checks EULA acceptance when the process starts. Export the variable in every new terminal before launching RoboLab: + +```bash +export OMNI_KIT_ACCEPT_EULA=Y +``` + +To avoid repeating this command, persist it in your shell startup file (for example, `~/.bashrc`) or environment launcher. + +Run a smoke test first: + +```bash +cd RoboLab + +CUDA_VISIBLE_DEVICES=0 uv run python policies/gr00t/run.py \ + --headless \ + --remote-host 127.0.0.1 \ + --remote-port 5555 \ + --task BananaOnPlateTask \ + --num-envs 10 \ + --num-runs 1 \ + --open-loop-horizon 8 \ + --instruction-type default \ + --video-mode none +``` + +For a more stable estimate, use the largest `--num-envs` that fits GPU memory: + +```bash +CUDA_VISIBLE_DEVICES=0 uv run python policies/gr00t/run.py \ + --headless \ + --remote-host 127.0.0.1 \ + --remote-port 5555 \ + --task BananaOnPlateTask \ + --num-envs 40 \ + --num-runs 1 \ + --open-loop-horizon 8 \ + --instruction-type default \ + --video-mode none +``` + +Useful setup-smoke tasks: + +- `BananaOnPlateTask` +- `BananaInBowlTask` +- `BananasInBinThreeTotalTask` +- `UnstackRubiksCubeTask` +- `SauceBottlesCrateTask` + +### Example 4-GPU Layout + +For faster evaluation on a 4-GPU node, run two GR00T servers and two RoboLab workers: + +| GPU | Process | +| --- | --- | +| 0 | GR00T server A | +| 1 | GR00T server B | +| 2 | RoboLab eval worker A | +| 3 | RoboLab eval worker B | + +Each RoboLab worker should point to a different server port and receive a disjoint task shard. Keep the same model, embodiment tag, horizon, camera, image, and video settings across shards. + +The GR00T server and Robolab client can also share a GPU, with smaller `--num-envs` parallel environments. + +## RoboLab Observation Contract + +The N1.7 DROID client sends this request shape to the policy server: + +| Group | Key | Shape | Dtype | +| --- | --- | --- | --- | +| Video | `video.exterior_image_1_left` | `[B, T, H, W, 3]` | `uint8` | +| Video | `video.wrist_image_left` | `[B, T, H, W, 3]` | `uint8` | +| State | `state.eef_9d` | `[B, T, 9]` | `float32` | +| State | `state.joint_position` | `[B, T, 7]` | `float32` | +| State | `state.gripper_position` | `[B, T, 1]` | `float32` | +| Language | `annotation.language.language_instruction` | `[B]` | string | + +Use `T=1` for the current baseline. Map RoboLab `over_shoulder_left_camera` to GR00T `exterior_image_1_left`, and RoboLab `wrist_cam` to GR00T `wrist_image_left`. + +The GR00T response contains chunked `action.joint_position` and `action.gripper_position`. Concatenate those actions and execute only the first 8 rows before querying the server again. + +## Image Handling + +Do not letterbox. Do not add black bars. + +The validated RoboLab client sends 16:9 HWC `uint8` images at `180x320`. This is only the transport size; the N1.7 processor still applies its model-side image transform after receiving the image. + +Avoid square client images unless deliberately running an ablation. Square stretching changes scene geometry, and square padding reintroduces letterbox bars. + +## Ablation Notes + +Useful checks from the validation sweep: + +| Factor | Outcome | +| --- | --- | +| 8 denoising steps instead of 4 | No meaningful full-suite improvement; roughly doubles DiT inference work. | +| Additional camera inputs | No stable improvement over left exterior + left wrist in the tested configs. | +| History frames | No stable improvement in the tested configs. | + +## Outputs And Dashboard + +For throughput sweeps, use `--video-mode none`. RoboLab still writes run summaries, task logs, HDF5 trajectories, timing, and per-task result rows. + +For inspectable diagnostic runs, use: + +```bash +--video-mode all --enable-subtask +``` + +`--video-mode all` writes both policy/sensor and viewport mp4s beside the task outputs. `--enable-subtask` populates score and failure-reason fields when task subtask tracking is available. + +The RoboLab dashboard reads an output directory containing run folders: + +```bash +robolab-dashboard --output-dir RoboLab/output --port 8080 +``` + +The dashboard uses `episode_results.jsonl` as the canonical per-episode summary and discovers mp4s, per-env logs, and HDF5 files from each task directory. + +## Troubleshooting + +If the server returns `SVD did not converge`, save the task name and server log. This is a numerical robustness issue in the action decode path, not a RoboLab installation problem. + +If RoboLab crashes before launching IsaacSim, check for duplicate argparse flags between RoboLab and IsaacLab's `AppLauncher`. diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_butter_above_raisin_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_butter_above_raisin_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..18352c161684c17212497bd2b260aaefd7b8e387 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_butter_above_raisin_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_mustard_above_raisin_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_mustard_above_raisin_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff422e89418f7bcd6197c59cc2439847ba31c117 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_mustard_above_raisin_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_plastic_bottles_square_pail_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_plastic_bottles_square_pail_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ddab7c42c182c7cbe599be30487782e2bc9cf396 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_plastic_bottles_square_pail_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_put_bowl_on_shelf_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_put_bowl_on_shelf_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff614920fb376fe648808f8a2ef0ece3f732a1b2 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_put_bowl_on_shelf_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_red_dishes_bin_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_red_dishes_bin_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..23938d71c4d9b3923dc938b45e74ca49d9d9e0ca Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_red_dishes_bin_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_and_banana_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_and_banana_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f007de45241ba97537316c80ee1b45891d0b0364 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_and_banana_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..865669d9a133ed5bbda742dace5444735e415200 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_then_banana_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_then_banana_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a21bd6ec2f2b401c2dcc6388c66c6e87bf393efa Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_rubiks_cube_then_banana_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_sauce_bottle_crate_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_sauce_bottle_crate_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..745522dbd79fcf488b49e5f03ea5e625207d3760 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_sauce_bottle_crate_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_take_measuring_spoon_out_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_take_measuring_spoon_out_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1deea836701ca5c2147cf5f3cb50c03a63c1f898 Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_take_measuring_spoon_out_success.jpg differ diff --git a/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_unstack_rubiks_cube_success.jpg b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_unstack_rubiks_cube_success.jpg new file mode 100644 index 0000000000000000000000000000000000000000..abc2d19773e9588bd69deaa228a8e49f168b38bb Binary files /dev/null and b/Isaac-GR00T/examples/RoboLab/media/robolab/posters/robolab_unstack_rubiks_cube_success.jpg differ diff --git a/Isaac-GR00T/examples/SO100/README.md b/Isaac-GR00T/examples/SO100/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4981c1d2a8a4c259de6f73e930f6961659d6d440 --- /dev/null +++ b/Isaac-GR00T/examples/SO100/README.md @@ -0,0 +1,124 @@ +# Finetuning Models for the SO100/SO101 Robot + +This guide shows how to finetune a dataset collected from the [SO101](https://huggingface.co/docs/lerobot/en/so101) robot, and evaluate the model on the real robot. + +## Setup + +Set an environment variable pointing at your local clone of this repository, then `cd` into it. Every step below references `$GR00T_REPO`, so export it in each terminal you open (or add it to your shell profile). + +```bash +export GR00T_REPO=~/Isaac-GR00T # update to match your path +cd "$GR00T_REPO" +``` + +## Dataset + +To collect the dataset via teleoperation, calibrate the robot, and determine camera indices, please refer to the official documentation in lerobot: https://huggingface.co/docs/lerobot/il_robots + +If you do not have a dataset, you can use this one as a basic test of the workflow. + +**Dataset Path:** [izuluaga/finish_sandwich](https://huggingface.co/datasets/izuluaga/finish_sandwich) + +Visualize it with this [link](https://huggingface.co/spaces/lerobot/visualize_dataset?path=%2Fizuluaga%2Ffinish_sandwich%2Fepisode_0) + +## Converting the Dataset + +1. From the repository root, run the following command to convert the dataset to the LeRobot v2 format necessary for finetuning. + +```bash +cd "$GR00T_REPO" +uv run --project scripts/lerobot_conversion \ + python scripts/lerobot_conversion/convert_v3_to_v2.py \ + --repo-id izuluaga/finish_sandwich \ + --root examples/SO100/finish_sandwich_lerobot +``` + +2. Copy the `modality.json` file for the SO100 to the root of the dataset. +```bash +cp examples/SO100/modality.json examples/SO100/finish_sandwich_lerobot/izuluaga/finish_sandwich/meta/modality.json +``` + +## Finetuning the Model + +1. Run the shared finetune launcher directly, this will use relative actions by default for all axes except the gripper. +```bash +CUDA_VISIBLE_DEVICES=0 NUM_GPUS=1 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/SO100/finish_sandwich_lerobot/izuluaga/finish_sandwich \ + --modality-config-path examples/SO100/so100_config.py \ + --embodiment-tag NEW_EMBODIMENT \ + --output-dir /tmp/so100_finetune +``` + +## Open-Loop Evaluation + +1. Evaluate the finetuned model with the following command: + +```bash +uv run python gr00t/eval/open_loop_eval.py \ + --dataset-path examples/SO100/finish_sandwich_lerobot/izuluaga/finish_sandwich/ \ + --embodiment-tag NEW_EMBODIMENT \ + --model-path /tmp/so100_finetune/checkpoint-10000 \ + --traj-ids 0 \ + --execution-horizon 16 \ + --steps 400 +``` + +2. The script saves one plot per trajectory to `/tmp/open_loop_eval/traj_.jpeg` by default (pass `--save-plot-path` to override). Open the output directory to view the results: + +```bash +xdg-open /tmp/open_loop_eval # macOS: open /tmp/open_loop_eval +``` + +### Evaluation Results + +The evaluation produces visualizations comparing predicted actions against ground truth trajectories: + +Open-loop evaluation results showing predicted vs ground truth trajectories + +To read these numbers and decide whether your fine-tune is working, see [Interpreting the Result: Is My Fine-tune Working?](../../getting_started/finetune_new_embodiment.md#interpreting-the-result-is-my-fine-tune-working). + +## Closed-Loop Evaluation + +Please refer to [eval_so100.py](../../gr00t/eval/real_robot/SO100/eval_so100.py) for how to write SO100 deployment code using Policy API. + +1. From the `gr00t/eval/real_robot/SO100` directory, set up client side dependencies: + +```bash +cd "$GR00T_REPO/gr00t/eval/real_robot/SO100" +uv sync +uv pip install --no-deps -e ../../../../ +``` + +2. Start the policy server: +```bash +cd "$GR00T_REPO" +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path /tmp/so100_finetune/checkpoint-10000 \ + --embodiment-tag NEW_EMBODIMENT +``` + +3. In a second terminal, navigate to the `gr00t/eval/real_robot/SO100` directory. +```bash +cd "$GR00T_REPO/gr00t/eval/real_robot/SO100" +``` + +4. Run the eval script as the client from the `gr00t/eval/real_robot/SO100` environment created above: +```bash +# Update these to match the address and indices assigned by your OS +ROBOT_PORT=/dev/ttyACM2 +ROBOT_ID=orange_follower +WRIST_CAM_IDX=2 +FRONT_CAM_IDX=6 +# Task specific prompt +PROMPT="finish the ham cheese olives sandwich" + +uv run --no-sync python eval_so100.py \ + --robot.type=so101_follower \ + --robot.port="$ROBOT_PORT" \ + --robot.id="$ROBOT_ID" \ + --robot.cameras="{ front: {type: opencv, index_or_path: $FRONT_CAM_IDX, width: 640, height: 480, fps: 30}, wrist: {type: opencv, index_or_path: $WRIST_CAM_IDX, width: 640, height: 480, fps: 30}}" \ + --policy_host=localhost \ + --policy_port=5555 \ + --lang_instruction="$PROMPT" +``` diff --git a/Isaac-GR00T/examples/SO100/modality.json b/Isaac-GR00T/examples/SO100/modality.json new file mode 100644 index 0000000000000000000000000000000000000000..0bd3a0883bc95db29f660aad0157bfa1c9c2ecac --- /dev/null +++ b/Isaac-GR00T/examples/SO100/modality.json @@ -0,0 +1,35 @@ +{ + "state": { + "single_arm": { + "start": 0, + "end": 5 + }, + "gripper": { + "start": 5, + "end": 6 + } + }, + "action": { + "single_arm": { + "start": 0, + "end": 5 + }, + "gripper": { + "start": 5, + "end": 6 + } + }, + "video": { + "front": { + "original_key": "observation.images.front" + }, + "wrist": { + "original_key": "observation.images.wrist" + } + }, + "annotation": { + "human.task_description": { + "original_key": "task_index" + } + } +} \ No newline at end of file diff --git a/Isaac-GR00T/examples/SO100/so100_config.py b/Isaac-GR00T/examples/SO100/so100_config.py new file mode 100644 index 0000000000000000000000000000000000000000..36b5f5c63524e5b9041bae95b2d70b3a7fff8606 --- /dev/null +++ b/Isaac-GR00T/examples/SO100/so100_config.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from gr00t.configs.data.embodiment_configs import register_modality_config +from gr00t.data.embodiment_tags import EmbodimentTag +from gr00t.data.types import ( + ActionConfig, + ActionFormat, + ActionRepresentation, + ActionType, + ModalityConfig, +) + + +so100_config = { + # Video: current frame only; keys must match "video" entries in meta/modality.json + "video": ModalityConfig( + delta_indices=[0], + modality_keys=["front", "wrist"], # front third-person view + wrist egocentric + ), + # State: current proprioceptive reading; keys must match "state" entries in meta/modality.json + "state": ModalityConfig( + delta_indices=[0], + modality_keys=[ + "single_arm", # joint positions + "gripper", # gripper state + ], + ), + # Action: 16-step prediction horizon; one ActionConfig per modality key + "action": ModalityConfig( + delta_indices=list(range(0, 16)), # predict 16 future steps + modality_keys=[ + "single_arm", + "gripper", + ], + action_configs=[ + # single_arm: RELATIVE = delta from current state (better generalization) + ActionConfig( + rep=ActionRepresentation.RELATIVE, + type=ActionType.NON_EEF, # joint-space, not end-effector + format=ActionFormat.DEFAULT, + ), + # gripper: ABSOLUTE = target position (binary open/close works better absolute) + ActionConfig( + rep=ActionRepresentation.ABSOLUTE, + type=ActionType.NON_EEF, + format=ActionFormat.DEFAULT, + ), + ], + ), + # Language: task instruction from annotation field in the dataset + "language": ModalityConfig( + delta_indices=[0], + modality_keys=["annotation.human.task_description"], + ), +} + +register_modality_config(so100_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT) diff --git a/Isaac-GR00T/examples/SimplerEnv/README.md b/Isaac-GR00T/examples/SimplerEnv/README.md new file mode 100644 index 0000000000000000000000000000000000000000..1e57622732c1be132bc780d685b3b30951dcf670 --- /dev/null +++ b/Isaac-GR00T/examples/SimplerEnv/README.md @@ -0,0 +1,176 @@ +# SimplerEnv + +Framework for evaluating real-world robot manipulation policies (RT-1, RT-1-X, Octo) in simulation. Replicates common setups like Google Robot and WidowX+Bridge, with GPU-accelerated simulations (10-15x speedup). Offers visual matching and variant aggregation evaluation methods for robust policy assessment. + +For more information, see the [official repository](https://github.com/simpler-env/SimplerEnv). + +--- + +# Benchmark results + +These values come from the default SimplerEnv evaluation runs (the per-task success rates are listed below). + +## Bridge (WidowX robot) + +Provided checkpoints: +- [nvidia/GR00T-N1.6-bridge](https://huggingface.co/nvidia/GR00T-N1.6-bridge) +- [nvidia/GR00T-N1.7-SimplerEnv-Bridge](https://huggingface.co/nvidia/GR00T-N1.7-SimplerEnv-Bridge) + +| Task | N1.6 success rate | N1.7 success rate | +| --- | ---: | ---: | +| `widowx_spoon_on_towel` | 56/101 (55.4%) | 78/100 (78.0%) | +| `widowx_carrot_on_plate` | 46/100 (46.0%) | 58/100 (58.0%) | +| `widowx_put_eggplant_in_basket` | 89/100 (89.0%) | 53/100 (53.0%) | +| `widowx_stack_cube` | 5/100 (5.0%) | 48/100 (48.0%) | +| `widowx_put_eggplant_in_sink` | 33/100 (33.0%) | 2/100 (2.0%) | +| `widowx_close_drawer` | 73/100 (73.0%) | 97/100 (97.0%) | +| `widowx_open_drawer` | 95/100 (95.0%) | 100/100 (100.0%) | +| **Average** | **56.6%** | **62.3%** | + +## Fractal (Google Robot) + +Provided checkpoints: +- [nvidia/GR00T-N1.6-fractal](https://huggingface.co/nvidia/GR00T-N1.6-fractal) +- [nvidia/GR00T-N1.7-SimplerEnv-Fractal](https://huggingface.co/nvidia/GR00T-N1.7-SimplerEnv-Fractal) + +| Task | N1.6 success rate | N1.7 success rate | +| --- | ---: | ---: | +| `google_robot_pick_coke_can` | 95/100 (95.0%) | 100/100 (100.0%) | +| `google_robot_pick_object` | 87/100 (87.0%) | 94/100 (94.0%) | +| `google_robot_move_near` | 81/100 (81.0%) | 100/100 (100.0%) | +| `google_robot_open_drawer` | 0/100 (0.0%) | 65/100 (65.0%) | +| `google_robot_close_drawer` | 44/100 (44.0%) | 69/100 (69.0%) | +| `google_robot_place_in_closed_drawer` | 5/100 (5.0%) | 7/100 (7.0%) | +| **Average** | **52.0%** | **72.5%** | + +# Fine-tune Simpler Env bridge dataset (WidowX robot) + +To reproduce our finetune results, use the following commands to setup dataset and launch finetune experiments. Please remember to set `WANDB_API_KEY` since W&B logging is on by default (`USE_WANDB=1` in `examples/finetune.sh`). If you don't have a WANDB account, prepend `USE_WANDB=0` to the launch command to disable it: + +```bash +uv run hf download \ + --repo-type dataset IPEC-COMMUNITY/bridge_orig_lerobot \ + --local-dir examples/SimplerEnv/bridge_orig_lerobot/ + +# Copy the patches and run the finetune script +cp examples/SimplerEnv/bridge_modality.json examples/SimplerEnv/bridge_orig_lerobot/meta/modality.json +``` + +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=1024 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/SimplerEnv/bridge_orig_lerobot/ \ + --embodiment-tag SIMPLER_ENV_WIDOWX \ + --output-dir /tmp/bridge_finetune \ + --state-dropout-prob 0.8 +``` + +# Fine-tune Simpler Env fractal dataset (Google robot) + +```bash +uv run hf download \ + --repo-type dataset IPEC-COMMUNITY/fractal20220817_data_lerobot \ + --local-dir examples/SimplerEnv/fractal20220817_data_lerobot/ + +# Copy the patches and run the finetune script +cp -r examples/SimplerEnv/fractal_modality.json examples/SimplerEnv/fractal20220817_data_lerobot/meta/modality.json +uv run python examples/SimplerEnv/convert_av1_to_h264.py --root examples/SimplerEnv/fractal20220817_data_lerobot --jobs 16 +``` + +```bash +NUM_GPUS=8 MAX_STEPS=20000 GLOBAL_BATCH_SIZE=1024 SAVE_STEPS=1000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path examples/SimplerEnv/fractal20220817_data_lerobot/ \ + --embodiment-tag SIMPLER_ENV_GOOGLE \ + --output-dir /tmp/fractal_finetune \ + --state-dropout-prob 0.5 +``` + +# Evaluate checkpoint + +First, complete the [one-time simulation environment setup](../../README.md#one-time-simulation-environment-setup), then run this benchmark's setup script (only needed once per benchmark): + +```bash +bash gr00t/eval/sim/SimplerEnv/setup_SimplerEnv.sh +``` + +Then, run client server evaluation under the project root directory in separate terminals: + +## Fractal (Google Robot) Evaluation + +**Terminal 1 - Server:** + +You can use either a local finetuned checkpoint path or the remote finetuned checkpoint (provided by us): + +**Option 1: Local finetuned checkpoint** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path /tmp/fractal_finetune/checkpoint-30000 \ + --embodiment-tag SIMPLER_ENV_GOOGLE \ + --use-sim-policy-wrapper +``` + +**Option 2: Remote finetuned checkpoint (directly runnable)** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path nvidia/GR00T-N1.7-SimplerEnv-Fractal \ + --embodiment-tag SIMPLER_ENV_GOOGLE \ + --use-sim-policy-wrapper +``` + +**Terminal 2 - Client:** +```bash +gr00t/eval/sim/SimplerEnv/simpler_uv/.venv/bin/python gr00t/eval/rollout_policy.py \ + --n-episodes 10 \ + --policy-client-host 127.0.0.1 \ + --policy-client-port 5555 \ + --max-episode-steps 300 \ + --env-name simpler_env_google/google_robot_pick_coke_can \ + --n-action-steps 1 \ + --n-envs 5 +``` + +## Bridge (WidowX) Evaluation + +**Terminal 1 - Server:** + +**Option 1: Local finetuned checkpoint** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path /tmp/bridge_finetune/checkpoint-30000 \ + --embodiment-tag SIMPLER_ENV_WIDOWX \ + --use-sim-policy-wrapper +``` + +**Option 2: Remote finetuned checkpoint (directly runnable)** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path nvidia/GR00T-N1.7-SimplerEnv-Bridge \ + --embodiment-tag SIMPLER_ENV_WIDOWX \ + --use-sim-policy-wrapper +``` + +**Terminal 2 - Client:** +```bash +gr00t/eval/sim/SimplerEnv/simpler_uv/.venv/bin/python gr00t/eval/rollout_policy.py \ + --n-episodes 10 \ + --policy-client-host 127.0.0.1 \ + --policy-client-port 5555 \ + --max-episode-steps 300 \ + --env-name simpler_env_widowx/widowx_spoon_on_towel \ + --n-action-steps 4 \ + --n-envs 5 +``` + +Other supported tasks are: +``` +simpler_env_google/google_robot_pick_object +simpler_env_google/google_robot_move_near +simpler_env_google/google_robot_open_drawer +... +simpler_env_widowx/widowx_spoon_on_towel +simpler_env_widowx/widowx_carrot_on_plate +simpler_env_widowx/widowx_stack_cube +``` + +you can replace the env_name with the corresponding tasks listed in the SimplerEnv fork this repo pins at `external_dependencies/SimplerEnv` (see `.gitmodules`). diff --git a/Isaac-GR00T/examples/SimplerEnv/bridge_modality.json b/Isaac-GR00T/examples/SimplerEnv/bridge_modality.json new file mode 100644 index 0000000000000000000000000000000000000000..4a10aa6e6acb4847878b30f66b1582af15e4fab2 --- /dev/null +++ b/Isaac-GR00T/examples/SimplerEnv/bridge_modality.json @@ -0,0 +1,77 @@ +{ + "state": { + "x": { + "start": 0, + "end": 1 + }, + "y": { + "start": 1, + "end": 2 + }, + "z": { + "start": 2, + "end": 3 + }, + "roll": { + "start": 3, + "end": 4 + }, + "pitch": { + "start": 4, + "end": 5 + }, + "yaw": { + "start": 5, + "end": 6 + }, + "pad": { + "start": 6, + "end": 7 + }, + "gripper": { + "start": 7, + "end": 8 + } + }, + "action": { + "x": { + "start": 0, + "end": 1 + }, + "y": { + "start": 1, + "end": 2 + }, + "z": { + "start": 2, + "end": 3 + }, + "roll": { + "start": 3, + "end": 4 + }, + "pitch": { + "start": 4, + "end": 5 + }, + "yaw": { + "start": 5, + "end": 6 + }, + "gripper": { + "start": 6, + "end": 7 + } + }, + "video": { + "image_0": { + "original_key": "observation.images.image_0" + } + }, + "annotation": { + "human.action.task_description": { + "original_key": "task_index" + }, + "human.validity": {} + } +} diff --git a/Isaac-GR00T/examples/SimplerEnv/convert_av1_to_h264.py b/Isaac-GR00T/examples/SimplerEnv/convert_av1_to_h264.py new file mode 100644 index 0000000000000000000000000000000000000000..89b80d1b969a027e65495e8b461e09d933348614 --- /dev/null +++ b/Isaac-GR00T/examples/SimplerEnv/convert_av1_to_h264.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +from concurrent.futures import ThreadPoolExecutor +import os +from pathlib import Path +import subprocess + + +VIDEO_EXTS = {".mp4", ".mov", ".mkv"} + + +def run(cmd): + return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + + +def is_av1(path: Path) -> bool: + cmd = [ + "ffprobe", + "-v", + "error", + "-select_streams", + "v:0", + "-show_entries", + "stream=codec_name", + "-of", + "default=nw=1:nk=1", + str(path), + ] + proc = run(cmd) + if proc.returncode != 0: + print(f"[ffprobe FAIL] {path}: {proc.stderr.strip()}") + return False + codec = proc.stdout.strip() + return codec in ("av01", "av1") + + +def convert_file(path: Path): + if not is_av1(path): + print(f"[SKIP] {path}") + return + + tmp = path.with_suffix(path.suffix + ".mp4") + print(f"[CONVERT] {path} -> {tmp}") + + cmd = [ + "ffmpeg", + "-y", + "-i", + str(path), + "-c:v", + "libx264", + "-qp", + "0", + "-pix_fmt", + "yuv420p", + "-c:a", + "copy", + "-vsync", + "passthrough", + "-copyts", + "-muxdelay", + "0", + "-muxpreload", + "0", + str(tmp), + ] + proc = run(cmd) + if proc.returncode != 0: + print(f"[ffmpeg FAIL] {path}: {proc.stderr.strip()}") + if tmp.exists(): + tmp.unlink() + return + + tmp.replace(path) + print(f"[DONE] {path}") + + +def find_videos(root: Path): + for dirpath, _, filenames in os.walk(root): + for name in filenames: + p = Path(dirpath) / name + if p.suffix.lower() in VIDEO_EXTS: + yield p + + +def main(): + ap = argparse.ArgumentParser( + description="Recursively convert AV1 videos to H.264 (lossless-ish) in place." + ) + ap.add_argument("root", nargs="?", default=".", help="Root directory (default: .)") + ap.add_argument( + "-j", + "--jobs", + type=int, + default=os.cpu_count() or 4, + help="Number of parallel workers (default: CPU count)", + ) + args = ap.parse_args() + + root = Path(args.root).resolve() + files = list(find_videos(root)) + print(f"Scanning {root}, found {len(files)} candidate video files") + + if not files: + return + + with ThreadPoolExecutor(max_workers=args.jobs) as ex: + for p in files: + ex.submit(convert_file, p) + + +if __name__ == "__main__": + main() diff --git a/Isaac-GR00T/examples/SimplerEnv/fractal_modality.json b/Isaac-GR00T/examples/SimplerEnv/fractal_modality.json new file mode 100644 index 0000000000000000000000000000000000000000..838de09b91951196feef4069b03174eca86e4050 --- /dev/null +++ b/Isaac-GR00T/examples/SimplerEnv/fractal_modality.json @@ -0,0 +1,77 @@ +{ + "state": { + "x": { + "start": 0, + "end": 1 + }, + "y": { + "start": 1, + "end": 2 + }, + "z": { + "start": 2, + "end": 3 + }, + "rx": { + "start": 3, + "end": 4 + }, + "ry": { + "start": 4, + "end": 5 + }, + "rz": { + "start": 5, + "end": 6 + }, + "rw": { + "start": 6, + "end": 7 + }, + "gripper": { + "start": 7, + "end": 8 + } + }, + "action": { + "x": { + "start": 0, + "end": 1 + }, + "y": { + "start": 1, + "end": 2 + }, + "z": { + "start": 2, + "end": 3 + }, + "roll": { + "start": 3, + "end": 4 + }, + "pitch": { + "start": 4, + "end": 5 + }, + "yaw": { + "start": 5, + "end": 6 + }, + "gripper": { + "start": 6, + "end": 7 + } + }, + "video": { + "image": { + "original_key": "observation.images.image" + } + }, + "annotation": { + "human.action.task_description": { + "original_key": "task_index" + }, + "human.validity": {} + } +} \ No newline at end of file diff --git a/Isaac-GR00T/examples/mask-guided-background-suppression/README.md b/Isaac-GR00T/examples/mask-guided-background-suppression/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cdc846fa80df5961185f2190e4ef7ceee0102887 --- /dev/null +++ b/Isaac-GR00T/examples/mask-guided-background-suppression/README.md @@ -0,0 +1,203 @@ +# Mask-Guided Background Suppression + +Mask-guided augmentations leverage per-frame segmentation masks to apply targeted image transformations during training. This enables **domain randomization** on specific regions (e.g., replacing backgrounds with noise, tinting foreground objects) without affecting the rest of the image. + +This feature is controlled via the `--extra-augmentation-config` argument (the finetune CLI uses tyro, so the flag is hyphenated), which accepts a JSON string specifying which mask regions to augment and how. + +--- + +## Prerequisites + +1. **Segmentation masks** must be pre-generated and stored alongside your dataset. The dataset's `info.json` must include a `mask_path` template, and `modality.json` must define a `"mask"` section mapping camera views. + +2. **Albumentations transforms** are enabled by default in N1.7 (`use_albumentations_transforms=True` in model config). No extra flag is needed. + +--- + +## Supported Augmentation Types + +### 1. Background Noise Transform + +Replaces pixels in specified mask regions with **random RGB noise**. Useful for sim-to-real transfer or preventing the model from overfitting to static backgrounds. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `target_mask_values` | `list[int]` | Mask label values to replace with noise (e.g., `[0]` for background) | +| `p` | `float` | Probability of applying the transform per frame (0.0 to 1.0) | + +### 2. Masked Region Color Transform + +Applies a **random color tint** to pixels in specified mask regions. Useful for augmenting the appearance of specific objects (e.g., tables, tools) to improve color generalization. + +| Parameter | Type | Description | +|-----------|------|-------------| +| `target_mask_values` | `list[int]` | Mask label values to apply the tint to (e.g., `[4]`, `[5]`) | +| `p` | `float` | Probability of applying the transform per frame (0.0 to 1.0) | +| `alpha_range` | `[min, max]` | Range for blending intensity between original and tint color (default: `[0.3, 1.0]`) | + +--- + +## Configuration Format + +The `--extra-augmentation-config` argument takes a JSON string with two optional keys: + +```json +{ + "background_noise_transforms": [ + {"target_mask_values": [0], "p": 0.9} + ], + "masked_region_transforms": [ + {"target_mask_values": [4], "p": 1.0, "alpha_range": [0.0, 1.0]} + ] +} +``` + +Multiple transforms of each type can be specified (e.g., different mask values with different probabilities). + +--- + +## Quick Start with Demo Data + +The included demo dataset `demo_data/cube_to_bowl_5_with_mask` contains a single episode with front and wrist camera views, along with pre-generated segmentation masks. The masks were generated using [SAM 3](https://github.com/facebookresearch/sam3) with the text prompt `"background"`, then converted so that background pixels = `0` and foreground pixels = `1` (see [Generating mask files](#generating-mask-files) below). + +### 1. Background noise only + +Replace background (mask=0) with random noise: + +```bash +uv run python test_extra_augmentation.py \ + --dataset_path ../../demo_data/cube_to_bowl_5_with_mask \ + --embodiment_tag NEW_EMBODIMENT \ + --modality_config_path so101_config.py \ + --extra_augmentation_config '{"background_noise_transforms": [{"target_mask_values": [0], "p": 1.0}]}' +``` + +### 2. Background noise + foreground color tint + +Apply both transforms together: + +```bash +uv run python test_extra_augmentation.py \ + --dataset_path ../../demo_data/cube_to_bowl_5_with_mask \ + --embodiment_tag NEW_EMBODIMENT \ + --modality_config_path so101_config.py \ + --extra_augmentation_config '{"background_noise_transforms": [{"target_mask_values": [0], "p": 1.0}], "masked_region_transforms": [{"target_mask_values": [1], "p": 1.0, "alpha_range": [0.3, 1.0]}]}' \ + --output_dir /tmp/augmentation_vis --num_frames 5 +``` + +Both commands save side-by-side comparison images (**Original | Augmented | Mask**) under `output_dir//`, with frames sampled evenly across the episode. + +### 3. Fine-tune with mask-guided augmentation + +```bash +export NUM_GPUS=8 + +torchrun --nproc_per_node=$NUM_GPUS --master_port=29500 \ + gr00t/experiment/launch_finetune.py \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path \ + --embodiment-tag \ + --num-gpus $NUM_GPUS \ + --output-dir /tmp/mask_augmentation_run \ + --save-steps 1000 \ + --save-total-limit 5 \ + --max-steps 20000 \ + --warmup-ratio 0.05 \ + --weight-decay 1e-5 \ + --learning-rate 1e-4 \ + --use-wandb \ + --global-batch-size 640 \ + --dataloader-num-workers 4 \ + --extra-augmentation-config '{"background_noise_transforms": [{"target_mask_values": [0], "p": 0.9}], "masked_region_transforms": [{"target_mask_values": [4], "p": 1.0, "alpha_range": [0, 1]}]}' +``` + +--- + +## Dataset Setup + +To use mask-guided augmentation with your own dataset, ensure: + +1. **Mask files** are stored as `.npz` files under a `masks/` directory, following the same chunk/episode structure as videos. Each `.npz` contains a single `uint8` array of shape `(num_frames, H, W)` where each pixel holds an integer semantic label (e.g., `0` = background, `1` = object A, `2` = object B). + + ``` + masks/ + └── chunk-000/ + └── observation.images.front/ + └── episode_000000_masks.npz + ``` + + See [Generating mask files](#generating-mask-files) below for how to produce these files. + +2. **`info.json`** includes a `mask_path` template: + + ```json + { + "mask_path": "masks/chunk-{episode_chunk:03d}/{mask_key}/episode_{episode_index:06d}_masks.npz" + } + ``` + +3. **`modality.json`** includes a `"mask"` section mapping view names to their original keys. The keys should match the actual camera view names in your dataset: + + ```json + { + "mask": { + "": { + "original_key": "" + } + } + } + ``` + + For example, if your dataset has `front` and `wrist` cameras: + + ```json + { + "mask": { + "front": { + "original_key": "observation.images.front" + }, + "wrist": { + "original_key": "observation.images.wrist" + } + } + } + ``` + +--- + +## Generating Mask Files + +You can generate mask files using any video segmentation model that produces per-pixel labels. The demo masks in this example were created with [SAM 3](https://github.com/facebookresearch/sam3) (see the [video predictor example](https://github.com/facebookresearch/sam3/blob/main/examples/sam3_video_predictor_example.ipynb) for SAM 3 usage). The workflow was: + +1. Run SAM 3 on each episode video with a text prompt such as `"background"`. SAM 3 returns per-frame binary masks via `propagate_in_video`. +2. Convert the binary masks into the label format expected by this pipeline (`0` = background, non-zero = foreground categories) and save as `.npz`: + +```python +import numpy as np + +# sam3_binary_masks: (num_frames, H, W) bool array from SAM 3 (True where prompt matched) +# For a "background" prompt, invert so that background=0 and foreground=1: +label_masks = (~sam3_binary_masks).astype(np.uint8) + +# For multiple prompts, merge into one label array instead: +# label_masks = np.zeros((num_frames, H, W), dtype=np.uint8) +# label_masks[prompt_0_masks] = 1 +# label_masks[prompt_1_masks] = 2 + +np.savez_compressed("episode_000000_masks.npz", label_masks) +``` + +The pipeline loads the array from the `.npz` file (it expects the key `arr_0`, which is the default for `np.savez_compressed`). A single `.npy` file containing the `(num_frames, H, W)` array also works. + +--- + +## How It Works + +The augmentation pipeline applies mask-based transforms **per-frame** before the standard augmentations (crop, resize, color jitter, etc.): + +1. For each frame, the corresponding segmentation mask is loaded. +2. `BackgroundNoiseTransform` replaces all pixels where `mask == target_value` with random RGB noise. +3. `MaskedColorTransform` blends a random color into all pixels where `mask == target_value`, controlled by `alpha_range`. +4. Standard augmentations (shared across views via replay) are then applied on top. + +This ordering ensures that mask-guided augmentations are applied independently per frame, while standard augmentations remain consistent across camera views within the same timestep. diff --git a/Isaac-GR00T/examples/mask-guided-background-suppression/so101_config.py b/Isaac-GR00T/examples/mask-guided-background-suppression/so101_config.py new file mode 100644 index 0000000000000000000000000000000000000000..64ad5974620bf27c785d63e56d05f5b6b4da06e0 --- /dev/null +++ b/Isaac-GR00T/examples/mask-guided-background-suppression/so101_config.py @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from gr00t.configs.data.embodiment_configs import register_modality_config +from gr00t.data.embodiment_tags import EmbodimentTag +from gr00t.data.types import ( + ActionConfig, + ActionFormat, + ActionRepresentation, + ActionType, + ModalityConfig, +) + + +so101_config = { + "video": ModalityConfig( + delta_indices=[0], + modality_keys=["front", "wrist"], + ), + "mask": ModalityConfig( + delta_indices=[0], + modality_keys=["front", "wrist"], + ), + "state": ModalityConfig( + delta_indices=[0], + modality_keys=["single_arm", "gripper"], + ), + "action": ModalityConfig( + delta_indices=list(range(16)), + modality_keys=["single_arm", "gripper"], + action_configs=[ + ActionConfig( + rep=ActionRepresentation.RELATIVE, + type=ActionType.NON_EEF, + format=ActionFormat.DEFAULT, + ), + ActionConfig( + rep=ActionRepresentation.ABSOLUTE, + type=ActionType.NON_EEF, + format=ActionFormat.DEFAULT, + ), + ], + ), + "language": ModalityConfig( + delta_indices=[0], + modality_keys=["annotation.human.task_description"], + ), +} + +register_modality_config(so101_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT) diff --git a/Isaac-GR00T/examples/mask-guided-background-suppression/test_extra_augmentation.py b/Isaac-GR00T/examples/mask-guided-background-suppression/test_extra_augmentation.py new file mode 100644 index 0000000000000000000000000000000000000000..43eef5f70a13491edc4608547015e4a413cacbeb --- /dev/null +++ b/Isaac-GR00T/examples/mask-guided-background-suppression/test_extra_augmentation.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Smoke test: apply extra_augmentation_config to raw frames and save comparison images.""" + +from __future__ import annotations + +import argparse +import importlib +import json +import os +from pathlib import Path +import sys + +from gr00t.configs.data.embodiment_configs import MODALITY_CONFIGS +from gr00t.data.dataset.lerobot_episode_loader import LeRobotEpisodeLoader +from gr00t.data.embodiment_tags import EmbodimentTag +from gr00t.model.gr00t_n1d7.image_augmentations import ( + apply_with_replay, + build_image_transformations_albumentations, +) +import numpy as np +from PIL import Image + + +def save_comparison(original, augmented, mask, output_path): + orig_arr = np.array(original) + aug_arr = augmented.transpose(1, 2, 0) if augmented.shape[0] == 3 else augmented + + panels = [orig_arr, aug_arr] + if mask is not None: + mask_vis = np.where(mask[..., None] > 0, 255, 0).astype(np.uint8) + mask_vis = np.broadcast_to(mask_vis, (*mask.shape[:2], 3)).copy() + if mask_vis.shape[:2] != orig_arr.shape[:2]: + mask_vis = np.array( + Image.fromarray(mask_vis).resize( + (orig_arr.shape[1], orig_arr.shape[0]), Image.NEAREST + ) + ) + panels.append(mask_vis) + + h = panels[0].shape[0] + resized = [] + for p in panels: + if p.shape[0] != h: + new_w = int(p.shape[1] * h / p.shape[0]) + p = np.array(Image.fromarray(p).resize((new_w, h), Image.BILINEAR)) + resized.append(p) + + Image.fromarray(np.concatenate(resized, axis=1)).save(output_path) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--dataset_path", required=True) + parser.add_argument("--embodiment_tag", required=True) + parser.add_argument("--modality_config_path", default=None) + parser.add_argument("--extra_augmentation_config", type=str, required=True) + parser.add_argument("--output_dir", type=str, default="/tmp/augmentation_vis") + parser.add_argument("--num_frames", type=int, default=5) + args = parser.parse_args() + + if args.modality_config_path: + path = Path(args.modality_config_path) + sys.path.append(str(path.parent)) + importlib.import_module(path.stem) + + embodiment_tag = EmbodimentTag[args.embodiment_tag].value + modality_configs = MODALITY_CONFIGS[embodiment_tag] + extra_aug_config = json.loads(args.extra_augmentation_config) + + train_transform, _ = build_image_transformations_albumentations( + image_target_size=[224, 224], + image_crop_size=[224, 224], + random_rotation_angle=0, + color_jitter_params=None, + shortest_image_edge=512, + crop_fraction=0.95, + extra_augmentation_config=extra_aug_config, + ) + + loader = LeRobotEpisodeLoader( + dataset_path=args.dataset_path, + modality_configs=modality_configs, + ) + episode_df = loader[0] + + video_cols = [c for c in episode_df.columns if c.startswith("video.")] + mask_cols = [c for c in episode_df.columns if c.startswith("mask.")] + print(f"Video columns: {video_cols}") + print(f"Mask columns: {mask_cols}") + + num_frames = min(args.num_frames, len(episode_df)) + frame_indices = np.linspace(0, len(episode_df) - 1, num_frames, dtype=int) + + os.makedirs(args.output_dir, exist_ok=True) + + for vcol in video_cols: + view_name = vcol.replace("video.", "") + mcol = f"mask.{view_name}" + has_mask = mcol in mask_cols + + view_dir = os.path.join(args.output_dir, view_name.replace(".", "_")) + os.makedirs(view_dir, exist_ok=True) + + for fidx in frame_indices: + orig_img = episode_df[vcol].iloc[fidx] + mask_arr = np.array(episode_df[mcol].iloc[fidx]) if has_mask else None + masks_list = [mask_arr] if mask_arr is not None else None + + transformed, _ = apply_with_replay(train_transform, [orig_img], masks_list) + aug_arr = transformed[0].numpy() + + out_path = os.path.join(view_dir, f"frame_{fidx:04d}.png") + save_comparison(orig_img, aug_arr, mask_arr, out_path) + print(f" Saved: {out_path}") + + print(f"\nDone! {num_frames} frames x {len(video_cols)} views saved to {args.output_dir}") + + print("\n" + "=" * 60) + print("Testing full training pipeline (processor + dataloader) ...") + print("=" * 60) + + from gr00t.configs.base_config import get_default_config + from gr00t.data.dataset.factory import DatasetFactory + from gr00t.model.gr00t_n1d7.processing_gr00t_n1d7 import Gr00tN1d7Processor + + config = get_default_config() + config = config.load_dict( + { + "data": { + "download_cache": False, + "datasets": [ + { + "dataset_paths": [args.dataset_path], + "mix_ratio": 1.0, + "embodiment_tag": embodiment_tag, + } + ], + } + } + ) + config.model.extra_augmentation_config = extra_aug_config + config.model.use_albumentations_transforms = True + + processor = Gr00tN1d7Processor( + modality_configs=config.data.modality_configs, + statistics=None, + image_crop_size=config.model.image_crop_size, + image_target_size=config.model.image_target_size, + random_rotation_angle=config.model.random_rotation_angle, + color_jitter_params=config.model.color_jitter_params, + model_name=config.model.model_name, + model_type=config.model.backbone_model_type, + formalize_language=config.model.formalize_language, + max_state_dim=config.model.max_state_dim, + max_action_dim=config.model.max_action_dim, + apply_sincos_state_encoding=config.model.apply_sincos_state_encoding, + max_action_horizon=config.model.action_horizon, + use_albumentations=config.model.use_albumentations_transforms, + extra_augmentation_config=config.model.extra_augmentation_config, + shortest_image_edge=config.model.shortest_image_edge, + crop_fraction=config.model.crop_fraction, + use_relative_action=config.model.use_relative_action, + ) + processor.train() + + dataset_factory = DatasetFactory(config=config) + train_dataset, _ = dataset_factory.build(processor=processor) + sample = next(iter(train_dataset)) + + print(f"Sample keys: {list(sample.keys())}") + print(f"VLM keys: {list(sample['vlm_content'].keys())}") + for k, v in sample.items(): + if hasattr(v, "shape"): + print(f" {k}: shape={v.shape}, dtype={v.dtype}") + print("\nPipeline test PASSED!") + + +if __name__ == "__main__": + main() diff --git a/Isaac-GR00T/examples/rebot-arm-dm/README.md b/Isaac-GR00T/examples/rebot-arm-dm/README.md new file mode 100644 index 0000000000000000000000000000000000000000..58925ef3beeabed63a98f51c0c74ad88be3cd891 --- /dev/null +++ b/Isaac-GR00T/examples/rebot-arm-dm/README.md @@ -0,0 +1,93 @@ +# Finetuning GR00T N1.7 Model for Seeed reBot Arm B601 DM + +This guide shows how to finetune dataset collected from [rebot arm b601 dm](https://www.seeedstudio.com/reBot-Arm-B601-DM-Bundle.html) robot, and evaluate the model on the real robot. + + +## Dataset + +To collect the dataset via teleoperation, please refer to the official documentation in lerobot: https://wiki.seeedstudio.com/rebot_arm_b601_dm_lerobot/#calibrate-the-robotic-arm + +The commands below use the test tube organization dataset as an example + +[youjiang97/organize_test_tube_0](https://huggingface.co/datasets/youjiang97/organize_test_tube_0) + +## Handling the dataset + +```bash +uv run --project scripts/lerobot_conversion \ + python scripts/lerobot_conversion/convert_v3_to_v2.py \ + --repo-id youjiang97/organize_test_tube_0 \ + --root +``` + +Then move the `modality.json` file to the root of the dataset. +```bash +cp examples/rebot-arm-dm/modality.json /meta/modality.json +``` + +## Finetuning + +Run the shared finetune launcher directly. The provided modality config trains the six arm joints as relative actions and the gripper as an absolute action: +```bash +CUDA_VISIBLE_DEVICES=0 NUM_GPUS=1 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path \ + --modality-config-path examples/rebot-arm-dm/rebot_config.py \ + --embodiment-tag NEW_EMBODIMENT \ + --output-dir /tmp/rebot-arm-dm_finetune +``` + +## Open-Loop Evaluation + +Evaluate the finetuned model with the following command: +```bash +uv run python gr00t/eval/open_loop_eval.py \ + --dataset-path \ + --embodiment-tag NEW_EMBODIMENT \ + --model-path /tmp/rebot-arm-dm_finetune/checkpoint-10000 \ + --traj-ids 0 \ + --action-horizon 16 \ + --steps 400 +``` + +### Evaluation Results + +The evaluation produces visualizations comparing predicted actions against ground truth trajectories: + +Open-loop evaluation results showing predicted vs ground truth trajectories + +To read these numbers and decide whether your fine-tune is working, see [Interpreting the Result: Is My Fine-tune Working?](../../getting_started/finetune_new_embodiment.md#interpreting-the-result-is-my-fine-tune-working). + +## Closed-Loop Evaluation + +Please refer to [eval_rebot_arm_dm.py](./eval_rebot_arm_dm.py) for how to write rebot arm deployment code using Policy API. + +1. set up client side deps + +```bash +cd examples/rebot-arm-dm +uv venv +source .venv/bin/activate +uv pip install -e . --verbose +uv pip install --no-deps -e ../../ +``` + +2. Start policy server from the repository root in a separate terminal: +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path /tmp/rebot-arm-dm_finetune/checkpoint-10000 \ + --embodiment-tag NEW_EMBODIMENT +``` + +3. Run the eval script as the client from the `examples/rebot-arm-dm` environment created above: +```bash +uv run python eval_rebot_arm_dm.py \ + --robot.type=seeed_b601_dm_follower \ + --robot.id=b601_dm_follower \ + --robot.port=/dev/ttyACM0 \ + --robot.can_adapter=damiao \ + --robot.cameras="{ front: {type: opencv, index_or_path: /dev/video0, width: 640, height: 480, fps: 30}, side: {type: opencv, index_or_path: /dev/video2, width: 640, height: 480, fps: 30}}" \ + --policy_host=localhost \ + --policy_port=5555 \ + --lang_instruction="organize test tube" +``` diff --git a/Isaac-GR00T/examples/rebot-arm-dm/eval_rebot_arm_dm.py b/Isaac-GR00T/examples/rebot-arm-dm/eval_rebot_arm_dm.py new file mode 100644 index 0000000000000000000000000000000000000000..9a168354cad056f7da7b7d08b151b4f1ca2041d2 --- /dev/null +++ b/Isaac-GR00T/examples/rebot-arm-dm/eval_rebot_arm_dm.py @@ -0,0 +1,254 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Seeed reBot Arm B601-DM real-robot GR00T policy evaluation. + +This entry point is intentionally standalone because the B601-DM arm has +different joints and a plugin-provided LeRobot robot class. +""" + +from dataclasses import asdict, dataclass +import importlib +import logging +from pprint import pformat +import time +from typing import Any + +import draccus +from gr00t.policy.server_client import PolicyClient +from lerobot.cameras.opencv.configuration_opencv import OpenCVCameraConfig # noqa: F401 +from lerobot.cameras.realsense.configuration_realsense import RealSenseCameraConfig # noqa: F401 +from lerobot.robots import RobotConfig, make_robot_from_config + + +try: + from lerobot.utils.import_utils import register_third_party_plugins +except ImportError: + from lerobot.utils.import_utils import ( + register_third_party_devices as register_third_party_plugins, + ) +from lerobot.utils.utils import init_logging, log_say +import numpy as np + + +for module_name in ["lerobot_robot_seeed_b601"]: + try: + importlib.import_module(module_name) + except ImportError: + pass + + +ROBOT_TYPE = "seeed_b601_dm_follower" +ROBOT_STATE_KEYS = [ + "shoulder_pan.pos", + "shoulder_lift.pos", + "elbow_flex.pos", + "wrist_flex.pos", + "wrist_yaw.pos", + "wrist_roll.pos", + "gripper.pos", +] + +# Matches B601-DM datasets with six arm joints plus one physical gripper: +# state/action.single_arm = [0:6], state/action.gripper = [6:7]. +DEFAULT_POLICY_STATE_KEYS = [ + "shoulder_pan.pos", + "shoulder_lift.pos", + "elbow_flex.pos", + "wrist_flex.pos", + "wrist_yaw.pos", + "wrist_roll.pos", + "gripper.pos", +] + +# Map the policy's 6-D single_arm output to the six B601-DM arm joints and +# the policy's gripper output to the physical gripper motor. +DEFAULT_ACTION_OUTPUT_KEYS = [ + "shoulder_pan.pos", + "shoulder_lift.pos", + "elbow_flex.pos", + "wrist_flex.pos", + "wrist_yaw.pos", + "wrist_roll.pos", + "gripper.pos", +] + +DEFAULT_CAMERA_KEYS = ["front", "side"] + + +def recursive_add_extra_dim(obs: dict) -> dict: + for key, val in obs.items(): + if isinstance(val, np.ndarray): + obs[key] = val[np.newaxis, ...] + elif isinstance(val, dict): + obs[key] = recursive_add_extra_dim(val) + else: + obs[key] = [val] + return obs + + +class RebotArmDMAdapter: + def __init__( + self, + policy_client: PolicyClient, + camera_keys: list[str] | None = None, + policy_state_keys: list[str] | None = None, + action_output_keys: list[str] | None = None, + ): + self.policy = policy_client + self.camera_keys = camera_keys or DEFAULT_CAMERA_KEYS + self.policy_state_keys = policy_state_keys or DEFAULT_POLICY_STATE_KEYS + self.action_output_keys = action_output_keys or DEFAULT_ACTION_OUTPUT_KEYS + + self._validate_keys("policy_state_keys", self.policy_state_keys) + self._validate_keys("action_output_keys", self.action_output_keys) + if len(self.policy_state_keys) < 2: + raise ValueError("policy_state_keys must include arm keys plus one gripper key") + if len(self.action_output_keys) != len(self.policy_state_keys): + raise ValueError( + "action_output_keys must have the same length as policy_state_keys " + "so policy outputs can be mapped unambiguously" + ) + + self.arm_dof = len(self.policy_state_keys) - 1 + + @staticmethod + def _validate_keys(field_name: str, keys: list[str]) -> None: + if len(keys) != len(set(keys)): + raise ValueError(f"{field_name} must not contain duplicate keys") + if not keys or keys[-1] != "gripper.pos": + raise ValueError(f"{field_name} must end with gripper.pos") + + unknown = [key for key in keys if key not in ROBOT_STATE_KEYS] + if unknown: + raise ValueError(f"{field_name} contains unsupported B601-DM keys: {unknown}") + + def obs_to_policy_inputs(self, obs: dict[str, Any]) -> dict: + missing_camera_keys = [key for key in self.camera_keys if key not in obs] + if missing_camera_keys: + raise KeyError( + f"Robot observation is missing camera keys {missing_camera_keys}. " + f"Available keys: {sorted(obs.keys())}" + ) + + missing_state_keys = [key for key in self.policy_state_keys if key not in obs] + if missing_state_keys: + raise KeyError( + f"Robot observation is missing state keys {missing_state_keys}. " + f"Available keys: {sorted(obs.keys())}" + ) + + state = np.array([obs[key] for key in self.policy_state_keys], dtype=np.float32) + model_obs = { + "video": {key: obs[key] for key in self.camera_keys}, + "state": { + "single_arm": state[: self.arm_dof], + "gripper": state[self.arm_dof : self.arm_dof + 1], + }, + "language": {"annotation.human.task_description": obs["lang"]}, + } + model_obs = recursive_add_extra_dim(model_obs) + model_obs = recursive_add_extra_dim(model_obs) + return model_obs + + def decode_action_chunk(self, chunk: dict, t: int) -> dict[str, float]: + single_arm = chunk["single_arm"][0][t] + gripper = chunk["gripper"][0][t] + if single_arm.shape[-1] != self.arm_dof: + raise ValueError( + f"Policy returned single_arm dim {single_arm.shape[-1]}, expected {self.arm_dof}. " + "Use policy_state_keys/action_output_keys that match the checkpoint modality." + ) + + full = np.concatenate([single_arm, gripper], axis=0) + return {key: float(full[i]) for i, key in enumerate(self.action_output_keys)} + + def get_action(self, obs: dict) -> list[dict[str, float]]: + model_input = self.obs_to_policy_inputs(obs) + action_chunk, info = self.policy.get_action(model_input) + any_key = next(iter(action_chunk.keys())) + horizon = action_chunk[any_key].shape[1] + return [self.decode_action_chunk(action_chunk, t) for t in range(horizon)] + + +@dataclass +class EvalConfig: + robot: RobotConfig + policy_host: str = "localhost" + policy_port: int = 5555 + action_horizon: int = 8 + lang_instruction: str = "Grab markers and place into pen holder." + camera_keys: list[str] | None = None + policy_state_keys: list[str] | None = None + action_output_keys: list[str] | None = None + play_sounds: bool = False + timeout: int = 60 + + +@draccus.wrap() +def eval(cfg: EvalConfig): + init_logging() + logging.info(pformat(asdict(cfg))) + + if cfg.robot.type != ROBOT_TYPE: + raise ValueError(f"eval_rebot_arm_dm.py only supports --robot.type={ROBOT_TYPE}") + + robot = make_robot_from_config(cfg.robot) + robot.connect() + + log_say("Initializing robot", cfg.play_sounds, blocking=True) + + policy_client = PolicyClient(host=cfg.policy_host, port=cfg.policy_port) + policy = RebotArmDMAdapter( + policy_client, + cfg.camera_keys, + cfg.policy_state_keys, + cfg.action_output_keys, + ) + + log_say( + f'Policy ready with instruction: "{cfg.lang_instruction}"', + cfg.play_sounds, + blocking=True, + ) + + try: + while True: + obs = robot.get_observation() + obs["lang"] = cfg.lang_instruction + + actions = policy.get_action(obs) + for i, action_dict in enumerate(actions[: cfg.action_horizon]): + tic = time.time() + print(f"action[{i}]: {action_dict}") + robot.send_action(action_dict) + toc = time.time() + if toc - tic < 1.0 / 30: + time.sleep(1.0 / 30 - (toc - tic)) + finally: + try: + robot.disconnect() + finally: + policy_client.close() + + +def main(): + register_third_party_plugins() + eval() + + +if __name__ == "__main__": + main() diff --git a/Isaac-GR00T/examples/rebot-arm-dm/modality.json b/Isaac-GR00T/examples/rebot-arm-dm/modality.json new file mode 100644 index 0000000000000000000000000000000000000000..50c6937d78c35c2cbcc9e1314cb511088d8fc1aa --- /dev/null +++ b/Isaac-GR00T/examples/rebot-arm-dm/modality.json @@ -0,0 +1,35 @@ +{ + "state": { + "single_arm": { + "start": 0, + "end": 6 + }, + "gripper": { + "start": 6, + "end": 7 + } + }, + "action": { + "single_arm": { + "start": 0, + "end": 6 + }, + "gripper": { + "start": 6, + "end": 7 + } + }, + "video": { + "front": { + "original_key": "observation.images.front" + }, + "side": { + "original_key": "observation.images.side" + } + }, + "annotation": { + "human.task_description": { + "original_key": "task_index" + } + } +} \ No newline at end of file diff --git a/Isaac-GR00T/examples/rebot-arm-dm/pyproject.toml b/Isaac-GR00T/examples/rebot-arm-dm/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..9d5924b9b8d71f10ac4997e1fcf6bce1657e7c6e --- /dev/null +++ b/Isaac-GR00T/examples/rebot-arm-dm/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["setuptools>=61", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "eval_rebot_arm_dm" +version = "0.1.0" +requires-python = ">=3.10" + +dependencies = [ + "draccus", + "matplotlib", + "ipython", + "msgpack==1.1.0", + "msgpack-numpy==0.4.8", + "zmq", + "transformers", + "lerobot @ git+https://github.com/Seeed-Projects/lerobot.git@0f392484458cb5ebca0310c0c4c47390a31c80ed", + "lerobot-robot-seeed-b601 @ git+https://github.com/Seeed-Projects/lerobot-robot-seeed-b601.git@5d36bef6e352ddfc4cefc40a16db02772e25655c", + "motorbridge", +] + +# Please also manually install `uv pip install --no-deps -e ../../` diff --git a/Isaac-GR00T/examples/rebot-arm-dm/rebot_config.py b/Isaac-GR00T/examples/rebot-arm-dm/rebot_config.py new file mode 100644 index 0000000000000000000000000000000000000000..27aa3b17320d3fad005e7adc2b6b6bf962f9016c --- /dev/null +++ b/Isaac-GR00T/examples/rebot-arm-dm/rebot_config.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from gr00t.configs.data.embodiment_configs import register_modality_config +from gr00t.data.embodiment_tags import EmbodimentTag +from gr00t.data.types import ( + ActionConfig, + ActionFormat, + ActionRepresentation, + ActionType, + ModalityConfig, +) + + +rebot_config = { + # Video: current frame only; keys must match "video" entries in meta/modality.json + "video": ModalityConfig( + delta_indices=[0], + modality_keys=["front", "side"], # front third-person view + side egocentric + ), + # State: current proprioceptive reading; keys must match "state" entries in meta/modality.json + "state": ModalityConfig( + delta_indices=[0], + modality_keys=[ + "single_arm", # joint positions + "gripper", # gripper state + ], + ), + # Action: 16-step prediction horizon; one ActionConfig per modality key + "action": ModalityConfig( + delta_indices=list(range(0, 16)), # predict 16 future steps + modality_keys=[ + "single_arm", + "gripper", + ], + action_configs=[ + # single_arm: RELATIVE = delta from current state (better generalization) + ActionConfig( + rep=ActionRepresentation.RELATIVE, + type=ActionType.NON_EEF, # joint-space, not end-effector + format=ActionFormat.DEFAULT, + ), + # gripper: ABSOLUTE = target position (binary open/close works better absolute) + ActionConfig( + rep=ActionRepresentation.ABSOLUTE, + type=ActionType.NON_EEF, + format=ActionFormat.DEFAULT, + ), + ], + ), + # Language: task instruction from annotation field in the dataset + "language": ModalityConfig( + delta_indices=[0], + modality_keys=["annotation.human.task_description"], + ), +} + +register_modality_config(rebot_config, embodiment_tag=EmbodimentTag.NEW_EMBODIMENT) diff --git a/Isaac-GR00T/examples/robocasa-gr1-tabletop-tasks/README.md b/Isaac-GR00T/examples/robocasa-gr1-tabletop-tasks/README.md new file mode 100644 index 0000000000000000000000000000000000000000..875ba5acfbdc0650b9d14371e300b2731220f3ba --- /dev/null +++ b/Isaac-GR00T/examples/robocasa-gr1-tabletop-tasks/README.md @@ -0,0 +1,87 @@ +# RoboCasa GR1 Tabletop Tasks + +Simulation benchmarks for GR-1 Tabletop Tasks developed for NVIDIA's GR00T N1 foundation model. Includes 24 tabletop manipulation tasks with 1,000 demonstrations each, enabling evaluation of generalist robotic policies in diverse household scenarios. + +For more information, see the [official repository](https://github.com/robocasa/robocasa-gr1-tabletop-tasks) and [research paper](https://arxiv.org/abs/2503.14734). + +--- + +# RoboCasa GR1 Tabletop Tasks evaluation benchmark result + +Checkpoint: finetuned N1.7 `ROBOCASA_GR1_TABLETOP` checkpoint + +| Task | Success rate | Trials | +| ---- | ------------ | ------ | +| `gr1_unified/PnPBottleToCabinetClose_GR1ArmsAndWaistFourierHands_Env` | 70.0% | 20 | +| `gr1_unified/PnPCanToDrawerClose_GR1ArmsAndWaistFourierHands_Env` | 70.0% | 20 | +| `gr1_unified/PnPCupToDrawerClose_GR1ArmsAndWaistFourierHands_Env` | 35.0% | 20 | +| `gr1_unified/PnPMilkToMicrowaveClose_GR1ArmsAndWaistFourierHands_Env` | 45.0% | 20 | +| `gr1_unified/PnPPotatoToMicrowaveClose_GR1ArmsAndWaistFourierHands_Env` | 40.0% | 20 | +| `gr1_unified/PnPWineToCabinetClose_GR1ArmsAndWaistFourierHands_Env` | 65.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromCuttingboardToBasketSplitA_GR1ArmsAndWaistFourierHands_Env` | 10.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromCuttingboardToCardboardboxSplitA_GR1ArmsAndWaistFourierHands_Env` | 30.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromCuttingboardToPanSplitA_GR1ArmsAndWaistFourierHands_Env` | 40.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromCuttingboardToPotSplitA_GR1ArmsAndWaistFourierHands_Env` | 45.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromCuttingboardToTieredbasketSplitA_GR1ArmsAndWaistFourierHands_Env` | 25.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlacematToBasketSplitA_GR1ArmsAndWaistFourierHands_Env` | 40.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlacematToBowlSplitA_GR1ArmsAndWaistFourierHands_Env` | 40.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlacematToPlateSplitA_GR1ArmsAndWaistFourierHands_Env` | 40.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlacematToTieredshelfSplitA_GR1ArmsAndWaistFourierHands_Env` | 18.2% | 22 | +| `gr1_unified/PosttrainPnPNovelFromPlateToBowlSplitA_GR1ArmsAndWaistFourierHands_Env` | 50.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlateToCardboardboxSplitA_GR1ArmsAndWaistFourierHands_Env` | 35.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlateToPanSplitA_GR1ArmsAndWaistFourierHands_Env` | 40.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromPlateToPlateSplitA_GR1ArmsAndWaistFourierHands_Env` | 75.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromTrayToCardboardboxSplitA_GR1ArmsAndWaistFourierHands_Env` | 60.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromTrayToPlateSplitA_GR1ArmsAndWaistFourierHands_Env` | 50.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromTrayToPotSplitA_GR1ArmsAndWaistFourierHands_Env` | 45.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromTrayToTieredbasketSplitA_GR1ArmsAndWaistFourierHands_Env` | 55.0% | 20 | +| `gr1_unified/PosttrainPnPNovelFromTrayToTieredshelfSplitA_GR1ArmsAndWaistFourierHands_Env` | 45.0% | 20 | +| **Average** | 44.5% | - | + +The average is the mean of per-task success rates. Trials are the per-task closed-loop episode counts. + +# Finetune + +To finetune from the N1.7 base model on the RoboCasa GR1 Tabletop Tasks dataset, convert the demonstrations to the GR00T LeRobot format and launch the shared finetune script: + +```bash +NUM_GPUS=8 MAX_STEPS=60000 GLOBAL_BATCH_SIZE=512 SAVE_STEPS=2000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path \ + --embodiment-tag ROBOCASA_GR1_TABLETOP \ + --output-dir /tmp/gr1_tabletop_finetune +``` + +The original N1.6 `gr1_unified` embodiment tag was retired with the N1.7 release. Use the N1.7 `ROBOCASA_GR1_TABLETOP` finetuning tag for this dataset. + +`ROBOCASA_GR1_TABLETOP` uses an 8-step action target to match the closed-loop RoboCasa GR1 evaluation setting. + +# Evaluate checkpoint + +First, complete the [one-time simulation environment setup](../../README.md#one-time-simulation-environment-setup), then run this benchmark's setup script (only needed once per benchmark): + +```bash +bash gr00t/eval/sim/robocasa-gr1-tabletop-tasks/setup_RoboCasaGR1TabletopTasks.sh +``` + +Then, run client server evaluation under the project root directory in separate terminals: + +**Terminal 1 - Server:** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path \ + --embodiment-tag ROBOCASA_GR1_TABLETOP \ + --use-sim-policy-wrapper +``` + +**Terminal 2 - Client:** +```bash +gr00t/eval/sim/robocasa-gr1-tabletop-tasks/robocasa_uv/.venv/bin/python gr00t/eval/rollout_policy.py \ + --n-episodes 10 \ + --policy-client-host 127.0.0.1 \ + --policy-client-port 5555 \ + --max-episode-steps 720 \ + --env-name gr1_unified/PnPBottleToCabinetClose_GR1ArmsAndWaistFourierHands_Env \ + --n-action-steps 8 \ + --n-envs 5 +``` diff --git a/Isaac-GR00T/examples/robocasa/README.md b/Isaac-GR00T/examples/robocasa/README.md new file mode 100644 index 0000000000000000000000000000000000000000..94209844a04b5286e7e432406e93e4ffd41a8120 --- /dev/null +++ b/Isaac-GR00T/examples/robocasa/README.md @@ -0,0 +1,130 @@ +# RoboCasa Evaluation Benchmark + +[RoboCasa](https://robocasa.ai/) is a large-scale simulation framework for training generally capable robots to perform everyday tasks, featuring realistic kitchen environments with over 2,500 3D assets and 100 diverse manipulation tasks. This evaluation benchmark uses RoboCasa with the Panda robot equipped with an Omron gripper to test household manipulation tasks including operating kitchen appliances, pick-and-place operations, and interacting with doors, drawers, and various objects. + +To run it on N1.7, finetune from the base model (`nvidia/GR00T-N1.7-3B`) using the instructions below — RoboCasa is not in the N1.7 pretrained embodiment set, so finetuning is required before evaluation. + +--- + +## Checkpoint Results + +- GR00T 1.6: [nvidia/GR00T-N1.6-3B](https://huggingface.co/nvidia/GR00T-N1.6-3B) +- GR00T 1.7: finetuned checkpoint + +| Task | GR00T 1.6 | GR00T 1.7 | +| ---- | --------- | --------- | +| `robocasa_panda_omron/CoffeeSetupMug_PandaOmron_Env` | 31.0% | 30.0% | +| `robocasa_panda_omron/CoffeeServeMug_PandaOmron_Env` | 63.5% | 85.0% | +| `robocasa_panda_omron/CoffeePressButton_PandaOmron_Env` | 98.5% | 100.0% | +| `robocasa_panda_omron/OpenSingleDoor_PandaOmron_Env` | 81.5% | 90.0% | +| `robocasa_panda_omron/OpenDoubleDoor_PandaOmron_Env` | 39.0% | 25.0% | +| `robocasa_panda_omron/CloseSingleDoor_PandaOmron_Env` | 96.0% | 95.0% | +| `robocasa_panda_omron/CloseDoubleDoor_PandaOmron_Env` | 88.5% | 80.0% | +| `robocasa_panda_omron/OpenDrawer_PandaOmron_Env` | 81.1% | 95.0% | +| `robocasa_panda_omron/CloseDrawer_PandaOmron_Env` | 100.0% | 100.0% | +| `robocasa_panda_omron/TurnOnMicrowave_PandaOmron_Env` | 91.5% | 95.0% | +| `robocasa_panda_omron/TurnOffMicrowave_PandaOmron_Env` | 96.0% | 95.0% | +| `robocasa_panda_omron/PnPCounterToCab_PandaOmron_Env` | 47.5% | 60.0% | +| `robocasa_panda_omron/PnPCabToCounter_PandaOmron_Env` | 41.0% | 65.0% | +| `robocasa_panda_omron/PnPCounterToSink_PandaOmron_Env` | 46.0% | 60.0% | +| `robocasa_panda_omron/PnPSinkToCounter_PandaOmron_Env` | 50.0% | 65.0% | +| `robocasa_panda_omron/PnPCounterToMicrowave_PandaOmron_Env` | 19.0% | 30.0% | +| `robocasa_panda_omron/PnPMicrowaveToCounter_PandaOmron_Env` | 24.5% | 19.0% | +| `robocasa_panda_omron/PnPCounterToStove_PandaOmron_Env` | 63.2% | 60.0% | +| `robocasa_panda_omron/PnPStoveToCounter_PandaOmron_Env` | 54.5% | 65.0% | +| `robocasa_panda_omron/TurnOnSinkFaucet_PandaOmron_Env` | 89.0% | 95.0% | +| `robocasa_panda_omron/TurnOffSinkFaucet_PandaOmron_Env` | 93.5% | 100.0% | +| `robocasa_panda_omron/TurnSinkSpout_PandaOmron_Env` | 87.0% | 80.0% | +| `robocasa_panda_omron/TurnOnStove_PandaOmron_Env` | 76.5% | 85.0% | +| `robocasa_panda_omron/TurnOffStove_PandaOmron_Env` | 31.0% | 25.0% | +| **Average** | 66.22% | 70.8% | + + +--- + +# Finetune + +Use the RoboCasa Panda Omron LeRobot datasets from Hugging Face, then launch the shared finetune script. These datasets already include the LeRobot metadata and statistics expected by GR00T and match the built-in N1.7 `ROBOCASA_PANDA_OMRON` finetuning tag. + +For a small local smoke-test dataset, download one task: + +```bash +uv run hf download nvidia/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim \ + --repo-type dataset \ + --include "single_panda_gripper.OpenDrawer/**" \ + --local-dir /root/.cache/g00t/datasets/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim + +DATASET_PATH=/root/.cache/g00t/datasets/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim/single_panda_gripper.OpenDrawer +uv run python scripts/repair_lerobot_metadata.py "$DATASET_PATH" \ + --embodiment-tag ROBOCASA_PANDA_OMRON +``` + +For the full benchmark training set, download the `single_panda_gripper.*` task directories and pass an `os.pathsep`-separated list of dataset directories to `--dataset-path`: + +```bash +uv run hf download nvidia/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim \ + --repo-type dataset \ + --include "single_panda_gripper.*/**" \ + --local-dir /root/.cache/g00t/datasets/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim + +DATASET_PATH=$(find /root/.cache/g00t/datasets/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim \ + -maxdepth 1 -type d -name "single_panda_gripper.*" | sort | paste -sd: -) +uv run python scripts/repair_lerobot_metadata.py "$DATASET_PATH" \ + --embodiment-tag ROBOCASA_PANDA_OMRON +``` + +```bash +NUM_GPUS=8 MAX_STEPS=60000 GLOBAL_BATCH_SIZE=512 SAVE_STEPS=2000 uv run bash examples/finetune.sh \ + --base-model-path nvidia/GR00T-N1.7-3B \ + --dataset-path "$DATASET_PATH" \ + --embodiment-tag ROBOCASA_PANDA_OMRON \ + --output-dir /tmp/robocasa_finetune +``` + +RoboCasa Panda Omron is not present in the base model checkpoint; use a checkpoint finetuned with `ROBOCASA_PANDA_OMRON` for evaluation. + +# Evaluate checkpoint + +First, complete the [one-time simulation environment setup](../../README.md#one-time-simulation-environment-setup), then run this benchmark's setup script (only needed once per benchmark): + +```bash +bash gr00t/eval/sim/robocasa/setup_RoboCasa.sh +``` + +#### Downloading RoboCasa Datasets (Optional) + +To download RoboCasa demonstration datasets, you **must** use the robocasa venv created by the setup script above (the main project venv does not have `robosuite` installed, which `robocasa` requires at import time): + +```bash +# Download human demonstration datasets +gr00t/eval/sim/robocasa/robocasa_uv/.venv/bin/python \ + external_dependencies/robocasa/robocasa/scripts/download_datasets.py --ds_types human_im + +# Download machine-generated datasets +gr00t/eval/sim/robocasa/robocasa_uv/.venv/bin/python \ + external_dependencies/robocasa/robocasa/scripts/download_datasets.py --ds_types mg +``` + +> **Note:** Running `python -m robocasa.scripts.download_datasets` from the main project environment will fail because `robocasa` depends on `robosuite`, which is only installed in the robocasa venv. + +Then, run client server evaluation under the project root directory in separate terminals: + +**Terminal 1 - Server:** +```bash +uv run python gr00t/eval/run_gr00t_server.py \ + --model-path \ + --embodiment-tag ROBOCASA_PANDA_OMRON \ + --use-sim-policy-wrapper +``` + +**Terminal 2 - Client:** +```bash +gr00t/eval/sim/robocasa/robocasa_uv/.venv/bin/python gr00t/eval/rollout_policy.py \ + --n-episodes 10 \ + --policy-client-host 127.0.0.1 \ + --policy-client-port 5555 \ + --max-episode-steps 720 \ + --env-name robocasa_panda_omron/OpenDrawer_PandaOmron_Env \ + --n-action-steps 8 \ + --n-envs 5 +``` diff --git a/Isaac-GR00T/external_dependencies/LIBERO/images/fig1.png b/Isaac-GR00T/external_dependencies/LIBERO/images/fig1.png new file mode 100644 index 0000000000000000000000000000000000000000..2a6e372b536ce9b285a42712cb80413fa7321495 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/images/fig1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0afb7dc138345b00bb8a445ae92dd480e05f10e41c63a62e443c050f7cbc854d +size 2650500 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/basin_faucet_base/visual/basin_faucet_base_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/basin_faucet_base/visual/basin_faucet_base_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..e559f3395145373a31ecc2511d6ebad97c312363 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/basin_faucet_base/visual/basin_faucet_base_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:198108aef8aa6509a7777a91e561e5631c12481582f6b624cecfb97c3139754e +size 108664 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/ceramic.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/ceramic.png new file mode 100644 index 0000000000000000000000000000000000000000..891c50a69b45e57cc9befa6f8fcc579d35552fc4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/basin_faucet/ceramic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:beef464a2aa9143ba6a25a44adcbfd1f1aff16c5969edbf08019b61025388402 +size 1442030 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/button_dark_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/button_dark_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..fee5b684002a6a3fe3601189cd272b25cc01c7cc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/button_dark_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4c9f069e1e5f976879466de9c2e158ed338f3d1fbf2a37c837abe8d432783a1 +size 156406 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/steel-scratched.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/steel-scratched.png new file mode 100644 index 0000000000000000000000000000000000000000..96c24dd05d9dd8ac7be045baf71c668582b1cd7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/steel-scratched.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e22a111d516cc84addde9b2b18353d8a6ec521b9b79ec5e9c169e2d9000d3fe +size 391216 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_base/steel-scratched.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_base/steel-scratched.png new file mode 100644 index 0000000000000000000000000000000000000000..96c24dd05d9dd8ac7be045baf71c668582b1cd7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_base/steel-scratched.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e22a111d516cc84addde9b2b18353d8a6ec521b9b79ec5e9c169e2d9000d3fe +size 391216 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/button_dark_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/button_dark_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..fee5b684002a6a3fe3601189cd272b25cc01c7cc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/button_dark_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4c9f069e1e5f976879466de9c2e158ed338f3d1fbf2a37c837abe8d432783a1 +size 156406 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/steel-scratched.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/steel-scratched.png new file mode 100644 index 0000000000000000000000000000000000000000..96c24dd05d9dd8ac7be045baf71c668582b1cd7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/flat_stove/stove_knob_button/steel-scratched.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e22a111d516cc84addde9b2b18353d8a6ec521b9b79ec5e9c169e2d9000d3fe +size 391216 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/base/dark-wood.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/base/dark-wood.png new file mode 100644 index 0000000000000000000000000000000000000000..09784cca1e9f2de13f0306189a9ad21aaa47241b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/base/dark-wood.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5da8dbf7af06ecd251840aceec25fedcfa98267041cea289b2829c982e008dc3 +size 239227 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_high/visual/drawer_high_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_high/visual/drawer_high_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..4c2e869c1b562a92641dfb7ffa3b3699e4ce19d0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_high/visual/drawer_high_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8b0b9c069a6ceab249afdecd63a5f79d45af72c1cf80a4e0685fe7e638f96c1 +size 155104 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_low/visual/drawer_low_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_low/visual/drawer_low_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..9690c9a6f52965ed6825c4ecf6545e43525e3d44 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_low/visual/drawer_low_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bc6f541d59cfc15a58d7c5ed37a7d66dcc1c7145efb6997d3cffdb3bd68ecc4 +size 155104 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_middle/visual/drawer_middle_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_middle/visual/drawer_middle_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..a48553b583633617bff03cef2530d2131023faf2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_cabinet/drawer_middle/visual/drawer_middle_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57c71536261b759a2260de5ee0c9b22d393574f3024542e6913632ad86c87865 +size 155104 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/base/visual/base_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/base/visual/base_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..321895eb9370292062b23b6a406168eff18ae6b4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/base/visual/base_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1909bc959ccd4547b036b3722d62e4b6286b1494e08f337438006ed8d95e3285 +size 410848 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/short_fridge/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal1.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal1.png new file mode 100644 index 0000000000000000000000000000000000000000..990982000adb702df9f849d5812443b85f34259c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d25fa8affbb0f579220f0cdad6ee74f875495822ee79bb5afd23d73671f6363 +size 289552 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal2.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal2.png new file mode 100644 index 0000000000000000000000000000000000000000..aa754a46d765eba08bc7c71bc465b78e27fb1e66 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/textures/metal2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70bf8f1c02841b802bcdabd734c8190f39e45cb3b4f916ddcad22335a26d5c12 +size 228486 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/white_wood.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/white_wood.png new file mode 100644 index 0000000000000000000000000000000000000000..1fcaab2ac22ebd3f04707caeb29c56a58927eb47 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/white_cabinet/white_wood.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43524d6bca8df5042d5b45d0b0e458f34ea7f2d6445d026c5b204ee32acd8bea +size 2209978 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_middle_handle/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_middle_handle/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_middle_handle/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_top_handle/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_top_handle/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/articulated_objects/wooden_cabinet/wooden_cabinet_top_handle/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/black_book_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/black_book_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..358503c8920d9045b63750a64c6199043ec47d47 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/black_book_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b743b0e878a10e579371707f3d135c6e7a80a8c307fffabfe1fea6a784830ec2 +size 186624 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/visual/black_book_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/visual/black_book_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..0bc60c6bbefe822be317f8875128f86087f92f15 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/black_book/visual/black_book_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca4a7f95bad5dee37a99c0374df132eadf5f8304770e5830f3286d730c844049 +size 773296 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/FabricLeatherBuffaloRustic001_COL_VAR1_4K.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/FabricLeatherBuffaloRustic001_COL_VAR1_4K.png new file mode 100644 index 0000000000000000000000000000000000000000..0524cd5a1f5943c6dd50a23599834ac0cb28cbac --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/FabricLeatherBuffaloRustic001_COL_VAR1_4K.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fabe46d134c4e0c7058795535df2e84a34bd5e2af83f881037a398f20629d57 +size 12825082 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/collision/coffee_table_seats_ch.stl b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/collision/coffee_table_seats_ch.stl new file mode 100644 index 0000000000000000000000000000000000000000..ac20fa71f6a3dd86da7f81d7d38adb6b5ae42bd3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/collision/coffee_table_seats_ch.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9017472a107c5e56c5222ca5212163b3156d19d10c773a717a835046d3cd81c3 +size 103284 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/visual/coffee_table_seats_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/visual/coffee_table_seats_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..04ebd13c7c5721eaa6337ffcd503ec42d0f4dc08 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/coffee_table_seats/visual/coffee_table_seats_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a206214be7f9ebb9d1a0358fffe07efbdae513e822371803480da67d4b7ae0fd +size 2073616 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/desk_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/desk_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..63056f46962891d8bb28e3cf12820c57f517ea35 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/desk_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1f228aca1dab2c88833d00d10983d3df62e64569bb61ad66865490cbd08a5c3 +size 489350 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/visual/desk_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/visual/desk_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..49d4431fe59972a7abd262c753a9a8ee0159db4c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/desk/visual/desk_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b883c91335372a5f7be2af0b83b95d2db429a5010110c8ca9739aef03d15f8f3 +size 742624 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/collision/floor_lamp_ch.stl b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/collision/floor_lamp_ch.stl new file mode 100644 index 0000000000000000000000000000000000000000..c7d7bc8d33dc0c43e59f0a86d757dad622d7e3da --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/collision/floor_lamp_ch.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47f1aa661fb6f911b3ace8b56dc2ea048a2a62b1e65a197252a2076561723191 +size 149584 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/visual/floor_lamp_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/visual/floor_lamp_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..5bd2f9e63d84a71cfc7453aeb30cb00934762d3a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/floor_lamp/visual/floor_lamp_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6de4776381809fdc2f7a6eae997a8269fb40fe09ef977e05a3e4fa1949a4e949 +size 7983160 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/steel-scratched.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/steel-scratched.png new file mode 100644 index 0000000000000000000000000000000000000000..96c24dd05d9dd8ac7be045baf71c668582b1cd7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/steel-scratched.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e22a111d516cc84addde9b2b18353d8a6ec521b9b79ec5e9c169e2d9000d3fe +size 391216 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/visual/fridge_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/visual/fridge_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..eb6469cd2597465094c0fd2bd942c11d3cfcbcfc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/fridge/visual/fridge_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:41edbedd182c3c27ffe8bc2c2808f61bc575c80bc37d717a17af71d10a04a208 +size 1395808 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/kitchen_background.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/kitchen_background.png new file mode 100644 index 0000000000000000000000000000000000000000..b10ed8c3d14c790612adcc9004af3e417f9b0bf2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/kitchen_background.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cb9379766b531eb8e6f44a1fa3df92430e0c73c6c3856a88521510e689bca15a +size 172490 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/visual/kitchen_background_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/visual/kitchen_background_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..6d5c41ef108ada1f25d2acb1eca6b2281d32e50c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background/visual/kitchen_background_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b2487166e07650ba787129919fb3c4f77bfd912fdd4e265f5bf68992175417a +size 7534528 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_hot_pot/visual/kitchen_background_hot_pot_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_hot_pot/visual/kitchen_background_hot_pot_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..40aea0d40c9751bf2d682501e5cab86818ac8ed6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_hot_pot/visual/kitchen_background_hot_pot_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05c173fb9ae96f7ed2fdccbeb14abb38e8db601f7802e9b78db04d9a5e2b0ce2 +size 845440 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/collision/kitchen_background_pot_ch.stl b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/collision/kitchen_background_pot_ch.stl new file mode 100644 index 0000000000000000000000000000000000000000..ba448f6081726252cd9b84def2b8ddc7cdb90d16 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/collision/kitchen_background_pot_ch.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:91f3a0265ed7173debf1a4fd12216f0c2edf696967d84a21ac5f36a0875df996 +size 183784 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/visual/kitchen_background_pot_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/visual/kitchen_background_pot_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..2c715822e901fdb0a9cd30c3a2ac405750e50a85 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_pot/visual/kitchen_background_pot_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3348ee8738bcaf84b6f9df6cae65d764bbc159410aea32d5d40c09dc58b69ec +size 4344316 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_stove/visual/kitchen_background_stove_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_stove/visual/kitchen_background_stove_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..c4d60daee252d336451de7a0533442599f50433a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/kitchen_background_stove/visual/kitchen_background_stove_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0efe7517df5bb76730dd0b951dcf40644e7c494005a89421229b422217998702 +size 6212608 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room/visual/living_room_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room/visual/living_room_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..7dd83070cab31c99cfd611cab8a8bf1c8269e209 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room/visual/living_room_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:326c50b18dfce7d338473ab8d99edce64c752cfef0203495faa2471dcafd4f8b +size 6514576 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/collision/living_room_table_ch.stl b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/collision/living_room_table_ch.stl new file mode 100644 index 0000000000000000000000000000000000000000..8ab2c4481b411749be6fd4ea261af686ac708828 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/collision/living_room_table_ch.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:deae447cb884f4d692e934a62a3b8ec7a30cf6746f7cd5cbb6a943d57a16dbd2 +size 232084 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/living_room_table_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/living_room_table_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..60a474267315742d93dae01ff672d171c3e5d773 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/living_room_table_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38f401fdbbdeae06bf4c674f2488ab4bda8b89519a1d58976c7265b1f7c8c1e7 +size 1331834 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/visual/living_room_table_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/visual/living_room_table_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..60828d04c1e6584316a6bd6499a5b0b3e5fc5162 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/living_room_table/visual/living_room_table_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9877f90c22971b98840ca6f8611fec6e0a8bec85f0e5f0a78e9e08bb57a8e2ec +size 1699504 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/office_book_shelf/ceramic.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/office_book_shelf/ceramic.png new file mode 100644 index 0000000000000000000000000000000000000000..891c50a69b45e57cc9befa6f8fcc579d35552fc4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/office_book_shelf/ceramic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:beef464a2aa9143ba6a25a44adcbfd1f1aff16c5969edbf08019b61025388402 +size 1442030 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/plant_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/plant_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..fedd465c790ed5e8062f361bb52a852394ad295b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/plant_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:216886be0ecd4a765b5f00fe664dd27f25d7af19caef1c2012c4cca429d66349 +size 1583401 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/visual/plant_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/visual/plant_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..9fc242e76cb87cfce54dd22e098ff3982c9ab8a7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/plant/visual/plant_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:648fed3592f88784f1dfde93387ca744b1b428ffed5d6a3a7317108b3cae45c5 +size 732472 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/short_coffee_table/Marble062_COL_4K.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/short_coffee_table/Marble062_COL_4K.png new file mode 100644 index 0000000000000000000000000000000000000000..942a4a4df42a9123e140a6038de8c0ec3a64215d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/short_coffee_table/Marble062_COL_4K.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6cc288b8006e1931f1904ae50741539e4c44c1ed67686822386c96aad013864c +size 9625750 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/study_background.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/study_background.png new file mode 100644 index 0000000000000000000000000000000000000000..6ba68597baca961e8f898cd1e1c60c5a954af1b9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/study_background.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a8ed45bfbe8aebc689cc72a1c3fba0bfd6f0847ba8a830bb1c0eac595e19252 +size 1184577 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/visual/study_background_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/visual/study_background_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..be6f2efe7d1fcad4afb1950ccdd89fec7875d9cd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_background/visual/study_background_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15f667adb66f79ad7c6fe472a51d27b33d8a2f5a9457c91488aca26e02424811 +size 777616 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_wall_painting/study_wall_painting.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_wall_painting/study_wall_painting.png new file mode 100644 index 0000000000000000000000000000000000000000..0a76965810b4adebe2a16c2443f533cab2558c53 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/study_wall_painting/study_wall_painting.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa1bf8b6658d03b9b20ff6ea0276fed8b68d50894579d43caca2a94fd246063a +size 432815 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.jpg b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2604aca4dd3121744a63b79faa520cbea7e926ca --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd6d3721066054b772ebe4829cfcbec9816690df89f83349dd262029a3ecb457 +size 1924813 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..a8cd650e6b7fa9624e1bd36bb14471089dc916ea --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/scenes/wall_decoration/wall_decoration_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b30b2b6f7499d05a4c502e3699027e14e9646023f4035b14b56f1fb55703bc3e +size 4492846 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..35dc47a6487249daa5ff892482278f243cb35646 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd47556b3b2916ae138e8fd370d4f5192a2fe100369eec254c3c173409f48674 +size 1138366 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..884ad9f2348c95070f4ac9b82740bd01ae6b9ccc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/alphabet_soup/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9f36a95f4ad97cb141f134251114d46cc4f3950229d76ac815e751cc0cf121e +size 1496788 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..be659b5c42d8e7b1d712aad058cd39ce6e59eed6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be21c2549bc0da64ec29665e3d064fcdb1d42a9f93f89eb38eecc4b08b4a3d39 +size 2089204 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/visual/bbq_sauce_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/visual/bbq_sauce_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..a865f7e4c0fd4f1613594db92d47a68a2ddbfbe4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/bbq_sauce/visual/bbq_sauce_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c2c8c6238e5b78c50fa7986a6de52f3c437a0e85cc1048760ed1f5fa868480c +size 1737736 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..252d5343a41015b9f082b953f2b87829dab879a4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e344d473644d71b919484f6b93d52707ea4821fe05c14514d7cd6cc24f2486c2 +size 3158511 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/visual/butter_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/visual/butter_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..92455c01d98533f9788b55c7b353b69cb9e0c0f6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/butter/visual/butter_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88b3916e53c813c7e06c856d7e0563e636c07247d95982c2cd05abc0ebd0cc68 +size 1554676 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..5f0ab11d5491ea3f529cf0af3007cee19904d8f6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d2db3872437523fd5fc5611728c154d475d05642c0d2a64ce60065e3c6ffc48 +size 3334239 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..7038d89f89c329105eba6aa57846ee94749ba96f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/chocolate_pudding/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34c7f14b29daa9f99daafe962866e0b4ea59d38863d04e3da1d4a7ed4e6244fd +size 1949848 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..3b8c578ccb13df3d4093bbc53e08ca8ff269ad3e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e1c4be04c8a9d60ba33ef100354c451a4b02f1bdc2fc7607708b2ff4ff82d783 +size 3248302 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/visual/cookies_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/visual/cookies_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..c07f03cc3ce6ac71cfa0a7eb67d03d2c3c54b94a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cookies/visual/cookies_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd2f87872eb6ac780525ec5bd710d690d520f7d6725b10625f8ee403115308df +size 1928248 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..6d18e1874b0fcf9c4418f3caff2429d8b36c50ec --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ef390c92c83f6f27da79df09130e48bda6785f98181942d2ec2548ab2afa814 +size 3071899 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/visual/cream_cheese_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/visual/cream_cheese_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..924eda705cb0ed0272e22e0e7f4da633d2250a8d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/cream_cheese/visual/cream_cheese_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0110fcd0351384174e70956ae83c4b30a677bc5673aa8107213b73334efbdf3b +size 1753612 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..1515bfbbd4ccd60452a6c680c5bf79a2f11167fd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01edda2f924589b0a23aac084c1270a4a39afde79131a1bec73f7a23ad592bfe +size 1898296 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..02c91ad88067aa2ae8cb2eeca4c0f4ef647d55e9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/ketchup/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52a6903d11261ef819b707241f058de28dced28746f9bbb142649a18f1d48321 +size 1677796 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..9a340bb4a1ea0c116fb68375d68f079bb464312d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3328a2d757dfeb93383340f8cee37de3d1caffebabae53f909345dd94b66b29 +size 3069741 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..099e506622b36576079a1e5a5d769c0f3cd29619 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/macaroni_and_cheese/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c40762b4af7ec0a14789da2757a0452756c35f1bfa7e3ab7cc280312d06a6c8 +size 2179240 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..f66d35d66ab7ee26896c451c81c028c5977c3688 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e6130ec7a6a611a2574bba4f3d77bfaecd8ff6ed0fd449e34fe8479f4585ec3 +size 3384036 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..113edbf4e42cec468db60f1723f3fa803f5561ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/milk/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:540a0eedb3d483e96dda195f06ce531f9991c9f07fece482f569131ab69a8036 +size 1578328 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..6996802464c5e965b75e4fd3289f4aa96f256bd7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17ac6d99eebf065eaa2243ebc578da65e7d5f112bbff75f083e451578efaae22 +size 2721594 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..6a9717ca96aa1a5fb063b9092a0dfdbdf4a8cffb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/new_salad_dressing/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11e210c93786626e66c832f1d5a0178eddf88e79775cc8e59cc060b52fc0abab +size 2117896 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..af7d6c64d7ae44e7ccb13c5d03b50c03c063bb9f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2488e5d72c7848db195be1d5a08d45a00b04122fff7ddcc107014d177d6d08c9 +size 3637784 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..2a6a1aed38de8defdc43fda02a204486034b971f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/orange_juice/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ebfebfe88f469abd9015bea348f242ee36a93829f75975535dcb44a5c3d876d +size 2152672 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..fac1dbe672b9e3f40c086e512ac3f5d5326ce23e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d2469127fcf474e20cb66d803e95f1df0cd2183cdb88815f863562f00ad8078 +size 3231298 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/visual/popcorn_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/visual/popcorn_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..3ace9313d2cefc0d09f8366011b1bf8ac533dcb0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/popcorn/visual/popcorn_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06ad7d7cec8ae493650438eecb66193e891ce36532516bf645ba7d5dd5944b2c +size 1942072 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..6996802464c5e965b75e4fd3289f4aa96f256bd7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:17ac6d99eebf065eaa2243ebc578da65e7d5f112bbff75f083e451578efaae22 +size 2721594 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..6a9717ca96aa1a5fb063b9092a0dfdbdf4a8cffb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/salad_dressing/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11e210c93786626e66c832f1d5a0178eddf88e79775cc8e59cc060b52fc0abab +size 2117896 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/texture_map.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/texture_map.png new file mode 100644 index 0000000000000000000000000000000000000000..072a7da4ec16ec7118c207b55a7397b797695972 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/texture_map.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9372cff38688004b69e7a1fc60ffa2576d6cf31a884de279d0d67bdd4a35c631 +size 2451651 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/visual/textured_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/visual/textured_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..e5e2c5532f3f8e6ceea67d851f0b1fdd5ea13d1c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_hope_objects/tomato_sauce/visual/textured_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eeb9ee401b204db5ca5b98cf8d52274695b5562ee31f0affaca58a25a07cc2e4 +size 3087520 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..31e78f0933c331b9061870d468eec6f011e37435 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a646d98b084b7400dd91beed9c83e10b4a4dca572896b3974356b7937a4bd85 +size 12751242 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/visual/akita_black_bowl_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/visual/akita_black_bowl_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..17f425fd97131944e989814b0d5164793e7d24dd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/akita_black_bowl/visual/akita_black_bowl_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6474d536a740e995c3a2eaeb74c61e14da94131b0b222c250b61b30b13d11229 +size 4592392 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basin_faucet_base/visual/basin_faucet_base_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basin_faucet_base/visual/basin_faucet_base_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..e559f3395145373a31ecc2511d6ebad97c312363 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basin_faucet_base/visual/basin_faucet_base_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:198108aef8aa6509a7777a91e561e5631c12481582f6b624cecfb97c3139754e +size 108664 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..db4b93efd313538e5fba3bc774a8900cd8ade0f5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89c2107a39ce27d7dffc383153153e021958408cd6fffd8bf8f318a0bb2c302b +size 11112400 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/visual/basket_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/visual/basket_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..ce992170cb13e3051e27dbdd0cb67fc402dc6612 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/basket/visual/basket_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51ca04e71fbca8a4fdd5fa86362867d414e401923e1cb9b0daed488513b46734 +size 7170136 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/bowl.zip b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/bowl.zip new file mode 100644 index 0000000000000000000000000000000000000000..689d3cc2f21d24ea85008f155610952920fa359e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/bowl.zip @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdbf7590b1010e7a30760c8344ec95d922b655132fb67025d6042a3681873d26 +size 4614115 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..cb195e89e0b4a00bc39e47ae88f55063bf1b8bcf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b6adc65fc2f18030a1aa0c3dde2c1719e7b74431e0e5279bea9b6416af7deb6 +size 752681 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/visual/chefmate_8_frypan_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/visual/chefmate_8_frypan_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..263277a04d34cb02cc3d15533a73c5c3d549b692 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/chefmate_8_frypan/visual/chefmate_8_frypan_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65e0483c19250107aef692fa80a8d597ef89bcf7ea28e6e9c2a4adcfa775acd2 +size 1006576 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..1c37df60d6d066ed3375af1fa532917884501b0d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7323b1d08b6242dd9127f853e23bb5b2651c8665dcb3c78ed00a632aef567750 +size 311263 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/visual/glazed_rim_porcelain_ramekin_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/visual/glazed_rim_porcelain_ramekin_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..998972f05d47af42549b63ff69326229070f1fc0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/glazed_rim_porcelain_ramekin/visual/glazed_rim_porcelain_ramekin_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ef1877c027112d27fca3e8b16e7c226fb02f52345750b8d8c8217ad0c41c5eb +size 1757608 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..4fbdeec0dfe6ddf57968afab43051f86db09b650 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b742142bf0e29a90d76c4b0254a4481e9eff4807eff3ac6c4ac67a5888fb005 +size 8660937 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/visual/model_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/visual/model_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..2ca109d9dbbe07ee85fdc03e671347c78b161765 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/plate/visual/model_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d3278b1cefb2ed496094cad18f0c66004ee65ab933122ec8d5efdc78daa96b4 +size 374128 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..5b969042e2a871bffb845c85e1100ae8f55fe209 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a850aaf925421f49a7399f6fc80444a1ab5de7b1110f4294598c5dc2231ea3fd +size 7982813 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/visual/model_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/visual/model_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..b3aa33711b56b4a8439b0af499a86ca83edf828d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/red_bowl/visual/model_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:260756fe40301b42f948d644f072eccf57b1ba57d20d3d26e5261383bdace350 +size 1515256 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/simple_rack/visual/simple_rack_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/simple_rack/visual/simple_rack_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..c5d66048c454874181f2c452c8662c4665034f41 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/simple_rack/visual/simple_rack_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3a4d5bcf3ce3718cecc51dea9e2edac068b80d4d6f58a27124f31eb408ca177f +size 188800 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/texture.png new file mode 100644 index 0000000000000000000000000000000000000000..5b969042e2a871bffb845c85e1100ae8f55fe209 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a850aaf925421f49a7399f6fc80444a1ab5de7b1110f4294598c5dc2231ea3fd +size 7982813 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/visual/model_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/visual/model_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..b3aa33711b56b4a8439b0af499a86ca83edf828d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/stable_scanned_objects/white_bowl/visual/model_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:260756fe40301b42f948d644f072eccf57b1ba57d20d3d26e5261383bdace350 +size 1515256 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/brown_ceramic_tile.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/brown_ceramic_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..6b589038c4b9bffa74de4adb1a49a881e69ff9e5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/brown_ceramic_tile.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76f19ce9c0a307a447d9c65edcf0757e405358e6d22e2a52cfa2cd6dc5c63224 +size 1192761 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/cream-plaster.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/cream-plaster.png new file mode 100644 index 0000000000000000000000000000000000000000..d77333eb1bd7d44057939b3c12c8d9a620e4a8e1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/cream-plaster.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f989033f089158b2c8f0f1f7881f6922b018a5b154558b2edcc9f41a21ab983 +size 696397 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_blue_wall.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_blue_wall.png new file mode 100644 index 0000000000000000000000000000000000000000..6fad048026dc2e06eef18821ba9e80622d3c22f8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_blue_wall.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecb999e23c85dfef374feeea938c6864f8fc14ba22b8a4c1b37785812d0923c5 +size 1216412 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_floor_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_floor_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..65b06d2c0aa05fc65d16992bd8fd5eec617860ae --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_floor_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:182b1d927029d6284b5cbe3e317b111cbc5b147b692fd0f19e4181a02d08f647 +size 432717 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_gray_plaster.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_gray_plaster.png new file mode 100644 index 0000000000000000000000000000000000000000..2944a7f6357e669b14425e2cc210d9aaceee6b0a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/dark_gray_plaster.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:122ac950498a1e157ddbe54df9a585344059018e36328341d2dd4eef72f5337c +size 172397 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/gray_ceramic_tile.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/gray_ceramic_tile.png new file mode 100644 index 0000000000000000000000000000000000000000..fb458a375892b208845c4d518eb00f0487c97a32 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/gray_ceramic_tile.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93a1c2b647f31aded62b4125439e17aa1a55c8f4e77820909d9a1c235f6c7315 +size 435890 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_floor.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_floor.png new file mode 100644 index 0000000000000000000000000000000000000000..dda395ea6d71825740a514ee071e62d02ac06e66 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_floor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6e69937f87ef7d956e4434535ab2ff99939216cc03c842cd9b4ba16023b32e6 +size 868219 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_grey_plaster.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_grey_plaster.png new file mode 100644 index 0000000000000000000000000000000000000000..392374aef0a3d04e4076e3a4c9759903b32806b7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/light_grey_plaster.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7fc746d496fcaed1c716ad5fc5f8237095613e09dd80eae3e969f599cee9c06 +size 392158 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/martin_novak_wood_table.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/martin_novak_wood_table.png new file mode 100644 index 0000000000000000000000000000000000000000..a2fc4490aaf2a74614641f6bfdfc71532483d217 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/martin_novak_wood_table.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d714fbf44d4d44f279761c0ddd0b2fd7271446cdbb85fcbef8677fe5f929850 +size 940180 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/new_light_gray_plaster.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/new_light_gray_plaster.png new file mode 100644 index 0000000000000000000000000000000000000000..7b11226f118e00cdd5a5183a188730724c45c431 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/new_light_gray_plaster.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a51d3ac1fc9991c1530eefdf7922aefdbd18f4cb1fd08ca0ee81e74b586defd +size 1457824 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/seamless_wood_planks_floor.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/seamless_wood_planks_floor.png new file mode 100644 index 0000000000000000000000000000000000000000..54804e77cf0f2147cd75ab169cd4dc6293a5bfbe --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/seamless_wood_planks_floor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7a70ef3fad0cafc1d196e49f9ff1b483d0a5e62ed457b108a9c9b2c9ed1dd13 +size 3174441 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/smooth_light_gray_plaster.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/smooth_light_gray_plaster.png new file mode 100644 index 0000000000000000000000000000000000000000..8553f5e438ccf68cfe9ce9300ce8c94712ba1e8f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/smooth_light_gray_plaster.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0bdaf13b44ab6ef3122451f6b3853e40bdf20bb9be7662649683ba525dfe191 +size 516639 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/white_marble_floor.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/white_marble_floor.png new file mode 100644 index 0000000000000000000000000000000000000000..a1fbee00d615b1638571bd692ecad25288b3277b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/white_marble_floor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d79fb61f545669659a6bbdfd68c750fe4fd2830e448465f223fe4c224b8d17ca +size 652993 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/yellow_linen_wall_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/yellow_linen_wall_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..47f880f92e32f0deccf8d98f7826ff9217419fdd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/textures/yellow_linen_wall_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:292d1bb3a8536b2faf73c91b9d6b11ac90c58136cbaade2af0d7b941f70904aa +size 607573 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/black_book_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/black_book_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..358503c8920d9045b63750a64c6199043ec47d47 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/black_book_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b743b0e878a10e579371707f3d135c6e7a80a8c307fffabfe1fea6a784830ec2 +size 186624 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/visual/black_book_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/visual/black_book_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..0bc60c6bbefe822be317f8875128f86087f92f15 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/black_book/visual/black_book_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca4a7f95bad5dee37a99c0374df132eadf5f8304770e5830f3286d730c844049 +size 773296 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/ceramic.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/ceramic.png new file mode 100644 index 0000000000000000000000000000000000000000..891c50a69b45e57cc9befa6f8fcc579d35552fc4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/ceramic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:beef464a2aa9143ba6a25a44adcbfd1f1aff16c5969edbf08019b61025388402 +size 1442030 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/visual/bowl_drainer_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/visual/bowl_drainer_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..3fb620e7db45e54d650dfffd7029035c9d8a950e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/bowl_drainer/visual/bowl_drainer_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05e0e419d1ba1642caf17b708091090b3acbba73964725fdde702f7f12b21146 +size 1597984 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/desk_caddy_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/desk_caddy_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..a8aab85145534e14ab08ff22f82fd687184f9feb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/desk_caddy_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea07fb85ab5ef7167040e459ae4442827d114d778aaf4f6a8229bc3898406238 +size 11230178 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/visual/desk_caddy_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/visual/desk_caddy_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..0856bbb2fca5d73a369f899496710975f3b9efac --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/desk_caddy/visual/desk_caddy_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2a31df6411aa382d91553a594faa2cb9577908c3881b9022616f9d6604333a4 +size 2696776 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/visual/dining_set_utensils_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/visual/dining_set_utensils_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..a5360acf686cf60ca1cdecbeb15fe30ec94516cc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/visual/dining_set_utensils_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3d3d44c836e908a25784e54e28c2083f4c01a45dcfa0ec69e72109356798d25 +size 262240 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/white_linen_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/white_linen_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..4a9c6276e2a4627014a59f3cdd9413a4d6bc6c22 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/dining_set_group/white_linen_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0ee137d6efc1dbac08db147f3b2c9cde59e204f429ac552267a8ca9e54917ccd +size 465048 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/metal_diff.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/metal_diff.png new file mode 100644 index 0000000000000000000000000000000000000000..c88dc71ca6c1ebacba3067d9405976a7e8528c0b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/metal_diff.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b59ae89c09579b8edcf29df79fc17090f9d9fd1ac8275a7bd3b5cabf376ffaa +size 1036822 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/rubber_black.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/rubber_black.png new file mode 100644 index 0000000000000000000000000000000000000000..ff630a6a8cac318f51d0487d5cfa01e2e8ce6bcf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/rubber_black.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8147f34af7c3e5c6b7c8496e34f848662a91d10cb55aae5bab8150eb7ff02e81 +size 492169 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/visual/moka_pot_body_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/visual/moka_pot_body_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..536d69be406ec52b515735468685d7bbcefd3edd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/moka_pot/visual/moka_pot_body_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b3009030d48d383572e7a3930ef0bbb55e16b59e9f2451a798c904dfdc227ca +size 155212 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/porcelain_mug_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/porcelain_mug_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..e4257bc6dd66ac3d27f409d9e68a6ee7ecb98c75 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/porcelain_mug_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bab4363b4e86e3352718ef1c3849a632fa06f83528bb408f4b533ceb01b3bc25 +size 7293802 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/visual/porcelain_mug_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/visual/porcelain_mug_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..977925c44d1c1df0407fc54a9fb5c898b1f2ccf9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/porcelain_mug/visual/porcelain_mug_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0dc3f0a0585d172c6ff22e49173774e37bc8a4a8e74d8c583ecb7eb314ffc13 +size 1797568 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/red_coffee_mug_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/red_coffee_mug_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..250a9647c697ceff416ece1d7dfb704055e1f0f5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/red_coffee_mug_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:056fe075297343bd294678be0f8df694a4f4e0563f42033bb167ce6b5bd0b3a9 +size 9780486 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/visual/red_coffee_mug_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/visual/red_coffee_mug_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..2ec287f4d9f9c42ba9ca1040529d56b1ce904427 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/red_coffee_mug/visual/red_coffee_mug_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4f694d1ea953d86ce29a085cf3613363a193a6e99446c190d88c47016d94fb6 +size 1212208 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_storage_box/ceramic.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_storage_box/ceramic.png new file mode 100644 index 0000000000000000000000000000000000000000..891c50a69b45e57cc9befa6f8fcc579d35552fc4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_storage_box/ceramic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:beef464a2aa9143ba6a25a44adcbfd1f1aff16c5969edbf08019b61025388402 +size 1442030 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/visual/white_yellow_mug_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/visual/white_yellow_mug_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..b20134a5a4c9f424cabae4eaa97424d5595fd4b9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/visual/white_yellow_mug_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aeabcc3a57b84549568a1d6907542ef9e65ea126c101f6f3985deb8b55d3aa79 +size 913048 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/white_yellow_mug_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/white_yellow_mug_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..a9db22636283df1f0059949f8fbe4f3b335adf3e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/white_yellow_mug/white_yellow_mug_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:152a4b711c33e8cb6956233043580331bd0f54d5b3dbc13a9bc870201b295890 +size 8119611 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/Cork_Texture_by_faycop.jpg b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/Cork_Texture_by_faycop.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6df4b732352b5d9367be985a43241aacebf03836 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/Cork_Texture_by_faycop.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a59f0b4204a858367bb7d41c94b2d4b5f27b2b30859637a6c8d072d3122a53d9 +size 277008 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/cork_texture.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/cork_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..1d6d6bfefaf274442207b06e49606cc1614358b6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/cork_texture.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93a9c1d22c7256e423a1473b2bf9107b4e120cd249423f7e01289f9c6fd63feb +size 1322298 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/label_wine.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/label_wine.png new file mode 100644 index 0000000000000000000000000000000000000000..6d089f79f0025059fc7c9f0abb294b8bda092965 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/label_wine.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a8caed4b3414dcf4b72558e339ce1cad1b90b4f159d0d293f06ed04a1f473241 +size 158360 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/visual/wine_bottle_red_main_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/visual/wine_bottle_red_main_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..d88460d886f0e1d5b5fa547c990b1cf3bfbba0bf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_bottle/visual/wine_bottle_red_main_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92a7a897bdac34f47161cb418fbe6f7fc9056d2f0e93647beb8139cffeed270a +size 487096 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light-wood.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light-wood.png new file mode 100644 index 0000000000000000000000000000000000000000..92f9d6aa33937bb75a49fb9543e0c6a74a88aff6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light-wood.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:967be64bdb170d36283bc43c2ae5d525ec88f78bc837dc7d0efc9a28d68caad1 +size 801173 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light_yellow_metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light_yellow_metal.png new file mode 100644 index 0000000000000000000000000000000000000000..10776e536222cb8a19ee38f22c3a2c0e298d86bc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/light_yellow_metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8d8abf32b1940b938c097e6955ef7c5e0b84ab97296e53aa65315efbf1f1359 +size 1729294 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack_stand/metal.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack_stand/metal.png new file mode 100644 index 0000000000000000000000000000000000000000..f5260ff57151e704fb133e4e0ea88af4a455ee24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wine_rack_stand/metal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93784216a66b52be9c8ccc3732e50f511815291e32f34f97bd139ed7229061fa +size 196878 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wooden_tray/crate_mat_BaseColor.png b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wooden_tray/crate_mat_BaseColor.png new file mode 100644 index 0000000000000000000000000000000000000000..28e0bb650016e0e94370fe3cc0b325e316d61664 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/wooden_tray/crate_mat_BaseColor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3524386ee45899ff14c6e386294e2552f3fb11d4e0f478ef3e71f055f68f800a +size 4988248 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/yellow_book/visual/yellow_book_vis.msh b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/yellow_book/visual/yellow_book_vis.msh new file mode 100644 index 0000000000000000000000000000000000000000..57aa4458029b645700b1c2f742f5a40833dcf39d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/assets/turbosquid_objects/yellow_book/visual/yellow_book_vis.msh @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1292bb7e96409a465a38aef94a6316b85608c9821cae0779b51082d8a777c34 +size 773296 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_alphabet_soup_and_the_tomato_sauce_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_alphabet_soup_and_the_tomato_sauce_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..54db06e215bd4123d2fe326c72eb1993af534820 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_alphabet_soup_and_the_tomato_sauce_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7cef6cd0973d5c125d3cba94469ee58b116825a8d1df32693fd48119647348c8 +size 117167 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_cream_cheese_box_and_the_butter_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_cream_cheese_box_and_the_butter_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..16f16629cd6d56ebe28943ade6c4f9a7fcda3427 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_10/LIVING_ROOM_SCENE2_put_both_the_cream_cheese_box_and_the_butter_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2357ab3a089b11c99a932f3e05fb33252f564f9ad66d39a61984156c04e288f +size 117295 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_alphabet_soup_and_put_it_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_alphabet_soup_and_put_it_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..b57a16cb0c93b73ae2b05ab3f988083c4b918aba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_alphabet_soup_and_put_it_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4704198722aab1252b9632f97a260117b658a33251f5d303bcc386ad52ed765e +size 117295 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_butter_and_put_it_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_butter_and_put_it_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..f54cccf33286fe44bd1306e5c134bead5b444e1b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_butter_and_put_it_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b8dab7d093318de68bd8453ec532252cfc0c0840d4709c05d3b994d4bd9f89d +size 117167 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_milk_and_put_it_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_milk_and_put_it_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..bcda3f444652acffa1bc5dd97fdd3794b3c61cff --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_milk_and_put_it_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c19d53f72f132176e7571a72ff4e411ae89ce3d06cd1b4b08c6180036d516fa6 +size 117231 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_orange_juice_and_put_it_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_orange_juice_and_put_it_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..658797d8043dfe74ab210ed365d42bd12798f400 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_orange_juice_and_put_it_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d4aa684cf808d7ac7856e18eb2969e609da0e4bad1018b1e1b7a3b44542cd3a +size 117231 diff --git a/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_tomato_sauce_and_put_it_in_the_basket.init b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_tomato_sauce_and_put_it_in_the_basket.init new file mode 100644 index 0000000000000000000000000000000000000000..9dd35c4a4dc13f4af55d2991b715a2af7b26a15c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/LIBERO/libero/libero/init_files/libero_90/LIVING_ROOM_SCENE2_pick_up_the_tomato_sauce_and_put_it_in_the_basket.init @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9efef6222ad8159fdb9e6314959e2577650cce2db8bf5cda52e27285624f0f89 +size 117295 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/7up_can/Pepsi1.001_baseColor.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/7up_can/Pepsi1.001_baseColor.png new file mode 100644 index 0000000000000000000000000000000000000000..bb00f561a53e10797b29ba1e92cdf28c877196d0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/7up_can/Pepsi1.001_baseColor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37bdacda4d7f276b145a5e8b33207664ac05921287c8d97283279fbad336d5f2 +size 326985 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/apple/Image_0.001.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/apple/Image_0.001.png new file mode 100644 index 0000000000000000000000000000000000000000..5bea648ef7d233852b537913230ffd4924bd2c53 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/apple/Image_0.001.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4001636b44c127a783108acc129cd17b8765100fc516a5dc888fedd467774833 +size 1270502 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..410d6eaa902833a4a507dad0a1faf3863f36e041 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a23f0ef0c0346165a6530d3dedde16c7f6bb2e582ec61b0eede3e449d8903a4d +size 146324 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..410d6eaa902833a4a507dad0a1faf3863f36e041 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a23f0ef0c0346165a6530d3dedde16c7f6bb2e582ec61b0eede3e449d8903a4d +size 146324 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..8ecaa168dbd922c143e864f2766fc2c996b71de1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a66b4d0360e3d8dcec0c820490d09d4aee15fdde09d0bc378d740e7f6aad3c59 +size 143096 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..710fec9c8f3e431bc76fb08014d8614af7eecf39 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62d328a270dcff6a676787a6a72e8cc8d90faba967f8c56eaaf584dead412f3b +size 146596 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..9df6555e04bc79ee2ea97d3d45f39f17c5bbe51f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5939ed0f41c25cb6a1f34d3c9ab5b787e8fee7509853aadd6690763f1b03f53c +size 530052 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..2e009bae4afcb6aae2062604da2724d37b339d93 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07a1d5422af1551fc3ee87b0e105c9f81459930e109c2718c1d0d4c998a37b38 +size 140092 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..6c2ff6810dbb5985a1b308c0b4e3394270bc1ddd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_apple_v2/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56175984e7413e56a6a0e0339b199b9aa7e7297e0fcd25b374bae274b44a8a7b +size 140012 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..7bc86dc403bf53fce23b5dea3b4bc8b91bb174ac --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c1e2e4fc1f52b01c8c145775c6c44f293dca9ba4d58f7a7c5d75ae367a4ae6b +size 440024 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..7bc86dc403bf53fce23b5dea3b4bc8b91bb174ac --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c1e2e4fc1f52b01c8c145775c6c44f293dca9ba4d58f7a7c5d75ae367a4ae6b +size 440024 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..ea0359ff6b145f3c488cd9112b99545b044a15b2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23fa7ccbabc51ed232c339f30832129b025c2654d621b21ea259594e43cd0a70 +size 436456 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..e4c0c33e452e4f5d52a22bea290d9f5111e8b932 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/old_not_very_good/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85a1a29c18b8eb0a38f441a0ee9645607d7818f414649e1869bda1117bb5edeb +size 431432 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..752162f1cb9263bc6ce9df34691bce88684c77fd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2fe007d2bf027807ad13ceb9e76aa41d7ea890fb4a0838152f3e80545f564a1 +size 364252 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.glb new file mode 100644 index 0000000000000000000000000000000000000000..2783f952fffffedde1bfbbd6bb247d1bf6e35794 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdae184328cdb5e3245a1ecdc71e66d7050e10663062e00190da57ca6180c398 +size 313212 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..c653b5b4dca18047d2e25e82463b96d0d88f8e38 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b84bc6f3db7aa1d7b7e556c44cf1773139ed0995eb63980114440d663b0d5883 +size 253511 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..593bb84b35eb9506fe5fa2f8b09d2e21efddeb59 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cda8101320aded09f8ee3932a44dc0866f6a02221161ecdda894c4c808c6930c +size 351076 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..2141984e245f7e24d33b0a4dc3e0d4e970623a2d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_blue_plastic_bottle_v2/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d328f0da9512749e7a72878cad45f8d5d883bd0ebb820c7967a97fbd58ae0c57 +size 350996 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..b7b349872ced6ae79fa85d16f40cc8737ae1fab0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e09e1013293f822ed7cd4110acd327e9b00ff69232a940e9e158c115efc78a36 +size 118860 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..b7b349872ced6ae79fa85d16f40cc8737ae1fab0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e09e1013293f822ed7cd4110acd327e9b00ff69232a940e9e158c115efc78a36 +size 118860 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..45cb59bef4f8a676d32cb96fa54eac9a7969da87 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8895480c9283d9f0c1f468652185b4933885eb3b42391d50cdf0af77efd6bc00 +size 117068 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..d5dbf95539b5107180e940bd90cbbc01178b5634 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdcda70700ee5acd8670b98b9e4878094aa24d0c5ca79e41fdf038ae7fab58ef +size 115256 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..bfc3c70703687c25f4070f2212d3eeff618d2668 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e61bc4f3dfd0757cbd3a908bf0747e0d36abaef994c46da76a7bcb9407ee6f4 +size 388263 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..c6a3700270bf26e61b85ece0a28ccb97a96e6cc5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d71b18728708573eaf90a71d5c37ef7d275646fbbb835887a9b5fc7d1aeb6cfd +size 111124 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..449c1395a2f059242978c7c13947df518c0b56e3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_7up_can_v2/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6120231b44ee6d0b001c390a8c581ffc7a37c9f04463896ed4f2610a2e44245f +size 111044 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..9a777d8c8ebfef9813f00014aa2e71ae07dae52f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e28c5fa75636a0ee2e312067dab9e483d34d2c32d0aa2708001bab66af6ab6f7 +size 1937368 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..9a777d8c8ebfef9813f00014aa2e71ae07dae52f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e28c5fa75636a0ee2e312067dab9e483d34d2c32d0aa2708001bab66af6ab6f7 +size 1937368 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..edd9bfc9d2947ad9ea138bf54bce235d7ae8eef1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe1496dd021b920831b7de6eaf9d228a4f6a4b04793fdf4254661042fc52384a +size 1933024 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..0454da3766c0807d58e008ab0ddd14ff759da5ca --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0eff2a517bb2beb3e739f6ffb875d02df0dfabc9b34a09d42ecd39f0fcfeb7a +size 1944208 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/manual/Image_2.004.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/manual/Image_2.004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..62bdfc52dbeec0b06610c7b54a2b037ece469e1c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/manual/Image_2.004.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf1db919e0c34519b5d23692472505f047a37d831aa3e661b1382d2aa4a6f28e +size 315912 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.glb new file mode 100644 index 0000000000000000000000000000000000000000..18f07522a3bfff927080a405b371f9885beb9994 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e00690e3a6ee977393ee23fd537634b44b111ab6564fb458bcc1803e595c8ff0 +size 1817084 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..5ef7ac956ae1582d368caf76f789b73af1f46db0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88063ab133741c7e2069b9d0a5e8f4c3dcdb60a22ad0323af12d3846f10d21f1 +size 420513 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..73f06fe75b8a6ecc97b1f2edb8e85d3159c6aeba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1e6f43b367381c893355051be1b7b1087d6fb4097055ffc4e33835cdbefd332 +size 2755048 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..07463e1d1649ba569856b1ece19ff515c695d3f5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_coke_can_v2/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24519b424c11022efb5c9e38aed02c0789e95d33db1082a7d96acd2921edb0f0 +size 2754972 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..9db99f8053340b95a38d02fb07a25c6b1dd10736 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be3de60a0632fbbcc2e095533ef40df5e2499d4ef7379a855d0c99fc5f36f66b +size 135120 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..9db99f8053340b95a38d02fb07a25c6b1dd10736 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be3de60a0632fbbcc2e095533ef40df5e2499d4ef7379a855d0c99fc5f36f66b +size 135120 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..c381cf1f5241bb60c87a36f63dfa1b876b0c02c8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5948af33ee31248d52ffb1f3bf01b7c2fd9b071f9886f371fd7585bd87373ace +size 133852 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..bbe44d2eabd75aedbc36c3a35b68fafea96208ac --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb07f408f65939b7e3d511ece3a6a20ae96a93cf0d39d7fb7644e66bb9315abc +size 139736 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_0.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_0.png new file mode 100644 index 0000000000000000000000000000000000000000..35e941dea653f8c2225d7ee330a8273ea382080b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc9024bb9d0043dbd79b873609710696d46416d88de969e606209ce9a8d02f15 +size 585560 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_3.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9aa955f32ce055cff0f655a1ba578121ca6fb44f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/manual/Image_3.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:204f0af3cf6f5d220bf0a6ab70e5257d7e7b42ec95804824f2aab37f2e4ed36e +size 103058 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..910820445fcb796cdecb987007979f72504d1705 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71a13035037f8f14b74b86ca006e756e53abf159f12c58a923df815e0914b8df +size 379585 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..02ccc80bede904b11d70ad76c92a7370e9d5e83d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9a0a51659374810f466d61dbdbbbc31e8b31bd9673edd8329c2763f45620c13 +size 105156 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..ea7e72daa7bd224b43f420564e7694a9ed4f5833 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_pepsi_can_v2/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7af70a2953ec4675dd683f956e566d119612c37d7d1feaf4c21fc62c8a7de116 +size 105080 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_0.005.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_0.005.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d0398309d876a4e38d15cce2e5d3aa3d7231b2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_0.005.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85d13fdb28fa83dabc05cf052927122dd580cfe0ede9c3875c8f21e7a50c1859 +size 142887 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_2.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b18d2cdf6104e399634344425c3076c5a0bca707 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can/Image_2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b30d4f10af229caf1eba251df64dc27f3a8b87bb6899fdef2c55c2d06b82819 +size 110334 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_0.005.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_0.005.png new file mode 100644 index 0000000000000000000000000000000000000000..a0d0398309d876a4e38d15cce2e5d3aa3d7231b2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_0.005.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:85d13fdb28fa83dabc05cf052927122dd580cfe0ede9c3875c8f21e7a50c1859 +size 142887 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_2.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b18d2cdf6104e399634344425c3076c5a0bca707 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2/Image_2.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9b30d4f10af229caf1eba251df64dc27f3a8b87bb6899fdef2c55c2d06b82819 +size 110334 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_0.004.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_0.004.png new file mode 100644 index 0000000000000000000000000000000000000000..af973d85764d3326ca732615fbace7c8afb69909 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_0.004.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d19119d43df8f31754d07ff2be5dd2d6a053f388fe65e88373c41b8dc6ec579c +size 241775 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_3.002.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_3.002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..603583c7cec506c40b1034763709abb7dc60b7c5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/manual/Image_3.002.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bc4e84ddd4cf0ff55388fecf8c260aa4acd19db0e733f0e05050f31ec51fed1 +size 104397 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.glb new file mode 100644 index 0000000000000000000000000000000000000000..537e0c12a086e499a69b8330b9ff5c0e8a3ee048 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c07cb92b608b61d42078b000cb27d15559ee9995af2dfa137c1868d1c84dc78a +size 682748 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..59225464494afab2c9e25295bd156809c9568e5d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce7ab1271e890e7f85cf67a6f57c1751a5e4a3e26d350c8ff83ee8eef39b952e +size 320314 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..f57a2642df2ffb75e5e139ef9f713e831039a91d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16428dfd2acbb1fffa855c8db3fa835804e529b83b0c08fead17e85586711c1a +size 728688 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..d768bcf5b50b7c562af3f96158e9152c8b7dfb39 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_opened_redbull_can_v2_alt/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f941423086d6f7c0f2cbe7d301e0e9bf8d7718429ea26e2237b57bda3612a7d5 +size 728612 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..338ec73395c81f8e9b868992f7a70dbcbb2c9a68 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4aa9ad9337adc7f466dcc81524ce5b183c1629ea68ba77654f228907f6698eea +size 143172 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..338ec73395c81f8e9b868992f7a70dbcbb2c9a68 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4aa9ad9337adc7f466dcc81524ce5b183c1629ea68ba77654f228907f6698eea +size 143172 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..9589cbf79549bfa472db88aeaa383ed25524a717 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8a6e46585e3ea17a4dfd2bcbd8987404050406317a7a849501287c044f39a67 +size 140840 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..a87a6b666df2784d4a0586d22a870df4d47844db --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b314f2e6701073396a0ea636f2c1cec44bbd3d943c82f912b4a2f718b12dcfd1 +size 143400 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..166503b8814b53ebfabb23f697a92a8c787fb505 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af14ccebf95c32b0ad504343d1aa96832b9d862d3c16091f2ba3c2ccbf2f25dc +size 526849 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..1ea3aed5f5d3a9be65ee2086db88fcb393916204 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1f9e4ae23ca3cb2b9653cb6ddafc3d679575d05797b04b6d06d17008cab8951 +size 119644 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.vis.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.vis.glb new file mode 100644 index 0000000000000000000000000000000000000000..f51a12341d203e3492920cc7c90ea80b94b948c3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_orange_v2/textured.vis.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad570dc690cb9d47ce96f3a2c56d56e9c7d14c2d2a62290bf267e0fe5d41b80a +size 119564 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured.glb new file mode 100644 index 0000000000000000000000000000000000000000..ee4665d1dd494d3ca77360a8c2bd1d10fd2fcbb2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa6db3ad1dedce22fa0501910ad520403cd200b571831cebcb967d7bb288a72e +size 154988 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_bkup.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_bkup.glb new file mode 100644 index 0000000000000000000000000000000000000000..ee4665d1dd494d3ca77360a8c2bd1d10fd2fcbb2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_bkup.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa6db3ad1dedce22fa0501910ad520403cd200b571831cebcb967d7bb288a72e +size 154988 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_cand1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_cand1.glb new file mode 100644 index 0000000000000000000000000000000000000000..26a8d1148c0f0fc446e0c224f342bf794f0a80bf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_cand1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e45b6f7ece6f40b2a6582609ae1747c82f988b0b8a1a797f985347aea8149eac +size 163424 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_toobright.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_toobright.glb new file mode 100644 index 0000000000000000000000000000000000000000..078a5fdbbb83156cea405116969636e283b603d7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge/textured_toobright.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:12b2c1803fa13e25abbe467e585dc886ffd63755ebbad31cc8c9c1ab6cfc6e7a +size 165808 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge_v2/textured.baked.zero123plus.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge_v2/textured.baked.zero123plus.png new file mode 100644 index 0000000000000000000000000000000000000000..793b424aa33acec57c676c2fa6a434f07a2f30cf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/baked_sponge_v2/textured.baked.zero123plus.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e2f2977cdcc3979003b07e9de43e19b25fb9b4da28286deb3f880f04b6ad316 +size 400158 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/jasmine_tea_3.jpg.002.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/jasmine_tea_3.jpg.002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..39aefd9137e618a737d3e2f6b49789961103b314 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/jasmine_tea_3.jpg.002.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82c10803d9aac79582f33a41236ff6a04195b63273160e8c126089f3ada5fc69 +size 1172246 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/textured.dae b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/textured.dae new file mode 100644 index 0000000000000000000000000000000000000000..07a1836d041e50c337e5e3d3874578ea30719c12 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/blue_plastic_bottle/textured.dae @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:716c21d7a2134d74b8c1b1a68716f50343e707a6e15edff46a9a38672d5205e5 +size 12124958 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated/Image_0.005.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated/Image_0.005.png new file mode 100644 index 0000000000000000000000000000000000000000..ad7c4d5c9a1f14ead248b8c5027f7cc23cf21949 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated/Image_0.005.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c23aa14532978e72644da9613f83e27ac8dfda1844293d6fe7e46ff88d8c6cb9 +size 2611762 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated_modified/Image_0.005.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated_modified/Image_0.005.png new file mode 100644 index 0000000000000000000000000000000000000000..ad7c4d5c9a1f14ead248b8c5027f7cc23cf21949 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_carrot_generated_modified/Image_0.005.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c23aa14532978e72644da9613f83e27ac8dfda1844293d6fe7e46ff88d8c6cb9 +size 2611762 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_spoon_generated_modified/Image_0.003.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_spoon_generated_modified/Image_0.003.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bcb7c17744d1d97c9ce7eaaff8816e01f1838639 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/bridge_spoon_generated_modified/Image_0.003.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a3a360b219b224638e69f0efb679d4e34be23fa5f143913eb5077e3998166d2 +size 2018301 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/coke_can/Image_2.004.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/coke_can/Image_2.004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..900333824758cdc9ddf27859ba42c7aa4cfb1599 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/coke_can/Image_2.004.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc4068ac6cd1ecdadca33d2ea0568057ffde4eeccd84bd748dadda66b9b447e9 +size 350977 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_7up_can/Pepsi1.001_baseColor.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_7up_can/Pepsi1.001_baseColor.png new file mode 100644 index 0000000000000000000000000000000000000000..bb00f561a53e10797b29ba1e92cdf28c877196d0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_7up_can/Pepsi1.001_baseColor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37bdacda4d7f276b145a5e8b33207664ac05921287c8d97283279fbad336d5f2 +size 326985 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_coke_can/Image_2.004.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_coke_can/Image_2.004.jpg new file mode 100644 index 0000000000000000000000000000000000000000..900333824758cdc9ddf27859ba42c7aa4cfb1599 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_coke_can/Image_2.004.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc4068ac6cd1ecdadca33d2ea0568057ffde4eeccd84bd748dadda66b9b447e9 +size 350977 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_pepsi_can/Image_0.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_pepsi_can/Image_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a90f03e1d8c839ec6e77baffff3e410cfa2ccf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_pepsi_can/Image_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:392ae07c85cc42f70081dacbb8d86295ac34b2935587bddd8e32246bb50e0ab4 +size 548056 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_0.004.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_0.004.png new file mode 100644 index 0000000000000000000000000000000000000000..7e745012954d2cce0bb772c3cfd5241987d85b20 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_0.004.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f63eb9ea2b0184a2abf2fc76792cdcd8e4fd5d4a585c86a70740b862f1d33f8c +size 209323 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_3.002.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_3.002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9aa955f32ce055cff0f655a1ba578121ca6fb44f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/opened_redbull_can/Image_3.002.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:204f0af3cf6f5d220bf0a6ab70e5257d7e7b42ec95804824f2aab37f2e4ed36e +size 103058 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/orange/Image_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/orange/Image_2.png new file mode 100644 index 0000000000000000000000000000000000000000..0523d13d882c34b790884d80f05f4bb67fef9477 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/orange/Image_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7993a4a959ad06a0afb9f831d2a3377c0a2264748e1531e7ca2fc4c4cb7a7cb7 +size 1131502 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/pepsi_can/Image_0.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/pepsi_can/Image_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a90f03e1d8c839ec6e77baffff3e410cfa2ccf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/pepsi_can/Image_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:392ae07c85cc42f70081dacbb8d86295ac34b2935587bddd8e32246bb50e0ab4 +size 548056 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_0.004.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_0.004.png new file mode 100644 index 0000000000000000000000000000000000000000..7e745012954d2cce0bb772c3cfd5241987d85b20 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_0.004.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f63eb9ea2b0184a2abf2fc76792cdcd8e4fd5d4a585c86a70740b862f1d33f8c +size 209323 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_3.002.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_3.002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a504fe1e1b7bab3bc793158608c8d2fd4935978 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can/Image_3.002.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc67dd9f13f2c9151c9c56479a5c3fe5566c5924b8b7da6a35804909d8caffd3 +size 110336 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_0.004.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_0.004.png new file mode 100644 index 0000000000000000000000000000000000000000..7e745012954d2cce0bb772c3cfd5241987d85b20 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_0.004.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f63eb9ea2b0184a2abf2fc76792cdcd8e4fd5d4a585c86a70740b862f1d33f8c +size 209323 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_3.002.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_3.002.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2a504fe1e1b7bab3bc793158608c8d2fd4935978 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/redbull_can_original/Image_3.002.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc67dd9f13f2c9151c9c56479a5c3fe5566c5924b8b7da6a35804909d8caffd3 +size 110336 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/stone_tabletop.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/stone_tabletop.glb new file mode 100644 index 0000000000000000000000000000000000000000..e3278766bf3333c300b85124ece5b74533d811df --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/stone_tabletop.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b38a4237c15dd2c74812abf9d134c0d149002fd583358e16661e239201846c7d +size 250560 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated/Image_0.001.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated/Image_0.001.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1709784282f7734245ded24dbef172db3126a40f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated/Image_0.001.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd56703c28fc307420c09f55b52e7e398ba6c170c9393381aa5abbe6ae1452c1 +size 3373009 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated_shorter/Image_0.001.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated_shorter/Image_0.001.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1709784282f7734245ded24dbef172db3126a40f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_generated_shorter/Image_0.001.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd56703c28fc307420c09f55b52e7e398ba6c170c9393381aa5abbe6ae1452c1 +size 3373009 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_objaverse/Image_14.jpg b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_objaverse/Image_14.jpg new file mode 100644 index 0000000000000000000000000000000000000000..763dde986c59e7b0de7fbd6bba6ddfc28caa467b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/custom/models/table_cloth_objaverse/Image_14.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bc5a06a4805e0d3b00fbdc276c09ef0d812e5022e84b37fd0279cd5c8f7d36d +size 264453 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1.mp4 b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..ca0781e99ede45619b2b5c73068028aca190d777 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:643f1406ba5e38071a3f11d30961d5b22192d33efcbf2c5fcb8c0b7ba4408544 +size 395266 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..cff0baa21d0491b0eea173f2961d48a766dc14c9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_1_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b2fca2d1b9fb529fdec59751980c0c167e2afdc5afa85d2b92c8992558ed803 +size 453336 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2.mp4 b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..efb632835a87d2759030b1ba6878e6e3db349f3d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2.mp4 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8347098047e4bfeacc4d3385edb45fa32bbea4cf5214098fc2d23bf5d5be503 +size 468591 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..ece57313ae1aabc8c57430ecb93436e4f3513562 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/debug/bridge_real_2_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:226afc83c56df94e42bc75167fb7490013461e144631239f4aabe212dc60f328 +size 429076 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet1_h870.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet1_h870.glb new file mode 100644 index 0000000000000000000000000000000000000000..d0e180aae5ea17ebafb51ad1e63d18e269dc69ae --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet1_h870.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:594957cbc4e1f5d586b15f48f1dfd651b9165f7d68758af01966328566e4175e +size 5524148 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet2_h870.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet2_h870.glb new file mode 100644 index 0000000000000000000000000000000000000000..4d3919cd70685cf380c1489f5fa272861f618101 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/Baked_sc1_staging_objaverse_cabinet2_h870.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ee8c705afb32d7ce9115e613b8f6f00733739ded333e7e192d8a76f804a27e4 +size 6147400 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v1.glb new file mode 100644 index 0000000000000000000000000000000000000000..94e72881aa3ab4b60f613d27036123768e5dd249 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a15b3055c007803b16a921a82602299c5c234a1ed69d98815078aff7d4717fc +size 4470984 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v2.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v2.glb new file mode 100644 index 0000000000000000000000000000000000000000..5ae936f0d8da419d20da820584e9c00f58f8584f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/bridge_table_1_v2.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b094056de003aecf69e11c42d45a2a231bd54990832be50d69ef3b812a8d14e5 +size 4470984 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj11_table.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj11_table.glb new file mode 100644 index 0000000000000000000000000000000000000000..caee36264c0decd6be5c693cb6a7fb94dad9a8a6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj11_table.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d9daa77c78b824c1b0db9bdeee9a9fdcf69d48812ef8091aa54c8c724891b13 +size 5487120 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj73_table.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj73_table.glb new file mode 100644 index 0000000000000000000000000000000000000000..caee36264c0decd6be5c693cb6a7fb94dad9a8a6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/fractal_traj73_table.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d9daa77c78b824c1b0db9bdeee9a9fdcf69d48812ef8091aa54c8c724891b13 +size 5487120 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/frl_apartment_stage_simple.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/frl_apartment_stage_simple.glb new file mode 100644 index 0000000000000000000000000000000000000000..bdb4d7576ade9648f02da76e1eedd81805d2269e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/frl_apartment_stage_simple.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:431504de881de530626f64b282111108388751d7ec4ecfeaa6fdc306005ce9b9 +size 1426120 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4.glb new file mode 100644 index 0000000000000000000000000000000000000000..92e796f82935f2ff840e6c45fb7fe0e136cc1ba1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:58cd94404decc679288d9a8e5adb74af775d57b80e3ceb546b954e503cf44dfb +size 5487128 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background.glb new file mode 100644 index 0000000000000000000000000000000000000000..af84c54500eb066b7bcda6ebac00c479c01934a9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9e711f3caba4f58a9140112b8bc37892a514366d7ca4117693e0a030f366222 +size 5487272 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background_2.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background_2.glb new file mode 100644 index 0000000000000000000000000000000000000000..8c73fe5e6dd33e5d159d86d964e53128340ff251 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_alt_background_2.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ff6351de2fcd9ecb2d7c665df08ac9cdc5c7d4819fdaddc93975005329d6bf1 +size 5487360 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_no_roof.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_no_roof.glb new file mode 100644 index 0000000000000000000000000000000000000000..5a057ff55c61a830bab4c6dc9fb90d2d3284f5e7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/google_pick_coke_can_1_v4_no_roof.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9ae3191e6a9fe89cb5f16e6fd8e2541b8bcd1559b26a81716a08e4a6b9bb46d +size 5467556 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/minimalistic_modern_bedroom.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/minimalistic_modern_bedroom.glb new file mode 100644 index 0000000000000000000000000000000000000000..c59e2a577a275f87ead99e37eea9bd95c65d7cb6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/minimalistic_modern_bedroom.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d9ea14c8cdfab1ebafe3e8ff5a071b77b361c1abd24e9c59b0f08e1d1a3421a +size 7595064 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_bedroom_no_roof.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_bedroom_no_roof.glb new file mode 100644 index 0000000000000000000000000000000000000000..daf10131259ccb4c00635f9ff05c327e2e16fd99 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_bedroom_no_roof.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd1ead671afcce46e202649cf4296f008a1c1c48e850844345f30cdfeb713b1d +size 8958704 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office.glb new file mode 100644 index 0000000000000000000000000000000000000000..6300ead69dd02882ade2cc281affd13b0bbcadb3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa85bb846b3f033bfa486253a15b3f5d402969254dc9844cc93620a08b2eae14 +size 12100428 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office_no_roof.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office_no_roof.glb new file mode 100644 index 0000000000000000000000000000000000000000..6764a8097dad9650e11fc9559d0bbf884d188772 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/hab2_bench_assets/stages/modern_office_no_roof.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d1cba07791601265722d65f7e439b9a5f6ccacb688621087c2ab2e97d8a3875 +size 12688992 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_1_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_1_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..eb23d769e38f6ab10fe7e669f423ee49f9af56cf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_1_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:051abdf6a67da542f7c6fb34d0cfe70809febf45b2c577a2f79ff59ab3698290 +size 522496 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_calibration.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_calibration.png new file mode 100644 index 0000000000000000000000000000000000000000..c1595899a6ac03a398bd2645daf3e00911075d22 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_calibration.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf2df816694efa5326231fa1213cbaebec171da8d0a12e84c47ef1a750612680 +size 340238 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_sink_calibrate.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_sink_calibrate.png new file mode 100644 index 0000000000000000000000000000000000000000..accfaa4fe1851bc9a88b1bcbeb6df8b7852de867 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/bridge_sink_calibrate.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:92d0f731006b5a05a23fc3904fac066f6c10c8b8858e9e0bd881df0d16b43f8e +size 307918 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/debug.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/debug.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed48b9546a6c8fc23d21763873c25abe9486147 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/debug.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca54aa7ff1920c98dc3c6e3db6912113741698e2997c627686425d1277797484 +size 342036 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/stack_cube_1st_frame.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/stack_cube_1st_frame.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f727089d0e5516b7b277ac0c44a174f8a5c781 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge/stack_cube_1st_frame.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f7c19cd794b20b1e93583104523101e07460f0ddc7e58a1800a883285853e19 +size 230924 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_1.png new file mode 100644 index 0000000000000000000000000000000000000000..5837f760dbdd299305d2fe629062f23117125ca8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d25ac179f7cdace1de14d5dab9496d52099231ea3e3d60eb3fe422c9802b611 +size 361295 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_2.png new file mode 100644 index 0000000000000000000000000000000000000000..b60c3ef8d1f7224235afc0686e1551c4bee17323 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_real_eval_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b6bd4840b8c4de8f7919b1095bbb44221f04c92c7204afd7d36bf93fee233403 +size 312712 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_sink.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_sink.png new file mode 100644 index 0000000000000000000000000000000000000000..e54466c29ca13f1af80b7b882e5bdec79ab5750f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/bridge_sink.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:86b50fa15ede8e2c28cc01b6adffc40b79f7136130547c6ee905cf91b4aff188 +size 334926 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1257_0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1257_0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..ac453decc431ee411b3d7d43418d4245d1b1226f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1257_0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3da73b1bc3ec1ea0d93ed0e080818a7ba00c442ad2f8a53a963b04f77a1dcf7 +size 100557 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..42d07ceb087d39e11533f94c347b94d5596307cb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a35103afd1f2bdc1c1640f3db69fc17f794072079afa389f50f4fc3cf9e984ae +size 134585 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup_no_coke_can.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup_no_coke_can.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b28113a9e9f40c5b73c17b839ae00f36937982 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1495_0_cleanup_no_coke_can.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4b3d99d3e6dc33cbffa07055f59a869693818ada54394bd7bd73ee02111030f +size 133819 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..10dad289ee2826d553b7626d1254a73406db638d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7edcd123bf9edf0105943bcad662a9502a3d2d73f536e3a0e7612892dec2e5bc +size 136463 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup_no_coke_can.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup_no_coke_can.png new file mode 100644 index 0000000000000000000000000000000000000000..bf48a3cb717f4eee07f8d59de37abf871f3dc017 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1539_0_cleanup_no_coke_can.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f0bfca1796ca3f13b9839d2cc48a04e6194394b0fc80361f7da60b9cc105df8 +size 135629 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..200ff4687a4d4dcecb345e0953c713dc2c933194 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8efcc51c048ff5f60987828ea1b15b7bb45a1dbea5c3fc9c5a4dd1d8c9ae19d1 +size 102546 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup_no_coke_can.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup_no_coke_can.png new file mode 100644 index 0000000000000000000000000000000000000000..a2e76d0862e203f0490cad994cc6ee015559902f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/1991_0_cleanup_no_coke_can.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e84b16bb275763071e0a66636f71d615b473ea36a3b4f04405516ae3717f3391 +size 100762 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..840eef1be5e808cb0f33bbe9e3a4a6491f1b2d25 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15c3152578b11318e64da76dff6f6a4a4cfe8f16d65c3912497c6eb58bc6f667 +size 132999 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup_no_coke_can.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup_no_coke_can.png new file mode 100644 index 0000000000000000000000000000000000000000..99016763a74ab1794dd453d2e31cae934a69b822 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/3289_0_cleanup_no_coke_can.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75ef386c090d62ebf88139fc22ac5a37cfe262c83e43f604cbdec10f3103e89f +size 131972 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/73_table_brighter.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/73_table_brighter.png new file mode 100644 index 0000000000000000000000000000000000000000..d50171ad53c08574bb3eff78e6a51ce2eb26423f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/73_table_brighter.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67136abbff8460b8eebf184deb6b04a9358d7f9acab9fddd9ffc9e89008034df +size 106372 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..c02e3cfe489c3b83b938f485aed1b820317f6c99 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5b6209e95651d9511aa910cffe25f48c76e1a15ea49db68ccb6961d9ff867fd5 +size 117834 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup_no_coke_can.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup_no_coke_can.png new file mode 100644 index 0000000000000000000000000000000000000000..05012794d9507ee923b0b7af5b16d830ef1e9161 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/805_0_cleanup_no_coke_can.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6dbf284cf9db9e7d4f02109072678d03a6c5a1feed5b4454a9ed7dae36c01d9e +size 116257 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/another_counter_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/another_counter_1.png new file mode 100644 index 0000000000000000000000000000000000000000..1193752fc2e036935c1fac81913ce761b2bfb6ab --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/fractal/another_counter_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b8d0f3a11ce219e4da0f500355523a38fd55670e34e623e1745add458a5d87d +size 250602 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/google_move_near_real_eval_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/google_move_near_real_eval_1.png new file mode 100644 index 0000000000000000000000000000000000000000..781d5546b46508f1e76eb58742b54ed0a99c455a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/google_move_near_real_eval_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9bf9ace717a1895d1e0f2af2c4c5b0a2c8c030717cd1f44380074f640e06bd3 +size 101906 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_1.png new file mode 100644 index 0000000000000000000000000000000000000000..24e8349c1c73ac2539c6a6ca5a26848ce9bfb003 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:99e0629eef54b506b8a2e41d0124b1a7baad49fd22520909f450e01bec9ab21a +size 101688 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_2.png new file mode 100644 index 0000000000000000000000000000000000000000..df439baccab82dd12474fc7defc714aa510a4999 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_1_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf96366fd2dd3e2dc56ebe75d06acae899dcb4c0fd0b9ece1edf4e1a2993463c +size 105612 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_1.png new file mode 100644 index 0000000000000000000000000000000000000000..07aee80225e383b9a784698dc2fe65d78d8827f9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0552aeda674d32a2aec9754bdd129b937ee228d7980ba49ab85e8797539a5ed3 +size 101261 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d32a9b3c1ecb778c41f845500856ab0aec124dcf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_2_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63de480d13a138d45482b6b76a7ed39a1dc54114b3f05f861c290188b7592f7f +size 102451 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_1.png new file mode 100644 index 0000000000000000000000000000000000000000..8ce18c818d93a5856286b68aded9980bfcfa5e75 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ac1342b28b614c07c30559e8d933d07112c5d09691aa3765f07c4c5c350f092 +size 102705 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_2.png new file mode 100644 index 0000000000000000000000000000000000000000..f89323c95aeb500bec51aa82c44d985c89fb1982 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_3_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18fd552da3d3017fda0e9aebf25faa4004ad937bb62fe8cda41346349bcb988d +size 104991 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..0238248d2297f3b5f5b1c8c5bff00136c8c02463 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a71047738d842f1583f2971f5a86ae25831960c1e0d550cd8113b58b90d474b6 +size 103064 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_2.png new file mode 100644 index 0000000000000000000000000000000000000000..b0c921889eb013c69175afecf44f7d2f6be962d4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_4_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dc621f76466a78939eed7fe69b220a565000e62b7a37798dcb19b87cb55df47f +size 103401 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_1.png new file mode 100644 index 0000000000000000000000000000000000000000..83c242fc7e3240dbb5f869d971d7faf346f45456 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15dab9a85b392fb5c765c696bcc5b8dcc23443e09a259f1f79b4e309e172564a +size 102230 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1ae761d3a3467bd6bbc55b3aa8dca1df4521f931 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/move_near_real_obj_variants/move_near_real_5_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65fa779f090f263280b25522ef9cbb80572cc43cc913671a514d9141ef1ec399 +size 102087 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a0.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a0.png new file mode 100644 index 0000000000000000000000000000000000000000..2a683d7f4aee4d44b4fe96d6da2545f7068da5fe --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a98b68b0a6b097af38b463e7b30371ec30eb15391f62fe9f03f16b97a0f6359b +size 133795 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a1.png new file mode 100644 index 0000000000000000000000000000000000000000..6c2223864617b976ed3569975785a0424d89afa9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fef25cffac02dd31898514fee63d2b0b9e763448f657da4a1be007f5fd4cf5d0 +size 129521 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a2.png new file mode 100644 index 0000000000000000000000000000000000000000..9949e410f1a5197a9c5b9ef709238ae44deb12ce --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_a2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75aeff00694ed2e4c9c299fc7a20bed1b3b7d6f863b28dc5964ea1931ea7069b +size 128898 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b0.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b0.png new file mode 100644 index 0000000000000000000000000000000000000000..df6e5899bc00a084f965aac88bf61128b0cccb62 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6665d9e3b2185c615994a5bdd435e2004c0374ebb1aa9480b7392c1dcc5277a5 +size 135840 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b1.png new file mode 100644 index 0000000000000000000000000000000000000000..beeb9a5517ce73001a5386f634173fcd5a43178a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a106aa95d35a9ea5b0c3ae21e9aaea6496855494ab6c8d07dd25181615ad599 +size 130940 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b2.png new file mode 100644 index 0000000000000000000000000000000000000000..b26849473dd1f9545741a1819d69fe417c5f67a4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_b2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b2eb39e654224fa5e8201eaa2614f76e72baa3881a0242b61c84e903d65ab48 +size 125760 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c0.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c0.png new file mode 100644 index 0000000000000000000000000000000000000000..f9543e4d3755424f03734d076ae6673f64957e1b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3bb62bf601598467c3a9cc515abcc9b43a37bd1b2296b431420b5806367b04a9 +size 137761 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c1.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c1.png new file mode 100644 index 0000000000000000000000000000000000000000..78d5112424f3445d1e772b66a9850d5232bfa1fa --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72746163c07514e6dda4e4145961f619be0439814917b913a035295bf65bd7be +size 129527 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c2.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c2.png new file mode 100644 index 0000000000000000000000000000000000000000..c47d1061ef4b0fff3b807787b124cdd450e6c8b6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/open_drawer_c2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84b9eb5ac8a8eb8faa1866f8761af318f89e876c9b4d6632d47ead4c6854db9e +size 132432 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_coke_can_real_eval_1_brighter.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_coke_can_real_eval_1_brighter.png new file mode 100644 index 0000000000000000000000000000000000000000..30c28241d900f8e829f911154fd3227b05a5950b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_coke_can_real_eval_1_brighter.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50069d8151daf35282974f4a1a11703fb4d302891ebebf22e09b1c09b16764b8 +size 108953 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_standing_coke_can_c0_cleanup.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_standing_coke_can_c0_cleanup.png new file mode 100644 index 0000000000000000000000000000000000000000..3802b92ab826f6d1a472acdf8cd012169660cd5a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/data/real_inpainting/pick_coke_can_real_misc/google_standing_coke_can_c0_cleanup.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0277c973647a071bd923c7aaea05b85f2b8dc97055c2e190075a4a484829f427 +size 101715 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/link_base.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/link_base.glb new file mode 100644 index 0000000000000000000000000000000000000000..4163cc5ecd443ad04282ace247134940c2544461 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/link_base.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:922dcf219018381dfe1afeb238a49135bbad0478230747e4f01d518a4eda7600 +size 172928 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_ao_roughness_metalness.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_ao_roughness_metalness.png new file mode 100644 index 0000000000000000000000000000000000000000..b28c680f3d3b2e7c9fe9d7094b1d7e0905a55e3b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_ao_roughness_metalness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2fee1de0e7112c27b9e52b8c246b06be37d11b4b83aaa44958df3476dfe768ed +size 137830 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_diffuse.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_diffuse.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd85b34f229b769bb598f8c4613108d0f44969e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_diffuse.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f5b97ff641f7fe9f19040855e701c9d20d4572658df1705c5bffb75388b214b +size 123227 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_normal.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdaee3cb74e8ba16f31e25ede1024c4c821b4ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj/meta_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a6657b716e61ac06e2f57ae3bd469c4d943562008954ff5c46849042a66040d +size 2314967 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_ao_roughness_metalness.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_ao_roughness_metalness.png new file mode 100644 index 0000000000000000000000000000000000000000..b28c680f3d3b2e7c9fe9d7094b1d7e0905a55e3b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_ao_roughness_metalness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2fee1de0e7112c27b9e52b8c246b06be37d11b4b83aaa44958df3476dfe768ed +size 137830 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_diffuse.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_diffuse.png new file mode 100644 index 0000000000000000000000000000000000000000..5e56e1e467baed5c267efb637b9311e39c629ca7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_diffuse.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9bfd86ad931ea9d687e4354b9b5d375a0119a5efebf9ba92dc58a2b1412c1f1b +size 117684 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_normal.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdaee3cb74e8ba16f31e25ede1024c4c821b4ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_cabinet_visual_matching_1/meta_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a6657b716e61ac06e2f57ae3bd469c4d943562008954ff5c46849042a66040d +size 2314967 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_ao_roughness_metalness.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_ao_roughness_metalness.png new file mode 100644 index 0000000000000000000000000000000000000000..b28c680f3d3b2e7c9fe9d7094b1d7e0905a55e3b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_ao_roughness_metalness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2fee1de0e7112c27b9e52b8c246b06be37d11b4b83aaa44958df3476dfe768ed +size 137830 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_normal.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdaee3cb74e8ba16f31e25ede1024c4c821b4ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_sim/meta_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a6657b716e61ac06e2f57ae3bd469c4d943562008954ff5c46849042a66040d +size 2314967 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_ao_roughness_metalness.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_ao_roughness_metalness.png new file mode 100644 index 0000000000000000000000000000000000000000..b28c680f3d3b2e7c9fe9d7094b1d7e0905a55e3b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_ao_roughness_metalness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2fee1de0e7112c27b9e52b8c246b06be37d11b4b83aaa44958df3476dfe768ed +size 137830 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_normal.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdaee3cb74e8ba16f31e25ede1024c4c821b4ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_1/meta_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a6657b716e61ac06e2f57ae3bd469c4d943562008954ff5c46849042a66040d +size 2314967 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_ao_roughness_metalness.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_ao_roughness_metalness.png new file mode 100644 index 0000000000000000000000000000000000000000..b28c680f3d3b2e7c9fe9d7094b1d7e0905a55e3b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_ao_roughness_metalness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2fee1de0e7112c27b9e52b8c246b06be37d11b4b83aaa44958df3476dfe768ed +size 137830 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_normal.png b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdaee3cb74e8ba16f31e25ede1024c4c821b4ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/3obj_recolor_tabletop_visual_matching_2/meta_normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a6657b716e61ac06e2f57ae3bd469c4d943562008954ff5c46849042a66040d +size 2314967 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_1.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_1.glb new file mode 100644 index 0000000000000000000000000000000000000000..b06d435d3b351dd6bed09a43ae8cb786f551abb0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_1.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8f4cf1e722b061a8cd0c9df1006e4b8486f50bc7b163da2a640387e9f745816 +size 128672 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_2.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_2.glb new file mode 100644 index 0000000000000000000000000000000000000000..b8a29be4a1317a2bf13b62d8c8ed4cd8cdec5e1d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_2.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6081ef0a739f538ff8fdcc2b29e9c0324928ae7af56bb8db51fd709231998d5d +size 129836 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_3.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_3.glb new file mode 100644 index 0000000000000000000000000000000000000000..26a2fe78dfce32f1e1edfd8bafe360b26c1d1c55 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_3.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:254d6300453b41cba7259307586ce55b8416a80861cea125d8baf700fc282243 +size 136256 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_4.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_4.glb new file mode 100644 index 0000000000000000000000000000000000000000..595314569c6e36f9d396ec4338494fff7ec77ca9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_4.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:594dcc696cb7e3c7e1b147c7b64e75cd0fc61106babe1cfb1e36d04c9c7f65a3 +size 133440 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_5.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_5.glb new file mode 100644 index 0000000000000000000000000000000000000000..ca81d414b2063364e2a2c6a8286ff5a9741c64d5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_base_5.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8de3d8d288c3f7adaf0cc39603d4a9ab7390c07cb5eae0cfe54fc1c5254aa7e7 +size 126896 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_rear_wheel.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_rear_wheel.glb new file mode 100644 index 0000000000000000000000000000000000000000..5b64845383ed688e0112fdc04863c4c00984c200 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/googlerobot_description/coarse_meshes/link_rear_wheel.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee1ccae560d15ba40adcbf3d54620b3416f5d3c5adb77375b3dc63d10beed4d9 +size 128216 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/widowx_description/meshes_wx250s/WXSA-250-M-5-LF.stl b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/widowx_description/meshes_wx250s/WXSA-250-M-5-LF.stl new file mode 100644 index 0000000000000000000000000000000000000000..dedfca506c33c8796a9811d6f99e6c092f1cb064 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/descriptions/widowx_description/meshes_wx250s/WXSA-250-M-5-LF.stl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1445950b7f5ce2cf374b98711df296acd6c2b4df24c3937b413bcb6beb037603 +size 149084 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/maniskill2-scene-2.glb b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/maniskill2-scene-2.glb new file mode 100644 index 0000000000000000000000000000000000000000..ed83b72dd99d0cdc55521182803b774575c3cbe8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/ManiSkill2_real2sim/mani_skill2_real2sim/assets/maniskill2-scene-2.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b9a26f68f6be81f9f5a86aeccd7d49b6595e6c87c35fec0bd9465628d7e2174 +size 4737204 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_close_drawer_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_close_drawer_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..de32645aad3f831f26ea255098113da42cbba821 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_close_drawer_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3fef9e34359c78ee99eb8b18d1c43aad08d3ca1d701d89771d5a89bf955de8e5 +size 171309 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_coke_can_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_coke_can_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..676f82abe27e892b28d0ce73925d35a082b30578 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_coke_can_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d1d822c872aa16d590267e8a2cabd8e9b683f827e3e4ea1e513468b0e479af7 +size 156356 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_move_near_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_move_near_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..b377fda581a674a17577cc1e280c9ee984ca172e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_move_near_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4944fce043f9ce2ce6609cb91c39412d31fff82b52380028e2e229b2ae07042e +size 330974 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_open_drawer_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_open_drawer_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..5212f207be2477583f7cbb2922348061c784dc21 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_open_drawer_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f7a11f5f9d53ccff53c51b0b631dfdda2b743411d2929fec47a08f7e033d90a +size 176724 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_pick_random_object.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_pick_random_object.png new file mode 100644 index 0000000000000000000000000000000000000000..a12fdfc5199fe51eb6fc8df09423beed4a076e5d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_pick_random_object.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0e675f7cb87ab5aad02e7205788c46ba7f34b7887040ff31fca980bc30dcf560 +size 200310 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_put_apple_in_closed_top_drawer.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_put_apple_in_closed_top_drawer.png new file mode 100644 index 0000000000000000000000000000000000000000..29bf609af5530c95658f55a52df3a2a5e8abc60a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/google_robot_put_apple_in_closed_top_drawer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9071a2fff6b07e570ca54f52292e817b7dcef552c3a8384ad6a0a429ff61f52b +size 226441 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_carrot_on_plate_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_carrot_on_plate_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..6c1ceb5d2baa0a51cd33365ffb053a070d8b17e8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_carrot_on_plate_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a679af0d2292f6b3b18fba49af9d3499e86274dadfe65ed5ca70625e28b2d559 +size 266629 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_close_drawer.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_close_drawer.png new file mode 100644 index 0000000000000000000000000000000000000000..98bbbb50ed569121fa80d61d7fdc56a744a454d3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_close_drawer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02ca980e8409b54e8c99bed4adcab8aebafd91cb7259a8c59b27bdf400dce1a8 +size 438636 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_open_drawer.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_open_drawer.png new file mode 100644 index 0000000000000000000000000000000000000000..7fee221d6d37b3ea3d6617a0fc3702f19b5a9f03 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_open_drawer.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24d4f5cf3e5b9492c9191a4c2d02c449582bf1fae048d358fce5619e06017c13 +size 427026 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_basket_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_basket_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..809bf9c55a553dba05dfbad88a94233c5e74c9a4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_basket_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3f33d2af8e7341a89f0fbc4acf28ad10f1617361618922e86a7d106a235a45d6 +size 220043 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_sink_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_sink_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..da86cae2fc1b8e88ad7065910a88f7135810f41e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_put_eggplant_in_sink_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05efca517ca544d99ac21b7538421912422d1aee50ff68a02b1d8771874f7d15 +size 248333 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_spoon_on_towel_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_spoon_on_towel_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..48738949a7b24431ed888cbb4b4a73f37810f58b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_spoon_on_towel_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf3fd15284e2b7d2cdee4af389d0fdffbe7b75b7a9e20debee6fd95415e06322 +size 273513 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_stack_cube_visual_matching.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_stack_cube_visual_matching.png new file mode 100644 index 0000000000000000000000000000000000000000..485b77be664875ed07a8d6208e1348f9437b2748 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/example_visualization/widowx_stack_cube_visual_matching.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a33c74fc5cbf8ace85bfbddd4a89cb285c8fc611d90acabd1866c2c475d2ab6 +size 263079 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/fSpy_calibration_example.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/fSpy_calibration_example.png new file mode 100644 index 0000000000000000000000000000000000000000..c414129fe579cf8f0f95e1883d8ebae680db6868 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/fSpy_calibration_example.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d12f2c298d3ee005915f6d2b8c849d91a58d164434b30bdfbfa9ba57c5d83d6 +size 1050015 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/images/teaser.png b/Isaac-GR00T/external_dependencies/SimplerEnv/images/teaser.png new file mode 100644 index 0000000000000000000000000000000000000000..2f05a8b7d612c025d241853ebfc25e19ac6c4400 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/images/teaser.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:01393fff47029e40f1c9c3c983fc0a55350dab623d9a629f75c2fd2232e125ef +size 828790 diff --git a/Isaac-GR00T/external_dependencies/SimplerEnv/simpler_env/utils/fonts/UbuntuMono-R.ttf b/Isaac-GR00T/external_dependencies/SimplerEnv/simpler_env/utils/fonts/UbuntuMono-R.ttf new file mode 100644 index 0000000000000000000000000000000000000000..56b9138f421bc456778f7fc74540523b60155445 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/SimplerEnv/simpler_env/utils/fonts/UbuntuMono-R.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b35dd9d2131d5d83a9b87fe9ad22c6288fa3d17688d43302c14da29812417d63 +size 205748 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.pdf b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.pdf new file mode 100644 index 0000000000000000000000000000000000000000..10b494856efd77fbccc2f0deb785d8c60347eb0b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15d02d0610cb71cd3fe50519bd9fada09ba8276a7b52d41e34abea30a8a4cd4e +size 3894805 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.png b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.png new file mode 100644 index 0000000000000000000000000000000000000000..8b2f1302a009f4420038adbcd0178abb68380e7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/images/fig_task_v6.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:966b02ca751829951ce7d5587b3c4c78acffde3c9e290822f25f8d3bdad8f27e +size 223248 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/__init__.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop.py new file mode 100644 index 0000000000000000000000000000000000000000..c32104c8ff075c645ab9ec23ed4b31418d4e0202 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop.py @@ -0,0 +1,1800 @@ +import os +import random +import xml.etree.ElementTree as ET +from copy import deepcopy + +import numpy as np +import robosuite +import robosuite.utils.transform_utils as T +from robosuite.environments.manipulation.manipulation_env import ManipulationEnv +from robosuite.models.tasks import ManipulationTask +from robosuite.utils.errors import RandomizationError +from robosuite.utils.mjcf_utils import ( + array_to_string, + find_elements, + xml_path_completion, +) +from robosuite.models.robots.robot_model import REGISTERED_ROBOTS +from robosuite.utils.observables import Observable, sensor +from robosuite.environments.base import EnvMeta +from scipy.spatial.transform import Rotation + +from robosuite.models.robots import PandaOmron +import yaml + +import robocasa +import robocasa.macros as macros +from robocasa.models.scenes.scene_builder import FIXTURES +from robocasa.models.scenes.scene_utils import initialize_fixture, load_style_config +import robocasa.utils.camera_utils as CamUtils +import robocasa.utils.object_utils as OU +import robocasa.models.scenes.scene_registry as SceneRegistry +from robocasa.models.scenes import TabletopArena +from robocasa.models.fixtures import * +from robocasa.models.robots import * +from robocasa.models.objects.kitchen_object_utils import sample_kitchen_object +from robocasa.models.objects.objects import MJCFObject +from robocasa.utils.placement_samplers import ( + SequentialCompositeSampler, + UniformRandomSampler, +) +from robocasa.utils.texture_swap import ( + get_random_textures, + replace_cab_textures, + replace_counter_top_texture, + replace_floor_texture, + replace_wall_texture, +) +from robocasa.utils.config_utils import refactor_composite_controller_config + + +REGISTERED_TABLETOP_EVNS = {} + + +def register_tabletop_env(target_class): + REGISTERED_TABLETOP_EVNS[target_class.__name__] = target_class + + +class TabletopEnvMeta(EnvMeta): + """Metaclass for registering robocasa environments""" + + def __new__(meta, name, bases, class_dict): + cls = super().__new__(meta, name, bases, class_dict) + register_tabletop_env(cls) + return cls + + +_ROBOT_POS_OFFSETS: dict[str, list[float]] = { + "GR1FloatingBody": [0, 0, 0.97], + "GR1": [0, 0, 0.97], + "GR1FixedLowerBody": [0, 0, 0.97], + "GR1FixedLowerBodyInspireHands": [0, 0, 0.97], + "GR1FixedLowerBodyFourierHands": [0, 0, 0.97], + "GR1ArmsOnly": [0, 0, 0.97], + "GR1ArmsOnlyInspireHands": [0, 0, 0.97], + "GR1ArmsOnlyFourierHands": [0, 0, 0.97], + "GR1ArmsAndWaistFourierHands": [0, 0, 0.97], + "BDM1FloatingBody": [0, 0, 0.97], + "BDM1": [0, 0, 0.97], + "BDM1FixedLowerBody": [0, 0, 0.97], + "BDM1ArmsOnly": [0, 0, 0.97], + "G1FloatingBody": [0, -0.33, 0], + "G1": [0, -0.33, 0], + "G1FixedLowerBody": [0, -0.33, 0], + "GoogleRobot": [0, 0, 0], + "NeoFixedLowerBody": [0, -0.05, 0.8], + "NeoArmsOnly": [0, -0.05, 0.8], +} + + +class Tabletop(ManipulationEnv, metaclass=TabletopEnvMeta): + """ + Initialized a Base Tabletop environment. + + Args: + robots: Specification for specific robot arm(s) to be instantiated within this env + (e.g: "Sawyer" would generate one arm; ["Panda", "Panda", "Sawyer"] would generate three robot arms) + + env_configuration (str): Specifies how to position the robot(s) within the environment. Default is "default", + which should be interpreted accordingly by any subclasses. + + controller_configs (str or list of dict): If set, contains relevant controller parameters for creating a + custom controller. Else, uses the default controller for this specific task. Should either be single + dict if same controller is to be used for all robots or else it should be a list of the same length as + "robots" param + + base_types (None or str or list of str): type of base, used to instantiate base models from base factory. + Default is "default", which is the default base associated with the robot(s) the 'robots' specification. + None results in no base, and any other (valid) model overrides the default base. Should either be + single str if same base type is to be used for all robots or else it should be a list of the same + length as "robots" param + + gripper_types (None or str or list of str): type of gripper, used to instantiate + gripper models from gripper factory. Default is "default", which is the default grippers(s) associated + with the robot(s) the 'robots' specification. None removes the gripper, and any other (valid) model + overrides the default gripper. Should either be single str if same gripper type is to be used for all + robots or else it should be a list of the same length as "robots" param + + initialization_noise (dict or list of dict): Dict containing the initialization noise parameters. + The expected keys and corresponding value types are specified below: + + :`'magnitude'`: The scale factor of uni-variate random noise applied to each of a robot's given initial + joint positions. Setting this value to `None` or 0.0 results in no noise being applied. + If "gaussian" type of noise is applied then this magnitude scales the standard deviation applied, + If "uniform" type of noise is applied then this magnitude sets the bounds of the sampling range + :`'type'`: Type of noise to apply. Can either specify "gaussian" or "uniform" + + Should either be single dict if same noise value is to be used for all robots or else it should be a + list of the same length as "robots" param + + :Note: Specifying "default" will automatically use the default noise settings. + Specifying None will automatically create the required dict with "magnitude" set to 0.0. + + use_camera_obs (bool): if True, every observation includes rendered image(s) + + placement_initializer (ObjectPositionSampler): if provided, will be used to place objects on every reset, + else a UniformRandomSampler is used by default. + + has_renderer (bool): If true, render the simulation state in + a viewer instead of headless mode. + + has_offscreen_renderer (bool): True if using off-screen rendering + + render_camera (str): Name of camera to render if `has_renderer` is True. Setting this value to 'None' + will result in the default angle being applied, which is useful as it can be dragged / panned by + the user using the mouse + + render_collision_mesh (bool): True if rendering collision meshes in camera. False otherwise. + + render_visual_mesh (bool): True if rendering visual meshes in camera. False otherwise. + + render_gpu_device_id (int): corresponds to the GPU device id to use for offscreen rendering. + Defaults to -1, in which case the device will be inferred from environment variables + (GPUS or CUDA_VISIBLE_DEVICES). + + control_freq (float): how many control signals to receive in every second. This sets the abase of + simulation time that passes between every action input. + + horizon (int): Every episode lasts for exactly @horizon timesteps. + + ignore_done (bool): True if never terminating the environment (ignore @horizon). + + hard_reset (bool): If True, re-loads model, sim, and render object upon a reset call, else, + only calls sim.reset and resets all robosuite-internal variables + + camera_names (str or list of str): name of camera to be rendered. Should either be single str if + same name is to be used for all cameras' rendering or else it should be a list of cameras to render. + + :Note: At least one camera must be specified if @use_camera_obs is True. + + :Note: To render all robots' cameras of a certain type (e.g.: "robotview" or "eye_in_hand"), use the + convention "all-{name}" (e.g.: "all-robotview") to automatically render all camera images from each + robot's camera list). + + camera_heights (int or list of int): height of camera frame. Should either be single int if + same height is to be used for all cameras' frames or else it should be a list of the same length as + "camera names" param. + + camera_widths (int or list of int): width of camera frame. Should either be single int if + same width is to be used for all cameras' frames or else it should be a list of the same length as + "camera names" param. + + camera_depths (bool or list of bool): True if rendering RGB-D, and RGB otherwise. Should either be single + bool if same depth setting is to be used for all cameras or else it should be a list of the same length as + "camera names" param. + + renderer (str): Specifies which renderer to use. + + renderer_config (dict): dictionary for the renderer configurations + + init_robot_base_pos (str): name of the fixture to place the near. If None, will randomly select a fixture. + + seed (int): environment seed. Default is None, where environment is unseeded, ie. random + + layout_and_style_ids (list of list of int): list of layout and style ids to use for the tabletop environment. + + layout_ids ((list of) TabletopLayoutType or int): layout id(s) to use for the tabletop environment. -1 and None specify all layouts + + style_ids ((list of) StyleType or int): style id(s) to use for the tabletop. -1 and None specify all styles. + + generative_textures (str): if set to "100p", will use AI generated textures + + obj_registries (tuple of str): tuple containing the object registries to use for sampling objects. + can contain "objaverse" and/or "aigen" to sample objects from objaverse, AI generated, or both. + + prefer_leading_registry (bool): whether to bias the sampling towards the first registry in obj_registries + + obj_instance_split (str): string for specifying a custom set of object instances to use. "A" specifies + all but the last 3 object instances (or the first half - whichever is larger), "B" specifies the + rest, and None specifies all. + + use_distractors (bool): if True, will add distractor objects to the scene + + distractor_config (dict): Configuration for distractor objects and fixtures. Format: + { + "regions": { + "back_edge": { # Name of region + "placement": { + "pos": (0, 1), # Position relative to table (-1 to 1) + "size": (1.2, 0.2), # Size of region in meters + }, + "fixtures": [ # List of fixtures to place in this region + { + "type": "mug_tree", # Type of fixture + "count": (0, 3), # Random number between 0-3 (optional, default is 1) + }, + { + "type": "plant", + "count": 1, + } + ], + "objects": [ # List of objects to place in this region + { + "type": ["fruit", "vegetable"], # Object type(s) + "count": (2, 4), + } + ] + }, + "left_side": { + "placement": { + "pos": (-1, 0), + "size": (0.2, 0.6), + }, + "fixtures": [...], + "objects": [...] + } + } + } + + translucent_robot (bool): if True, will make the robot appear translucent during rendering + + randomize_cameras (bool): if True, will add gaussian noise to the position and rotation of the + wrist and agentview cameras + + env_lang (str): kept for backwards compatibility + """ + + VALID_LAYOUTS = [0, 1, 2, 3, 4, 5] + + def __init__( + self, + robots, + env_configuration="default", + controller_configs=None, + gripper_types="default", + base_types="default", + initialization_noise="default", + use_camera_obs=True, + use_object_obs=True, # currently unused variable + reward_scale=1.0, # currently unused variable + reward_shaping=False, # currently unused variables + placement_initializer=None, + has_renderer=False, + has_offscreen_renderer=True, + render_camera="robot0_agentview_center", + render_collision_mesh=False, + render_visual_mesh=True, + render_gpu_device_id=-1, + control_freq=20, + horizon=1000, + ignore_done=True, + hard_reset=True, + camera_names="agentview", + camera_heights=256, + camera_widths=256, + camera_depths=False, + renderer="mujoco", + renderer_config=None, + init_robot_base_pos=None, + seed=None, + layout_and_style_ids=None, + layout_ids=None, + style_ids=None, + scene_split=None, # unsued, for backwards compatibility + generative_textures=None, + obj_registries=("objaverse", "sketchfab", "lightwheel"), + prefer_leading_registry=False, + obj_instance_split=None, + use_distractors=False, + distractor_config=None, + translucent_robot=False, + randomize_cameras=False, + env_lang="en", + ): + self.init_robot_base_pos = init_robot_base_pos + + # object placement initializer + self.placement_initializer = placement_initializer + self.obj_registries = obj_registries + self.prefer_leading_registry = prefer_leading_registry + self.obj_instance_split = obj_instance_split + + if layout_and_style_ids is not None: + assert ( + layout_ids is None and style_ids is None + ), "layout_ids and style_ids must both be set to None if layout_and_style_ids is set" + self.layout_and_style_ids = layout_and_style_ids + else: + layout_ids = SceneRegistry.unpack_tabletop_layout_ids(layout_ids) + style_ids = SceneRegistry.unpack_style_ids(style_ids) + self.layout_and_style_ids = [(l, s) for l in layout_ids for s in style_ids] + + # remove excluded layouts + self.layout_and_style_ids = [ + (int(l), int(s)) + for (l, s) in self.layout_and_style_ids + if l in self.VALID_LAYOUTS + ] + assert len(self.layout_and_style_ids) > 0 + + assert generative_textures in [None, False, "100p"] + self.generative_textures = generative_textures + + assert distractor_config is None or use_distractors + self.use_distractors = use_distractors + self.distractor_config = distractor_config + self.translucent_robot = translucent_robot + self.randomize_cameras = randomize_cameras + + # intialize cameras + self._cam_configs = deepcopy(CamUtils.CAM_CONFIGS) + + if isinstance(robots, str): + robots = [robots] + + # backward compatibility: rename all robots that were previously called PandaMobile -> PandaOmron + for i in range(len(robots)): + if robots[i] == "PandaMobile": + robots[i] = "PandaOmron" + assert len(robots) == 1 + + # set up currently unused variables (used in robosuite) + self.use_object_obs = use_object_obs + self.reward_scale = reward_scale + self.reward_shaping = reward_shaping + + if controller_configs is not None: + # detect if using stale controller configs (before robosuite v1.5.1) and update to new convention + arms = REGISTERED_ROBOTS[robots[0]].arms + controller_configs = refactor_composite_controller_config( + controller_configs, robots[0], arms + ) + if robots[0] == "PandaOmron": + if "composite_controller_specific_configs" not in controller_configs: + controller_configs["composite_controller_specific_configs"] = {} + controller_configs["composite_controller_specific_configs"][ + "body_part_ordering" + ] = ["right", "right_gripper", "base", "torso"] + + super().__init__( + robots=robots, + env_configuration=env_configuration, + controller_configs=controller_configs, + base_types=base_types, + gripper_types=gripper_types, + initialization_noise=initialization_noise, + use_camera_obs=use_camera_obs, + has_renderer=has_renderer, + has_offscreen_renderer=has_offscreen_renderer, + render_camera=render_camera, + render_collision_mesh=render_collision_mesh, + render_visual_mesh=render_visual_mesh, + render_gpu_device_id=render_gpu_device_id, + control_freq=control_freq, + lite_physics=True, + horizon=horizon, + ignore_done=ignore_done, + hard_reset=hard_reset, + camera_names=camera_names, + camera_heights=camera_heights, + camera_widths=camera_widths, + camera_depths=camera_depths, + renderer=renderer, + renderer_config=renderer_config, + seed=seed, + ) + + def _load_model_monitor_wrapper(func): + """Wrapper to count number of times _load_model is called""" + + def wrapper(self, *args, **kwargs): + if not hasattr(self, "_load_model_count"): + self._load_model_count = 0 + self._load_model_count += 1 + + if self._load_model_count % 10 == 0: + print( + f"WARNING: _load_model has been called over {self._load_model_count} times!" + ) + + return func(self, *args, **kwargs) + + return wrapper + + @_load_model_monitor_wrapper + def _load_model(self, reload=True): + """ + Loads an xml model, puts it in self.model + """ + super()._load_model() + + for robot in self.robots: + if isinstance(robot.robot_model, PandaOmron): + robot.init_qpos = ( + -0.01612974, + -1.03446714, + -0.02397936, + -2.27550888, + 0.03932365, + 1.51639493, + 0.69615947, + ) + robot.init_torso_qpos = np.array([0.0]) + + # determine sample layout and style + # Set layout_id + if "layout_id" in self._ep_meta: + self.layout_id = self._ep_meta["layout_id"] + else: + layout_id, _ = self.rng.choice(self.layout_and_style_ids) + self.layout_id = int(layout_id) + + # Set style_id + if "style_id" in self._ep_meta: + self.style_id = self._ep_meta["style_id"] + else: + _, style_id = self.rng.choice(self.layout_and_style_ids) + self.style_id = int(style_id) + + if macros.VERBOSE: + print("layout: {}, style: {}".format(self.layout_id, self.style_id)) + + # to be set later inside edit_model_xml function + self._curr_gen_fixtures = None + + # setup scene + self.mujoco_arena = TabletopArena( + layout_id=self.layout_id, + style_id=self.style_id, + rng=self.rng, + ) + # Arena always gets set to zero origin + self.mujoco_arena.set_origin([0, 0, 0]) + self.set_cameras() # setup cameras + + # setup rendering for this layout + if self.renderer == "mjviewer": + camera_config = CamUtils.DEFAULT_LAYOUT_CAM + self.renderer_config = {"cam_config": camera_config} + + # setup fixtures + self.fixture_cfgs = self.mujoco_arena.get_fixture_cfgs() + self.fixture_cfgs.extend(self._get_distractor_fixture_cfgs()) + self.fixtures = {cfg["name"]: cfg["model"] for cfg in self.fixture_cfgs} + + # setup scene, robots, objects + self.model = ManipulationTask( + mujoco_arena=self.mujoco_arena, + mujoco_robots=[robot.robot_model for robot in self.robots], + mujoco_objects=list(self.fixtures.values()), + ) + + # setup fixture locations + fxtr_placement_initializer = self._get_placement_initializer( + self.fixture_cfgs, z_offset=0.0 + ) + fxtr_placements = None + for i in range(10): + try: + fxtr_placements = fxtr_placement_initializer.sample() + except RandomizationError as e: + if macros.VERBOSE: + print("Randomization error in initial placement. Try #{}".format(i)) + continue + break + if fxtr_placements is None: + if macros.VERBOSE: + print("Could not place fixtures. Trying again with self._load_model()") + self._load_model() + return + self.fxtr_placements = fxtr_placements + # Loop through all objects and reset their positions + for obj_pos, obj_quat, obj in fxtr_placements.values(): + assert isinstance(obj, Fixture) + obj.set_pos(obj_pos) + + # hacky code to set orientation + obj.set_euler(T.mat2euler(T.quat2mat(T.convert_quat(obj_quat, "xyzw")))) + + # setup internal references related to fixtures + self._setup_table_references() + + robot_base_pos, robot_base_ori = self.compute_robot_base_placement_pose() + robot_model = self.robots[0].robot_model + robot_model.set_base_xpos(robot_base_pos) + robot_model.set_base_ori(robot_base_ori) + + # create and place objects + self._create_objects() + + # setup object locations + self.placement_initializer = self._get_placement_initializer(self.object_cfgs) + object_placements = None + for i in range(1): + try: + object_placements = self.placement_initializer.sample( + placed_objects=self.fxtr_placements + ) + except RandomizationError as e: + if macros.VERBOSE: + print(f"Randomization error in initial placement. {e}. Try #{i}") + continue + break + if object_placements is None: + if macros.VERBOSE: + print("Could not place objects. Trying again with self._load_model()") + self._load_model() + return + self.object_placements = object_placements + + def _get_distractor_fixture_cfgs(self): + """Returns configurations for distractor fixtures to be placed in the scene""" + if self.distractor_config is None or self.layout_id == 1: + return [] + + # Load style config + style_path = SceneRegistry.get_style_path(self.style_id) + with open(style_path, "r") as f: + style = yaml.safe_load(f) + + processed_configs = [] + + # Process each region's fixtures + for region_name, region_config in self.distractor_config.get( + "regions", {} + ).items(): + placement = region_config.get("placement", {}) + + for fixture_config in region_config.get("fixtures", []): + count_spec = fixture_config.get("count", 1) + if isinstance(count_spec, (list, tuple)): + min_count = count_spec[0] + max_count = count_spec[1] + else: + min_count = max_count = count_spec + + for i in range(max_count): + cfg = { + "name": f"distractor_fixture_{region_name}_{fixture_config['type']}_{i}", + "type": fixture_config["type"], + "placement": { + **placement, + "optional": i >= min_count, + "fixture": "table_main_group", + }, + } + + if fixture_config.get("scale", None): + cfg["scale"] = fixture_config["scale"] + + # Apply style configs + default_config = load_style_config(style, cfg) + for k, v in cfg.items(): + default_config[k] = v + cfg = default_config + + # Convert to fixture class and initialize + cfg["type"] = FIXTURES[cfg["type"]] + fixture = initialize_fixture(cfg, [], rng=self.rng) + cfg["model"] = fixture + cfg["type"] = "fixture" + + processed_configs.append(cfg) + + return processed_configs + + def _get_distractor_obj_cfgs(self): + """Returns configurations for distractor objects""" + if self.distractor_config is None: + return [] + + cfgs = [] + + counter = self.fixture_refs.get( + "counter", self.get_fixture(id=FixtureType.COUNTER) + ) + + # Process each region's objects + for region_name, region_config in self.distractor_config.get( + "regions", {} + ).items(): + placement = region_config.get("placement", {}) + + for obj_config in region_config.get("objects", []): + count_spec = obj_config.get("count", 1) + if isinstance(count_spec, (list, tuple)): + min_count = count_spec[0] + max_count = self.rng.integers(min_count, count_spec[1] + 1) + else: + min_count = max_count = count_spec + + for i in range(max_count): + if isinstance(obj_config["type"], str): + obj_type = obj_config["type"] + else: + obj_type = self.rng.choice(obj_config["type"]) + cfgs.append( + dict( + name=f"distractor_obj_{region_name}_{obj_type}_{i}", + type="object", + obj_groups=obj_type, + graspable=False, + placement={ + **placement, + "optional": i >= min_count, + "fixture": counter, + }, + ) + ) + + return cfgs + + def _create_objects(self): + """ + Creates and places objects in the tabletop environment. + Helper function called by _load_model() + """ + # add objects + self.objects = {} + if "object_cfgs" in self._ep_meta: + self.object_cfgs = self._ep_meta["object_cfgs"] + for obj_num, cfg in enumerate(self.object_cfgs): + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + model, info = self._create_obj(cfg) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + else: + self.object_cfgs = self._get_obj_cfgs() + num_objects = len(self.object_cfgs) + exclude_cat = [] + self.object_cfgs.extend(self._get_distractor_obj_cfgs()) + addl_obj_cfgs = [] + for obj_num, cfg in enumerate(self.object_cfgs): + cfg["type"] = "object" + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + if obj_num >= num_objects: + # objects part of distractors + cfg["exclude_cat"] = exclude_cat + model, info = self._create_obj(cfg) + if obj_num < num_objects: + # objects part of the task + exclude_cat.append(info["cat"]) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + try_to_place_in = cfg["placement"].get("try_to_place_in", None) + + # place object in a container and add container as an object to the scene + if try_to_place_in and ( + "in_container" in cfg["info"]["groups_containing_sampled_obj"] + ): + container_cfg = { + "name": cfg["name"] + "_container", + "obj_groups": cfg["placement"].get("try_to_place_in"), + "placement": deepcopy(cfg["placement"]), + "type": "object", + } + + container_kwargs = cfg["placement"].get("container_kwargs", None) + if container_kwargs is not None: + for k, v in container_kwargs.items(): + container_cfg[k] = v + + # add in the new object to the model + addl_obj_cfgs.append(container_cfg) + model, info = self._create_obj(container_cfg) + container_cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + reference = container_cfg["name"] + site_id = cfg["placement"].get("site_id", None) + if site_id is not None: + reference = (reference, site_id) + + # modify object config to lie inside of container + cfg["placement"] = dict( + size=(0.01, 0.01), + ensure_object_boundary_in_range=False, + sample_args=dict( + reference=reference, + ), + ) + + # place the additional objects (usually containers) in first + self.object_cfgs = addl_obj_cfgs + self.object_cfgs + + # # remove objects that didn't get created + # self.object_cfgs = [cfg for cfg in self.object_cfgs if "model" in cfg] + + def _create_obj(self, cfg): + """ + Helper function for creating objects. + Called by _create_objects() + """ + if "info" in cfg: + """ + if cfg has "info" key in it, that means it is storing meta data already + that indicates which object we should be using. + set the obj_groups to this path to do deterministic playback + """ + mjcf_path = cfg["info"]["mjcf_path"] + # replace with correct base path + new_base_path = os.path.join(robocasa.models.assets_root, "objects") + new_path = os.path.join(new_base_path, mjcf_path.split("/objects/")[-1]) + obj_groups = new_path + exclude_obj_groups = None + exclude_cat = None + else: + obj_groups = cfg.get("obj_groups", "all") + exclude_obj_groups = cfg.get("exclude_obj_groups", None) + exclude_cat = cfg.get("exclude_cat", None) + object_kwargs, object_info = self.sample_object( + obj_groups, + exclude_groups=exclude_obj_groups, + exclude_cat=exclude_cat, + graspable=cfg.get("graspable", None), + washable=cfg.get("washable", None), + microwavable=cfg.get("microwavable", None), + cookable=cfg.get("cookable", None), + freezable=cfg.get("freezable", None), + max_size=cfg.get("max_size", (None, None, None)), + object_scale=cfg.get("object_scale", None), + ) + info = object_info + + object = MJCFObject(name=cfg["name"], **object_kwargs) + + return object, info + + def _setup_table_references(self): + """ + setup fixtures (and their references). this function is called within load_model function for tabletops + """ + serialized_refs = self._ep_meta.get("fixture_refs", {}) + # unserialize refs + self.fixture_refs = { + k: self.get_fixture(v) for (k, v) in serialized_refs.items() + } + + def _reset_observables(self): + if self.hard_reset: + self._observables = self._setup_observables() + + def compute_robot_base_placement_pose(self, offset=None): + """ + steps: + 1. compute offset relative to the counter + 2. transform offset to global coordinates + + Args: + offset (list): offset to add to the base position + + """ + # step 1: find vase fixture closest to robot + # get first counter in the environment + base_fixtures = [ + fxtr for fxtr in self.fixtures.values() if isinstance(fxtr, Counter) + ] + + # use first counter available + base_fixture = base_fixtures[0] + + # step 2: compute offset relative to this counter + cntr_y = base_fixture.get_ext_sites(relative=True)[0][1] + base_to_edge = [ + 0, + cntr_y - 0.20, + 0, + ] + if offset is not None: + base_to_edge[0] += offset[0] + base_to_edge[1] += offset[1] + + # apply robot-specific offset relative to the base fixture for x,y dims + robot_model = self.robots[0].robot_model + robot_class_name = robot_model.__class__.__name__ + if robot_class_name in _ROBOT_POS_OFFSETS: + for dimension in range(0, 2): + base_to_edge[dimension] += _ROBOT_POS_OFFSETS[robot_class_name][ + dimension + ] + else: + raise ValueError + + # step 3: transform offset to global coordinates + robot_base_pos = np.zeros(3) + robot_base_pos[0:2] = OU.get_pos_after_rel_offset(base_fixture, base_to_edge)[ + 0:2 + ] + # apply robot-specific absolutely for z dim + if robot_class_name in _ROBOT_POS_OFFSETS: + robot_base_pos[2] = _ROBOT_POS_OFFSETS[robot_class_name][2] + robot_base_ori = np.array([0, 0, base_fixture.rot + np.pi / 2]) + + return robot_base_pos, robot_base_ori + + def _get_placement_initializer(self, cfg_list, z_offset=0.01): + """ + Creates a placement initializer for the objects/fixtures based on the specifications in the configurations list + + Args: + cfg_list (list): list of object configurations + + z_offset (float): offset in z direction + + Returns: + SequentialCompositeSampler: placement initializer + + """ + + placement_initializer = SequentialCompositeSampler( + name="SceneSampler", rng=self.rng + ) + + for obj_i, cfg in enumerate(cfg_list): + # determine which object is being placed + if cfg["type"] == "fixture": + mj_obj = self.fixtures[cfg["name"]] + elif cfg["type"] == "object": + mj_obj = self.objects[cfg["name"]] + else: + raise ValueError + + placement = cfg.get("placement", None) + if placement is None: + continue + fixture_id = placement.get("fixture", None) + + if fixture_id is not None: + # get fixture to place object on + fixture = self.get_fixture( + id=fixture_id, + ref=placement.get("ref", None), + ) + + # calculate the total available space where object could be placed + sample_region_kwargs = placement.get("sample_region_kwargs", {}) + reset_region = fixture.sample_reset_region( + env=self, **sample_region_kwargs + ) + outer_size = reset_region["size"] + margin = placement.get("margin", 0.04) + outer_size = (outer_size[0] - margin, outer_size[1] - margin) + + # calculate the size of the inner region where object will actually be placed + target_size = placement.get("size", None) + if target_size is not None: + target_size = deepcopy(list(target_size)) + for size_dim in [0, 1]: + if target_size[size_dim] == "obj": + target_size[size_dim] = mj_obj.size[size_dim] + 0.005 + if target_size[size_dim] == "obj.x": + target_size[size_dim] = mj_obj.size[0] + 0.005 + if target_size[size_dim] == "obj.y": + target_size[size_dim] = mj_obj.size[1] + 0.005 + inner_size = np.min((outer_size, target_size), axis=0) + else: + inner_size = outer_size + + inner_xpos, inner_ypos = placement.get("pos", (None, None)) + offset = placement.get("offset", (0.0, 0.0)) + + # center inner region within outer region + if inner_xpos == "ref": + # compute optimal placement of inner region to match up with the reference fixture + x_halfsize = outer_size[0] / 2 - inner_size[0] / 2 + if x_halfsize == 0.0: + inner_xpos = 0.0 + else: + ref_fixture = self.get_fixture( + placement["sample_region_kwargs"]["ref"] + ) + ref_pos = ref_fixture.pos + fixture_to_ref = OU.get_rel_transform(fixture, ref_fixture)[0] + outer_to_ref = fixture_to_ref - reset_region["offset"] + inner_xpos = outer_to_ref[0] / x_halfsize + inner_xpos = np.clip(inner_xpos, a_min=-1.0, a_max=1.0) + elif inner_xpos is None: + inner_xpos = 0.0 + + if inner_ypos is None: + inner_ypos = 0.0 + # offset for inner region + intra_offset = ( + (outer_size[0] / 2 - inner_size[0] / 2) * inner_xpos + offset[0], + (outer_size[1] / 2 - inner_size[1] / 2) * inner_ypos + offset[1], + ) + + # center surface point of entire region + ref_pos = fixture.pos + [0, 0, reset_region["offset"][2]] + ref_rot = fixture.rot + + # x, y, and rotational ranges for randomization + x_range = ( + np.array([-inner_size[0] / 2, inner_size[0] / 2]) + + reset_region["offset"][0] + + intra_offset[0] + ) + y_range = ( + np.array([-inner_size[1] / 2, inner_size[1] / 2]) + + reset_region["offset"][1] + + intra_offset[1] + ) + rotation = placement.get("rotation", np.array([-np.pi / 4, np.pi / 4])) + else: + target_size = placement.get("size", None) + x_range = np.array([-target_size[0] / 2, target_size[0] / 2]) + y_range = np.array([-target_size[1] / 2, target_size[1] / 2]) + rotation = placement.get("rotation", np.array([-np.pi / 4, np.pi / 4])) + ref_pos = [0, 0, 0] + ref_rot = 0.0 + + if macros.SHOW_SITES is True: + """ + show outer reset region in blue + """ + pos_to_vis = deepcopy(ref_pos) + pos_to_vis[:2] += T.rotate_2d_point( + [reset_region["offset"][0], reset_region["offset"][1]], rot=ref_rot + ) + size_to_vis = np.concatenate( + [ + np.abs( + T.rotate_2d_point( + [outer_size[0] / 2, outer_size[1] / 2], rot=ref_rot + ) + ), + [0.001], + ] + ) + site_str = """""".format( + pos=array_to_string(pos_to_vis), + size=array_to_string(size_to_vis), + postfix=str(obj_i), + ) + site_tree = ET.fromstring(site_str) + self.model.worldbody.append(site_tree) + + """ + show inner reset region in red + """ + pos_to_vis = deepcopy(ref_pos) + pos_to_vis[:2] += T.rotate_2d_point( + [np.mean(x_range), np.mean(y_range)], rot=ref_rot + ) + size_to_vis = np.concatenate( + [ + np.abs( + T.rotate_2d_point( + [ + (x_range[1] - x_range[0]) / 2, + (y_range[1] - y_range[0]) / 2, + ], + rot=ref_rot, + ) + ), + [0.002], + ] + ) + site_str = """""".format( + pos=array_to_string(pos_to_vis), + size=array_to_string(size_to_vis), + postfix=str(obj_i), + ) + site_tree = ET.fromstring(site_str) + self.model.worldbody.append(site_tree) + + placement_initializer.append_sampler( + sampler=UniformRandomSampler( + name="{}_Sampler".format(cfg["name"]), + mujoco_objects=mj_obj, + x_range=x_range, + y_range=y_range, + rotation=rotation, + ensure_object_boundary_in_range=placement.get( + "ensure_object_boundary_in_range", True + ), + ensure_valid_placement=placement.get( + "ensure_valid_placement", True + ), + ensure_object_in_ref_region=placement.get( + "ensure_object_in_ref_region", False + ), + ensure_object_out_of_ref_region=placement.get( + "ensure_object_out_of_ref_region", False + ), + reference_pos=ref_pos, + reference_rot=ref_rot, + z_offset=z_offset, + rng=self.rng, + rotation_axis=placement.get("rotation_axis", "z"), + num_attempts=100 if placement.get("optional", False) else 5000, + ), + sample_args=placement.get("sample_args", None), + optional=placement.get("optional", False), + ) + + return placement_initializer + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + # Reset all object positions using initializer sampler if we're not directly loading from an xml + if not self.deterministic_reset and self.placement_initializer is not None: + # use pre-computed object placements + object_placements = self.object_placements + + # Loop through all objects and reset their positions + for obj_pos, obj_quat, obj in object_placements.values(): + for j in obj.joints: + # Reset free joints only + if np.size(self.sim.data.get_joint_qpos(j)) == 7: + self.sim.data.set_joint_qpos( + j, np.concatenate([np.array(obj_pos), np.array(obj_quat)]) + ) + + # step through a few timesteps to settle objects + action = np.zeros(self.action_spec[0].shape) # apply empty action + + # Since the env.step frequency is slower than the mjsim timestep frequency, the internal controller will output + # multiple torque commands in between new high level action commands. Therefore, we need to denote via + # 'policy_step' whether the current step we're taking is simply an internal update of the controller, + # or an actual policy update + policy_step = True + + # zero_action only works with IK in delta mode. + # When evaluating, not calling IK and directly applying zero_action leads to an error. + if len(self.robots) == 1 and "GR1" in self.robots[0].name: + self.robots[0].composite_controller.reset() + policy_step = False + + # Loop through the simulation at the model timestep rate until we're ready to take the next policy step + # (as defined by the control frequency specified at the environment level) + for i in range(10 * int(self.control_timestep / self.model_timestep)): + self.sim.step1() + self._pre_action(action, policy_step) + self.sim.step2() + policy_step = False + + # Only needed for GR1 + if "GR1" in self.robots[0].name: + for joint_name in ["robot0_l_elbow_pitch", "robot0_r_elbow_pitch"]: + l_elbow_pitch_id = self.sim.model.joint_name2id(joint_name) + l_elbow_pitch_range = self.sim.model.jnt_range[l_elbow_pitch_id] + self.sim.data.qpos[self.sim.model.get_joint_qpos_addr(joint_name)] = ( + l_elbow_pitch_range[0] * 0.7 + l_elbow_pitch_range[1] * 0.3 + ) + elif "BDM1" in self.robots[0].name: + for joint_name in ["robot0_larm.el", "robot0_rarm.el"]: + l_elbow_pitch_id = self.sim.model.joint_name2id(joint_name) + l_elbow_pitch_range = self.sim.model.jnt_range[l_elbow_pitch_id] + self.sim.data.qpos[self.sim.model.get_joint_qpos_addr(joint_name)] = ( + l_elbow_pitch_range[0] * 0.1 + l_elbow_pitch_range[1] * 0.9 + ) + + def _get_obj_cfgs(self): + """ + Returns a list of object configurations to use in the environment. + The object configurations are usually environment-specific and should + be implemented in the subclass. + + Returns: + list: list of object configurations + """ + + return [] + + def get_ep_meta(self): + """ + Returns a dictionary containing episode meta data + """ + + def copy_dict_for_json(orig_dict): + new_dict = {} + for k, v in orig_dict.items(): + if isinstance(v, dict): + new_dict[k] = copy_dict_for_json(v) + elif isinstance(v, Fixture): + new_dict[k] = v.name + else: + new_dict[k] = v + return new_dict + + ep_meta = super().get_ep_meta() + ep_meta["layout_id"] = self.layout_id + ep_meta["style_id"] = self.style_id + ep_meta["object_cfgs"] = [copy_dict_for_json(cfg) for cfg in self.object_cfgs] + ep_meta["fixtures"] = { + k: {"cls": v.__class__.__name__} for (k, v) in self.fixtures.items() + } + ep_meta["gen_textures"] = self._curr_gen_fixtures or {} + ep_meta["lang"] = "" + ep_meta["fixture_refs"] = dict( + {k: v.name for (k, v) in self.fixture_refs.items()} + ) + ep_meta["cam_configs"] = deepcopy(self._cam_configs) + + return ep_meta + + def find_object_cfg_by_name(self, name): + """ + Finds and returns the object configuration with the given name. + + Args: + name (str): name of the object configuration to find + + Returns: + dict: object configuration with the given name + """ + for cfg in self.object_cfgs: + if cfg["name"] == name: + return cfg + raise ValueError + + def set_cameras(self): + """ + Adds new tabletop-relevant cameras to the environment. Will randomize cameras if specified. + """ + + self._cam_configs = deepcopy(CamUtils.CAM_CONFIGS) + + egoview_mount_body = find_elements( + root=self.robots[0].robot_model.root, + tags="body", + attribs={"name": "robot0_head_pitch"}, + ) + if egoview_mount_body is not None: + self._cam_configs["egoview"] = dict( + pos=[ + 2.650 - 2.65017178 + 0.23, + -1.944 + 2.174 - 0.23, + 1.538 - 1.4475, + ], + quat=[0.676, 0.205, -0.205, -0.676], + camera_attribs=dict(fovy="77"), + parent_body="robot0_head_pitch", + ) + + if self.randomize_cameras: + self._randomize_cameras() + + for cam_name, cam_cfg in self._cam_configs.items(): + if cam_cfg.get("parent_body", None) is not None: + continue + + self.mujoco_arena.set_camera( + camera_name=cam_name, + pos=cam_cfg["pos"], + quat=cam_cfg["quat"], + camera_attribs=cam_cfg.get("camera_attribs", None), + ) + + def _randomize_cameras(self): + """ + Randomizes the position and rotation of the wrist and agentview cameras. + Note: This function is called only if randomize_cameras is set to True. + """ + for camera in self._cam_configs: + if "agentview" in camera: + pos_noise = self.rng.normal(loc=0, scale=0.05, size=(1, 3))[0] + euler_noise = self.rng.normal(loc=0, scale=3, size=(1, 3))[0] + elif "eye_in_hand" in camera: + pos_noise = np.zeros_like(pos_noise) + euler_noise = np.zeros_like(euler_noise) + else: + # skip randomization for cameras not implemented + continue + + old_pos = self._cam_configs[camera]["pos"] + new_pos = [pos + n for pos, n in zip(old_pos, pos_noise)] + self._cam_configs[camera]["pos"] = list(new_pos) + + old_euler = Rotation.from_quat(self._cam_configs[camera]["quat"]).as_euler( + "xyz", degrees=True + ) + new_euler = [eul + n for eul, n in zip(old_euler, euler_noise)] + new_quat = Rotation.from_euler("xyz", new_euler, degrees=True).as_quat() + self._cam_configs[camera]["quat"] = list(new_quat) + + def edit_model_xml(self, xml_str): + """ + This function postprocesses the model.xml collected from a MuJoCo demonstration + for retrospective model changes. + + Args: + xml_str (str): Mujoco sim demonstration XML file as string + + Returns: + str: Post-processed xml file as string + """ + xml_str = super().edit_model_xml(xml_str) + + tree = ET.fromstring(xml_str) + root = tree + worldbody = root.find("worldbody") + actuator = root.find("actuator") + asset = root.find("asset") + meshes = asset.findall("mesh") + textures = asset.findall("texture") + all_elements = meshes + textures + + robosuite_path_split = os.path.split(robosuite.__file__)[0].split("/") + robocasa_path_split = os.path.split(robocasa.__file__)[0].split("/") + + # replace robocasa-specific asset paths + for elem in all_elements: + old_path = elem.get("file") + if old_path is None: + continue + + old_path_split = old_path.split("/") + # maybe replace all paths to robosuite assets + if "models/assets" in old_path: + if "/robosuite/" in old_path: + check_lst = [ + loc + for loc, val in enumerate(old_path_split) + if val == "robosuite" + ] + ind = max(check_lst) # last occurrence index + new_path_split = robosuite_path_split + old_path_split[ind + 1 :] + elif "/robocasa/" in old_path: + check_lst = [ + loc + for loc, val in enumerate(old_path_split) + if val == "robocasa" + ] + ind = max(check_lst) # last occurrence index + new_path_split = robocasa_path_split + old_path_split[ind + 1 :] + else: + raise ValueError + + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + # set cameras + for cam_name, cam_config in self._cam_configs.items(): + parent_body = cam_config.get("parent_body", None) + + cam_root = worldbody + if parent_body is not None: + cam_root = find_elements( + root=worldbody, tags="body", attribs={"name": parent_body} + ) + if cam_root is None: + # camera config refers to body that doesnt exist on the robot + continue + + cam = find_elements( + root=cam_root, tags="camera", attribs={"name": cam_name} + ) + + if cam is None: + old_cam = find_elements( + root=worldbody, tags="camera", attribs={"name": cam_name} + ) + if old_cam is not None: + # old camera associated with different body + continue + + cam = ET.Element("camera") + cam.set("mode", "fixed") + cam.set("name", cam_name) + cam_root.append(cam) + + cam.set("pos", array_to_string(cam_config["pos"])) + cam.set("quat", array_to_string(cam_config["quat"])) + for k, v in cam_config.get("camera_attribs", {}).items(): + cam.set(k, v) + + # replace base -> mobilebase (this is needed for old PandaOmron demos) + for elem in find_elements( + root=worldbody, tags=["geom", "site", "body", "joint"], return_first=False + ): + if elem.get("name") is None: + continue + if elem.get("name").startswith("base0_"): + old_name = elem.get("name") + new_name = "mobilebase0_" + old_name[6:] + elem.set("name", new_name) + for elem in find_elements( + root=actuator, + tags=["velocity", "position", "motor", "general"], + return_first=False, + ): + if elem.get("name") is None: + continue + if elem.get("name").startswith("base0_"): + old_name = elem.get("name") + new_name = "mobilebase0_" + old_name[6:] + elem.set("name", new_name) + for elem in find_elements( + root=actuator, + tags=["velocity", "position", "motor", "general"], + return_first=False, + ): + if elem.get("joint") is None: + continue + if elem.get("joint").startswith("base0_"): + old_joint = elem.get("joint") + new_joint = "mobilebase0_" + old_joint[6:] + elem.set("joint", new_joint) + + # result = ET.tostring(root, encoding="utf8").decode("utf8") + result = ET.tostring(root).decode("utf8") + + # replace with generative textures + if (self.generative_textures is not None) and ( + self.generative_textures is not False + ): + # sample textures + assert self.generative_textures == "100p" + self._curr_gen_fixtures = get_random_textures(self.rng) + + cab_tex = self._curr_gen_fixtures["cab_tex"] + counter_tex = self._curr_gen_fixtures["counter_tex"] + wall_tex = self._curr_gen_fixtures["wall_tex"] + floor_tex = self._curr_gen_fixtures["floor_tex"] + + result = replace_cab_textures( + self.rng, result, new_cab_texture_file=cab_tex + ) + result = replace_counter_top_texture( + self.rng, result, new_counter_top_texture_file=counter_tex + ) + result = replace_wall_texture( + self.rng, result, new_wall_texture_file=wall_tex + ) + result = replace_floor_texture( + self.rng, result, new_floor_texture_file=floor_tex + ) + + return result + + def _setup_references(self): + """ + Sets up references to important components. A reference is typically an + index or a list of indices that point to the corresponding elements + in a flatten array, which is how MuJoCo stores physical simulation data. + """ + super()._setup_references() + + self.obj_body_id = {} + for name, model in self.objects.items(): + self.obj_body_id[name] = self.sim.model.body_name2id(model.root_body) + + def _setup_observables(self): + """ + Sets up observables to be used for this environment. Creates object-based observables if enabled + + Returns: + OrderedDict: Dictionary mapping observable names to its corresponding Observable object + """ + observables = super()._setup_observables() + + # low-level object information + + # Get robot prefix and define observables modality + pf = self.robots[0].robot_model.naming_prefix + modality = "object" + + # for conversion to relative gripper frame + @sensor(modality=modality) + def world_pose_in_gripper(obs_cache): + return ( + T.pose_inv( + T.pose2mat((obs_cache[f"{pf}eef_pos"], obs_cache[f"{pf}eef_quat"])) + ) + if f"{pf}eef_pos" in obs_cache and f"{pf}eef_quat" in obs_cache + else np.eye(4) + ) + + sensors = [world_pose_in_gripper] + names = ["world_pose_in_gripper"] + actives = [False] + + # add ground-truth poses (absolute and relative to eef) for all objects + for obj_name in self.obj_body_id: + obj_sensors, obj_sensor_names = self._create_obj_sensors( + obj_name=obj_name, modality=modality + ) + sensors += obj_sensors + names += obj_sensor_names + actives += [False] * len(obj_sensors) + + # Create observables + for name, s, active in zip(names, sensors, actives): + observables[name] = Observable( + name=name, + sensor=s, + sampling_rate=self.control_freq, + active=active, + ) + + return observables + + def _create_obj_sensors(self, obj_name, modality="object"): + """ + Helper function to create sensors for a given object. This is abstracted in a separate function call so that we + don't have local function naming collisions during the _setup_observables() call. + + Args: + obj_name (str): Name of object to create sensors for + + modality (str): Modality to assign to all sensors + + Returns: + 2-tuple: + sensors (list): Array of sensors for the given obj + names (list): array of corresponding observable names + """ + + ### TODO: this was stolen from pick-place - do we want to move this into utils to share it? ### + pf = self.robots[0].robot_model.naming_prefix + + @sensor(modality=modality) + def obj_pos(obs_cache): + return np.array(self.sim.data.body_xpos[self.obj_body_id[obj_name]]) + + @sensor(modality=modality) + def obj_quat(obs_cache): + return T.convert_quat( + self.sim.data.body_xquat[self.obj_body_id[obj_name]], to="xyzw" + ) + + @sensor(modality=modality) + def obj_to_eef_pos(obs_cache): + # Immediately return default value if cache is empty + if any( + [ + name not in obs_cache + for name in [ + f"{obj_name}_pos", + f"{obj_name}_quat", + "world_pose_in_gripper", + ] + ] + ): + return np.zeros(3) + obj_pose = T.pose2mat( + (obs_cache[f"{obj_name}_pos"], obs_cache[f"{obj_name}_quat"]) + ) + rel_pose = T.pose_in_A_to_pose_in_B( + obj_pose, obs_cache["world_pose_in_gripper"] + ) + rel_pos, rel_quat = T.mat2pose(rel_pose) + obs_cache[f"{obj_name}_to_{pf}eef_quat"] = rel_quat + return rel_pos + + @sensor(modality=modality) + def obj_to_eef_quat(obs_cache): + return ( + obs_cache[f"{obj_name}_to_{pf}eef_quat"] + if f"{obj_name}_to_{pf}eef_quat" in obs_cache + else np.zeros(4) + ) + + sensors = [obj_pos, obj_quat, obj_to_eef_pos, obj_to_eef_quat] + names = [ + f"{obj_name}_pos", + f"{obj_name}_quat", + f"{obj_name}_to_{pf}eef_pos", + f"{obj_name}_to_{pf}eef_quat", + ] + + return sensors, names + + def _post_action(self, action): + """ + Do any housekeeping after taking an action. + + Args: + action (np.array): Action to execute within the environment + + Returns: + 3-tuple: + - (float) reward from the environment + - (bool) whether the current episode is completed or not + - (dict) information about the current state of the environment + """ + reward, done, info = super()._post_action(action) + + # Check if stove is turned on or not + self.update_state() + return reward, done, info + + def convert_rel_to_abs_action(self, rel_action): + # if moving mobile base, there is no notion of absolute actions. + # use relative actions instead. + + # if moving arm, get the absolute action + robot = self.robots[0] + robot.control(rel_action, policy_step=True) + rel_pose = robot.composite_controller.part_controllers[ + "right" + ].goal_origin_to_eef_pose() + ac_pos, ac_ori = rel_pose[:3, 3], rel_pose[:3, :3] + ac_ori = Rotation.from_matrix(ac_ori).as_rotvec() + action_abs = np.hstack( + [ + ac_pos, + ac_ori, + rel_action[6:], + ] + ) + return action_abs + + def update_state(self): + """ + Updates the state of the environment. + This involves updating the state of all fixtures in the environment. + """ + super().update_state() + + for fixtr in self.fixtures.values(): + fixtr.update_state(self) + + def visualize(self, vis_settings): + """ + In addition to super call, make the robot semi-transparent + + Args: + vis_settings (dict): Visualization keywords mapped to T/F, determining whether that specific + component should be visualized. Should have "grippers" keyword as well as any other relevant + options specified. + """ + # Run superclass method first + super().visualize(vis_settings=vis_settings) + + visual_geom_names = [] + + for robot in self.robots: + robot_model = robot.robot_model + visual_geom_names += robot_model.visual_geoms + + for name in visual_geom_names: + rgba = self.sim.model.geom_rgba[self.sim.model.geom_name2id(name)] + if self.translucent_robot: + rgba[-1] = 0.10 + else: + rgba[-1] = 1.0 + + def reward(self, action=None): + """ + Reward function for the task. The reward function is based on the task + and to be implemented in the subclasses. Returns 0 by default. + + Returns: + float: Reward for the task + """ + reward = 0 + if self._check_success(): + reward = 1.0 + return reward + + def _check_success(self): + """ + Checks if the task has been successfully completed. + Success condition is based on the task and to be implemented in the + subclasses. Returns False by default. + + Returns: + bool: True if the task is successfully completed, False otherwise + """ + return False + + def sample_object( + self, + groups, + exclude_groups=None, + exclude_cat=None, + graspable=None, + microwavable=None, + washable=None, + cookable=None, + freezable=None, + max_size=(None, None, None), + object_scale=None, + ): + """ + Sample a tabletop object from the specified groups and within max_size bounds. + + Args: + groups (list or str): groups to sample from or the exact xml path of the object to spawn + + exclude_groups (str or list): groups to exclude + + exclude_cat (str or list): groups to exclude + + graspable (bool): whether the sampled object must be graspable + + washable (bool): whether the sampled object must be washable + + microwavable (bool): whether the sampled object must be microwavable + + cookable (bool): whether whether the sampled object must be cookable + + freezable (bool): whether whether the sampled object must be freezable + + max_size (tuple): max size of the object. If the sampled object is not within bounds of max size, + function will resample + + object_scale (float): scale of the object. If set will multiply the scale of the sampled object by this value + + + Returns: + dict: kwargs to apply to the MJCF model for the sampled object + + dict: info about the sampled object - the path of the mjcf, groups which the object's category belongs to, + the category of the object the sampling split the object came from, and the groups the object was sampled from + """ + return sample_kitchen_object( + groups, + exclude_groups=exclude_groups, + exclude_cat=exclude_cat, + graspable=graspable, + washable=washable, + microwavable=microwavable, + cookable=cookable, + freezable=freezable, + rng=self.rng, + obj_registries=self.obj_registries, + prefer_leading_registry=self.prefer_leading_registry, + split=self.obj_instance_split, + max_size=max_size, + object_scale=object_scale, + ) + + def _is_fxtr_valid(self, fxtr, size): + """ + checks if counter is valid for object placement by making sure it is large enough + + Args: + fxtr (Fixture): fixture to check + size (tuple): minimum size (x,y) that the counter region must be to be valid + + Returns: + bool: True if fixture is valid, False otherwise + """ + for region in fxtr.get_reset_regions(self).values(): + if region["size"][0] >= size[0] and region["size"][1] >= size[1]: + return True + return False + + def get_fixture(self, id, ref=None, size=(0.2, 0.2)): + """ + search fixture by id (name, object, or type) + + Args: + id (str, Fixture, FixtureType): id of fixture to search for + + ref (str, Fixture, FixtureType): if specified, will search for fixture close to ref (within 0.10m) + + size (tuple): if sampling counter, minimum size (x,y) that the counter region must be + + Returns: + Fixture: fixture object + """ + # case 1: id refers to fixture object directly + if isinstance(id, Fixture): + return id + # case 2: id refers to exact name of fixture + elif id in self.fixtures.keys(): + return self.fixtures[id] + + if ref is None: + # find all fixtures with names containing given name + if isinstance(id, FixtureType) or isinstance(id, int): + matches = [ + name + for (name, fxtr) in self.fixtures.items() + if fixture_is_type(fxtr, id) + ] + else: + matches = [name for name in self.fixtures.keys() if id in name] + if id == FixtureType.COUNTER or id == FixtureType.COUNTER_NON_CORNER: + matches = [ + name + for name in matches + if self._is_fxtr_valid(self.fixtures[name], size) + ] + assert len(matches) > 0 + # sample random key + key = self.rng.choice(matches) + return self.fixtures[key] + else: + ref_fixture = self.get_fixture(ref) + + assert isinstance(id, FixtureType) + cand_fixtures = [] + for fxtr in self.fixtures.values(): + if not fixture_is_type(fxtr, id): + continue + if fxtr is ref_fixture: + continue + if id == FixtureType.COUNTER: + fxtr_is_valid = self._is_fxtr_valid(fxtr, size) + if not fxtr_is_valid: + continue + cand_fixtures.append(fxtr) + + # first, try to find fixture "containing" the reference fixture + for fxtr in cand_fixtures: + if OU.point_in_fixture(ref_fixture.pos, fxtr, only_2d=True): + return fxtr + # if no fixture contains reference fixture, sample all close fixtures + dists = [ + OU.fixture_pairwise_dist(ref_fixture, fxtr) for fxtr in cand_fixtures + ] + min_dist = np.min(dists) + close_fixtures = [ + fxtr for (fxtr, d) in zip(cand_fixtures, dists) if d - min_dist < 0.10 + ] + return self.rng.choice(close_fixtures) + + def register_fixture_ref(self, ref_name, fn_kwargs): + """ + Registers a fixture reference for later use. Initializes the fixture + if it has not been initialized yet. + + Args: + ref_name (str): name of the reference + + fn_kwargs (dict): keyword arguments to pass to get_fixture + + Returns: + Fixture: fixture object + """ + if ref_name not in self.fixture_refs: + self.fixture_refs[ref_name] = self.get_fixture(**fn_kwargs) + return self.fixture_refs[ref_name] + + def get_obj_lang(self, obj_name="obj", get_preposition=False): + """ + gets a formatted language string for the object (replaces underscores with spaces) + + Args: + obj_name (str): name of object + get_preposition (bool): if True, also returns preposition for object + + Returns: + str: language string for object + """ + obj_cfg = None + for cfg in self.object_cfgs: + if cfg["name"] == obj_name: + obj_cfg = cfg + break + + assert obj_cfg is not None + lang = obj_cfg["info"]["cat"].replace("_", " ") + + if not get_preposition: + return lang + + if lang in ["bowl", "pot", "pan"]: + preposition = "in" + elif lang in ["plate"]: + preposition = "on" + else: + raise ValueError + + return lang, preposition diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_24dc.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_24dc.py new file mode 100644 index 0000000000000000000000000000000000000000..8408266021c29434ef7cd7e8908761eea0e82390 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_24dc.py @@ -0,0 +1,1037 @@ +from typing import List, Tuple +import numpy as np +from copy import deepcopy +from itertools import combinations, chain + +import robocasa.utils.object_utils as OU +from robocasa.environments.tabletop.tabletop_pnp import TabletopPnP +from robocasa.models.objects.kitchen_objects import get_all_obj_cats +from robocasa.utils.cotrain_utils import ( + COTRAIN_REAL_MATCHED_ROBOT_INITIAL_POSE, +) +from robocasa.models.fixtures.fixture import FixtureType + +# =============================================================================== +# Configurations +# =============================================================================== + +SEED = 42 +rng = np.random.default_rng(seed=SEED) + +# Task Generation Configuration +TASK_CONFIG = { + "registries": ["objaverse", "sketchfab", "lightwheel"], + "obj_groups": [ + "vegetable", + "bread_food", + "pastry", + "sweets", + "fruit", + "meat", + "drink", + "cooked_food", + "toy", + ], + "source_containers": ["cutting_board", "tray", "plate", "placemat"], + "target_containers": [ + "basket", + "pan", + "pot", + "bowl", + "plate", + "tiered_shelf", + "tiered_basket", + "cardboard_box", + ], + "exclude_combos": [], + "similar_containers": { + "tray": ["cutting_board"], + "cutting_board": ["tray"], + "basket": ["tiered_basket"], + "tiered_basket": ["basket", "tiered_shelf"], + "tiered_shelf": ["tiered_basket"], + "pot": ["pan"], + "pan": ["pot"], + }, +} + +# Distractor Configurations +RANDOM_DISTRACTOR_CONFIG = { + "distractor_obj": { # placing object on the source container + "placement": { + "try_to_place_in": "obj_container", + "use_existing_container": True, + "ensure_object_in_ref_region": True, + "ensure_object_boundary_in_range": False, + }, + "objects": [ + { + "type": ("obj", "distractor"), + "count": (1, 1), + "exclude_groups": ["drink"], + }, + ], + }, + "distractor_source_container": { # placing object on a new container, different from the source container + "placement": { + "try_to_place_in": ("source_container", "distractor"), + "use_existing_container": False, + "ensure_object_in_ref_region": True, + "ensure_object_boundary_in_range": False, + "size": (1.1, 0.45), + "pos": (0, -0.6), + "container_kwargs": { + "exclude_obj_cat": True, + }, + }, + "objects": [ + { + "type": ("obj", "any"), + "count": (1, 1), + "exclude_groups": ["drink"], + "exclude_obj_cat": False, + }, + ], + }, + "distractor_target_container": { # a distractor target container + "placement": { + "size": (1.1, 0.45), + "pos": (0, -0.6), + "ensure_object_boundary_in_range": False, + }, + "objects": [ + { + "type": ("target_container", "distractor"), + "count": (1, 1), + }, + ], + }, +} + +FIXED_DISTRACTOR_CONFIG = { + "back_edge": { + "placement": { + "pos": (0, 0.9), + "rotation": (np.pi / 2, np.pi / 2), + "size": (1.0, 0.1), + "try_not_to_place_in": ["container", "obj_container"], + "ensure_object_out_of_ref_region": True, + "ensure_object_boundary_in_range": False, + }, + "fixtures": [ + { + "type": ["toaster"], + "count": (0, 1), + }, + { + "type": ["plant"], + "count": (0, 1), + }, + ], + "objects": [ + { + "type": ["chips", "cereal", "book", "candle"], + "count": (0, 1), + }, + ], + }, +} + + +class PositionSampler: + """Samples positions for containers and objects based on handedness.""" + + _POSITIONS = { + "right": { + "container": [(0.75, -0.15)], + "obj": [(0.85, -0.9)], + }, + "left": { + "container": [(-0.7, -0.45), (-0.2, -0.45)], + "obj": [(-0.2, -0.85), (-0.7, -0.85)], + }, + } + _SIZE = { + "obj": [(0.7, 0.3)], + "container": [(0.6, 0.2)], + } + + @staticmethod + def sample( + handedness: str, rng: np.random.Generator + ) -> Tuple[Tuple[float, float], Tuple[float, float]]: + """Sample a container and object position pair.""" + if handedness not in ["left", "right"]: + raise ValueError(f"Handedness must be 'left' or 'right', got {handedness}") + + positions = PositionSampler._POSITIONS[handedness] + container_positions = positions["container"] + obj_positions = positions["obj"] + + idx = rng.choice(len(container_positions)) + return ( + container_positions[idx], + obj_positions[idx], + PositionSampler._SIZE["container"][idx], + PositionSampler._SIZE["obj"][idx], + ) + + @staticmethod + def get_size(key) -> Tuple[float, float]: + return PositionSampler._SIZE[key] + + +OBJ_SCALES = { + "tiered_shelf": 0.7, + "tiered_basket": 0.7, + "plate": 1.2, + "cardboard_box": 0.9, + "placemat": 0.8, + "rubix_cube": 0.8, + "tray": 0.8, + "cutting_board": 0.8, +} + +FIXTURE_SCALES = { + "paper_towel": (0.3), + "plant": 0.3, + "toaster": 1.0, +} + +# =============================================================================== +# Helper Functions +# =============================================================================== + + +def construct_distractor_obj_cfgs( + included_configs: List[str] = None, + randomize_configs: bool = False, + task_seed: int = None, +): + """Construct distractor object configurations.""" + + distractor_config = {"regions": {}} + distractor_config["regions"].update(deepcopy(FIXED_DISTRACTOR_CONFIG)) + + task_rng = np.random.default_rng(seed=task_seed if task_seed else SEED) + + for region in distractor_config["regions"]: + for fixture in distractor_config["regions"][region]["fixtures"]: + if isinstance(fixture["type"], list): + fixture["type"] = task_rng.choice(fixture["type"]) + fixture["scale"] = FIXTURE_SCALES.get(fixture["type"], 1.0) + for obj in distractor_config["regions"][region]["objects"]: + if isinstance(obj["type"], list): + obj["type"] = task_rng.choice(obj["type"]) + if "object_scale" in obj: + obj["object_scale"] = OBJ_SCALES[obj["type"]] + if randomize_configs: + p = 0.4 + # Randomly include items with 0.4 probability + for item in RANDOM_DISTRACTOR_CONFIG.items(): + if task_rng.random() < p: + distractor_config["regions"].update({item[0]: item[1]}) + else: + if included_configs is not None: + # If not randomizing, include distractor items in included_configs + for item in RANDOM_DISTRACTOR_CONFIG.items(): + if item[0] in included_configs: + distractor_config["regions"].update({item[0]: item[1]}) + else: + distractor_config["regions"] = {} + + return distractor_config + + +def is_excluded( + obj_group: str, source: str, target: str, exclude_list: List[Tuple[str, str, str]] +) -> bool: + """Check if a combination is excluded.""" + for excluded_obj, excluded_source, excluded_target in exclude_list: + matches_obj = excluded_obj == "*" or excluded_obj == obj_group + matches_source = excluded_source == "*" or excluded_source == source + matches_target = excluded_target == "*" or excluded_target == target + if matches_obj and matches_source and matches_target: + return True + return False + + +def get_excluded_obj_cats(obj_cats: List[str]) -> List[str]: + """Get all object categories that are not in val_obj_cats.""" + all_obj_cats = [] + # Get all object categories from all groups + for group in TASK_CONFIG["obj_groups"]: + cats = get_all_obj_cats( + groups=[group], registries=TASK_CONFIG["registries"], attrs=["graspable"] + ) + if cats: + all_obj_cats.extend(cats) + + # Remove duplicates and exclude val_obj_cats + all_obj_cats = list(set(all_obj_cats)) + return [cat for cat in all_obj_cats if cat not in obj_cats] + + +def get_excluded_container_combos( + container_combos: List[Tuple[str, str]] +) -> List[Tuple[str, str]]: + """Get all valid container combinations that are not in val_container_combos.""" + all_combos = [] + for source in TASK_CONFIG["source_containers"]: + for target in TASK_CONFIG["target_containers"]: + if not is_excluded("*", source, target, TASK_CONFIG["exclude_combos"]): + combo = (source, target) + if combo not in container_combos: + all_combos.append(combo) + return all_combos + + +# =============================================================================== +# Class Generation +# =============================================================================== + +def create_pnp_class( + class_name: str, + obj_cat: str, + source: str, + target: str, + all_obj_cats: List[str], + all_source_containers: List[str], + all_target_containers: List[str], + distractor_cfg: dict = None, + obj_instance_split: str = None, + distractor_obj_cats: List[str] = None, +) -> type: + """Creates a pick-and-place class dynamically.""" + + if not distractor_obj_cats: + distractor_obj_cats = all_obj_cats + + def __init__(self, *args, **kwargs): + if "obj_instance_split" not in kwargs: + kwargs["obj_instance_split"] = obj_instance_split + + TabletopPnP.__init__( + self, + obj_groups=obj_cat, + source_container=source, + source_container_size=PositionSampler.get_size("obj"), + target_container=target, + target_container_size=PositionSampler.get_size("container"), + distractor_config=distractor_cfg, + obj_registries=TASK_CONFIG["registries"], + *args, + **kwargs, + ) + + def _create_objects(self): + """ + Creates and places objects in the tabletop environment. + Helper function called by _load_model() + """ + # add objects + self.objects = {} + if "object_cfgs" in self._ep_meta: + self.object_cfgs = self._ep_meta["object_cfgs"] + for obj_num, cfg in enumerate(self.object_cfgs): + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + model, info = self._create_obj(cfg) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + else: + self.object_cfgs = self._get_obj_cfgs() + num_objects = len(self.object_cfgs) + exclude_cat = [] + self.object_cfgs.extend(self._get_distractor_obj_cfgs()) + addl_obj_cfgs = [] + invalid_obj_cfgs = [] + # if self.source_container in [ + # "plate", + # "bowl", + # ]: + # cfg["exclude_cat"] += get_all_obj_cats(["drink"]) + for obj_num, cfg in enumerate(self.object_cfgs): + cfg["type"] = "object" + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + if obj_num >= num_objects and cfg.get("exclude_obj_cat", True): + # objects part of distractors + cfg["exclude_cat"] = cfg.get("exclude_cat", []) + exclude_cat + if cfg["obj_groups"] == "obj": + # Find the obj config and use its info + for obj_cfg in self.object_cfgs: + if obj_cfg["name"] == "obj": + cfg["obj_groups"] = obj_cfg["info"]["cat"] + break + try: + model, info = self._create_obj(cfg) + except ValueError: + # no valid object found + # this is due to the object group selected only has 1 object category which is the same as the target object + # so we skip this object config + print( + f"No valid object found for {cfg['name']}, skip this object config" + ) + invalid_obj_cfgs.append(cfg) + continue + if obj_num < num_objects: + # objects part of the task + exclude_cat.append(info["cat"]) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + try_to_place_in = cfg["placement"].get("try_to_place_in", None) + + # place object in a container and add container as an object to the scene + if try_to_place_in: + assert ( + "in_container" in cfg["info"]["groups_containing_sampled_obj"] + ), f"Object {cfg['name']} is not part of in_container group" + + if cfg["placement"].get("use_existing_container", False): + # use existing container, no need to create a new one + reference = cfg["placement"]["try_to_place_in"] + else: + container_cfg = { + "name": cfg["name"] + "_container", + "obj_groups": cfg["placement"].get("try_to_place_in"), + "placement": deepcopy(cfg["placement"]), + "type": "object", + } + + container_kwargs = cfg["placement"].get( + "container_kwargs", None + ) + if container_kwargs is not None: + for k, v in container_kwargs.items(): + container_cfg[k] = v + + # containers that are part of distractors + if obj_num >= num_objects and container_cfg.get( + "exclude_obj_cat", True + ): + container_cfg["exclude_cat"] = ( + container_cfg.get("exclude_cat", []) + exclude_cat + ) + + # add in the new object to the model + addl_obj_cfgs.append(container_cfg) + model, info = self._create_obj(container_cfg) + container_cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + if obj_num < num_objects: + # container part of the task + exclude_cat.append(info["cat"]) + + reference = container_cfg["name"] + site_id = cfg["placement"].get("site_id", None) + if site_id is not None: + reference = (reference, site_id) + + # modify object config to lie inside of container + cfg["placement"] = dict( + # pos=(0, 0), + size=(0.1, 0.1), + ensure_object_boundary_in_range=False, + ensure_object_in_ref_region=cfg["placement"].get( + "ensure_object_in_ref_region", False + ), + sample_args=dict( + reference=reference, + ), + ) + + if cfg["placement"].get("try_not_to_place_in", None): + reference = cfg["placement"]["try_not_to_place_in"] + cfg["placement"].update( + ensure_object_boundary_in_range=False, + ensure_object_out_of_ref_region=cfg["placement"].get( + "ensure_object_out_of_ref_region", False + ), + sample_args=dict( + neg_reference=reference, + ), + ) + + # place the additional objects (usually containers) in first + + for cfg in invalid_obj_cfgs: + self.object_cfgs.remove(cfg) + + self.object_cfgs = addl_obj_cfgs + self.object_cfgs + + # # remove objects that didn't get created + # self.object_cfgs = [cfg for cfg in self.object_cfgs if "model" in cfg] + + def _get_obj_cfgs(self): + """Get object configurations for the scene.""" + + pos_container, pos_obj, size_container, size_obj = PositionSampler.sample( + self.handedness, + self.rng, + ) + + return [ + { + "name": "container", + "obj_groups": self.target_container, + "placement": { + "fixture": self.counter, + "size": size_container, + "pos": pos_container, + "rotation": (-np.pi / 2, np.pi / 2), + "ensure_object_boundary_in_range": False, + }, + "object_scale": OBJ_SCALES.get(self.target_container, None), + }, + { + "name": "obj", + "obj_groups": self.obj_groups, + "exclude_obj_groups": self.exclude_obj_groups, + "graspable": True, + "placement": { + "fixture": self.counter, + "size": size_obj if size_obj else (0.3, 0.3), + "pos": pos_obj, + "rotation": (-np.pi / 2, np.pi / 2), + "try_to_place_in": self.source_container, + "ensure_object_in_ref_region": True, + "ensure_object_boundary_in_range": True, + }, + "object_scale": OBJ_SCALES, + }, + ] + + def _get_distractor_obj_cfgs(self): + """Returns configurations for distractor objects""" + + def _resolve_type_tuple(type_tuple): + """Helper function to resolve (A, B) type tuples + A: 'obj', 'source_container', or 'target_container' + B: 'focus', 'distractor', or 'any' + """ + category, mode = type_tuple + + if category == "obj": + pool = distractor_obj_cats.copy() + focus_item = self.obj_groups + elif category == "source_container": + pool = all_source_containers.copy() + focus_item = self.source_container + elif category == "target_container": + pool = all_target_containers.copy() + focus_item = self.target_container + else: + raise ValueError(f"Unknown category type: {category}") + + if mode == "focus": + return focus_item + elif mode == "distractor": + if focus_item in pool: + pool.remove(focus_item) + for similar_item in TASK_CONFIG["similar_containers"].get( + focus_item, [] + ): + if similar_item in pool: + pool.remove(similar_item) + # print(f"Removed similar item: {similar_item}") + return pool + elif mode == "any": + return pool + else: + raise ValueError(f"Unknown mode: {mode}") + + for config in self.distractor_config.get("regions", {}).values(): + # Handle placement configurations + if config.get("placement", None): + try_to_place_in = config["placement"].get("try_to_place_in", None) + if isinstance(try_to_place_in, tuple): + config["placement"]["try_to_place_in"] = _resolve_type_tuple( + try_to_place_in, + ) + + # Handle object configurations + for obj_config in config.get("objects", []): + obj_type = obj_config.get("type", None) + if isinstance(obj_type, tuple): + resolved_type = _resolve_type_tuple( + obj_type, + ) + obj_config["type"] = resolved_type + # Set exclude_obj_cat to True if we're dealing with objects + if obj_type[0] == "obj": + obj_config["exclude_obj_cat"] = True + + # Start processing distractor object configurations + if self.distractor_config is None: + return [] + + cfgs = [] + + counter = self.fixture_refs.get( + "counter", self.get_fixture(id=FixtureType.COUNTER) + ) + + # Process each region's objects + for region_name, region_config in self.distractor_config.get( + "regions", {} + ).items(): + placement = region_config.get("placement", {}) + + for i, obj_config in enumerate(region_config.get("objects", [])): + count_spec = obj_config.get("count", 1) + if isinstance(count_spec, (list, tuple)): + min_count = count_spec[0] + max_count = self.rng.integers(min_count, count_spec[1] + 1) + else: + min_count = max_count = count_spec + + for j in range(max_count): + cfgs.append( + dict( + name=f"distractor_obj_{region_name}_type_{i}_num_{j}", + type="object", + obj_groups=obj_config["type"], + exclude_cat=obj_config.get("exclude_cat", []), + graspable=False, + exclude_obj_cat=obj_config.get("exclude_obj_cat", True), + placement={ + **placement, + "optional": i >= min_count, + "fixture": counter, + }, + ) + ) + + return cfgs + + def _check_grasp_distractor_obj(self): + check_grasp_distractor_obj = False + if "distractor_obj" in self.distractor_config.get("regions", {}).keys(): + for cfg in self.object_cfgs: + if "distractor_obj_distractor_obj" in cfg["name"]: + distractor = self.objects[cfg["name"]] + if self._check_grasp( + gripper=self.robots[0].gripper["right"], + object_geoms=distractor, + ): + check_grasp_distractor_obj = True + return check_grasp_distractor_obj + + def _check_success(self): + + gripper_container_far = OU.any_gripper_obj_far(self, obj_name="container") + gripper_obj_far = OU.any_gripper_obj_far(self, obj_name="obj") + if self.target_container in [ + "tiered_basket", + "tiered_shelf", + ]: # currently only these containers have spawn regions + highest_spawn_region = OU.get_highest_spawn_region( + self, self.objects["container"] + ) + else: + highest_spawn_region = None + obj_in_container = OU.check_obj_in_receptacle( + self, "obj", "container", spawn_regions=[highest_spawn_region] + ) + obj_on_counter = OU.check_obj_fixture_contact(self, "obj", self.counter) + container_upright = OU.check_obj_upright(self, "container", threshold=0.8) + + # check if the distractor object is in the target container if it has the distractor_obj key + if "distractor_obj" in self.distractor_config.get("regions", {}).keys(): + distractor_obj_in_receptacle = False + for cfg in self.object_cfgs: + if "distractor_obj_distractor_obj" in cfg["name"]: + distractor_obj_in_receptacle |= OU.check_obj_in_receptacle( + self, + cfg["name"], + "container", + spawn_regions=[highest_spawn_region], + ) + else: + distractor_obj_in_receptacle = False + return ( + gripper_container_far + and gripper_obj_far + and obj_in_container + and not obj_on_counter + and container_upright + and not distractor_obj_in_receptacle + ) + + def _reset_internal(self): + TabletopPnP._reset_internal(self) + + # Randomization for joints + joint_rand_strength = 0.2 + + cotrain_qpos = dict() + for robot_type, qpos in COTRAIN_REAL_MATCHED_ROBOT_INITIAL_POSE.items(): + if isinstance(self.robots[0].robot_model, robot_type): + cotrain_qpos = deepcopy(qpos) + break + if not cotrain_qpos: + print(f"No cotrain qpos for {self.robot_names}") + + current_qpos = self.sim.data.qpos.copy() + + for name in self.sim.model.joint_names: + if "robot0_" in name: + joint_id = self.sim.model.joint_name2id(name) + if name in cotrain_qpos: + # For joints in COTRAIN_REAL_MATCHED_ROBOT_INITIAL_POSE, apply pos + randomization + new_pos = cotrain_qpos[name] + self.rng.uniform( + -joint_rand_strength, joint_rand_strength + ) + else: + # For other joints, use current pos + new_pos = current_qpos[joint_id] + self.sim.data.qpos[joint_id] = new_pos + + self.sim.forward() + + def compute_robot_base_placement_pose(self, offset=None): + robot_base_pos, robot_base_ori = TabletopPnP.compute_robot_base_placement_pose( + self, offset + ) + # Randomization for the table + robot_base_pos += np.array([0.05, 0.05, -0.05]) + robot_base_pos -= self.rng.uniform(0, 0.05, 3) + return robot_base_pos, robot_base_ori + + return type( + class_name, + (TabletopPnP,), + { + "__init__": __init__, + "_create_objects": _create_objects, + "_get_obj_cfgs": _get_obj_cfgs, + "_get_distractor_obj_cfgs": _get_distractor_obj_cfgs, + "_check_success": _check_success, + "_check_grasp_distractor_obj": _check_grasp_distractor_obj, + "_reset_internal": _reset_internal, + "compute_robot_base_placement_pose": compute_robot_base_placement_pose, + }, + ) + + +def generate_task_classes( + obj_cats: List[str], + container_combos: List[Tuple[str, str]], + prefix: str = "PnP", + distractor_configs: dict = None, + randomize_distractor_configs: bool = False, + obj_instance_split: str = None, + distractor_obj_cats: List[str] = None, + postfix: str = None, +): + """Generate all test task classes based on configuration.""" + task_infos = [] + source_containers_set = set([c for c, _ in container_combos]) + target_containers_set = set([t for _, t in container_combos]) + for source_container, target_container in container_combos: + class_name = f"{prefix}From{source_container.replace('_','').title()}To{target_container.replace('_','').title()}" + if postfix: + class_name += postfix + + task_seed = hash(class_name) & (2**32 - 1) + + distractor_cfg = construct_distractor_obj_cfgs( + included_configs=distractor_configs[(source_container, target_container)] + if distractor_configs + else None, + randomize_configs=randomize_distractor_configs, + task_seed=task_seed, + ) + + globals()[class_name] = create_pnp_class( + class_name, + obj_cats, + source_container, + target_container, + all_obj_cats=obj_cats, + all_source_containers=list(source_containers_set), + all_target_containers=list(target_containers_set), + distractor_cfg=distractor_cfg, + obj_instance_split=obj_instance_split, + distractor_obj_cats=distractor_obj_cats, + ) + task_infos.append( + { + "class_name": class_name, + "source_container": source_container, + "target_container": target_container, + "obj_cats": obj_cats, + "distractor_keys": distractor_cfg["regions"].keys(), + "randomize_distractor_configs": randomize_distractor_configs, + } + ) + return task_infos + + +# =============================================================================== +# Main Execution +# =============================================================================== + +novel_obj_cats = [ + "sweet_potato", + "bell_pepper", + "lemon", + "croissant", + "pear", + "squash", + "cupcake", + "can", + "tomato", + "eggplant", +] +novel_container_combos = [ + # cutting_board + ("cutting_board", "pot"), + ("cutting_board", "basket"), + ("cutting_board", "tiered_basket"), + ("cutting_board", "pan"), + ("cutting_board", "cardboard_box"), + # placemat + ("placemat", "bowl"), + ("placemat", "plate"), + ("placemat", "basket"), + ("placemat", "tiered_shelf"), + # plate + ("plate", "pan"), + ("plate", "cardboard_box"), + ("plate", "bowl"), + ("plate", "plate"), + # tray + ("tray", "tiered_shelf"), + ("tray", "plate"), + ("tray", "tiered_basket"), + ("tray", "cardboard_box"), + ("tray", "pot"), +] + +base_obj_cats = get_excluded_obj_cats(novel_obj_cats) +base_container_combos = get_excluded_container_combos(novel_container_combos) + + +distractor_config_for_pretrain_base = { + ("cutting_board", "bowl"): [], + ("cutting_board", "plate"): ["distractor_obj", "distractor_target_container"], + ("cutting_board", "tiered_shelf"): ["distractor_source_container"], + ("tray", "basket"): ["distractor_obj"], + ("tray", "pan"): ["distractor_target_container"], + ("tray", "bowl"): ["distractor_target_container"], + ("plate", "basket"): ["distractor_obj"], + ("plate", "pot"): [], + ("plate", "tiered_shelf"): ["distractor_obj", "distractor_target_container"], + ("plate", "tiered_basket"): ["distractor_obj", "distractor_source_container"], + ("placemat", "pan"): ["distractor_obj", "distractor_source_container"], + ("placemat", "pot"): ["distractor_obj", "distractor_target_container"], + ("placemat", "tiered_basket"): ["distractor_obj"], + ("placemat", "cardboard_box"): [], + ("cutting_board", "pot"): ["distractor_source_container"], + ("cutting_board", "basket"): ["distractor_source_container"], + ("cutting_board", "tiered_basket"): [ + "distractor_obj", + "distractor_target_container", + ], + ("cutting_board", "pan"): [], + ("cutting_board", "cardboard_box"): [], + ("placemat", "bowl"): ["distractor_obj", "distractor_target_container"], + ("placemat", "plate"): ["distractor_obj"], + ("placemat", "basket"): ["distractor_obj", "distractor_source_container"], + ("placemat", "tiered_shelf"): ["distractor_target_container"], + ("plate", "pan"): ["distractor_source_container", "distractor_target_container"], + ("plate", "cardboard_box"): ["distractor_source_container"], + ("plate", "bowl"): [ + "distractor_obj", + "distractor_source_container", + "distractor_target_container", + ], + ("plate", "plate"): [], + ("tray", "tiered_shelf"): ["distractor_target_container"], + ("tray", "plate"): ["distractor_source_container", "distractor_target_container"], + ("tray", "tiered_basket"): ["distractor_source_container"], + ("tray", "cardboard_box"): [ + "distractor_obj", + "distractor_source_container", + "distractor_target_container", + ], + ("tray", "pot"): ["distractor_source_container"], +} + +distractor_config_for_pretrain_novel = { + ("cutting_board", "bowl"): [], + ("cutting_board", "plate"): ["distractor_obj"], + ("cutting_board", "tiered_shelf"): [ + "distractor_obj", + "distractor_target_container", + ], + ("tray", "basket"): ["distractor_source_container"], + ("tray", "pan"): [], + ("tray", "bowl"): ["distractor_obj"], + ("plate", "basket"): ["distractor_obj", "distractor_target_container"], + ("plate", "pot"): ["distractor_source_container", "distractor_target_container"], + ("plate", "tiered_shelf"): [ + "distractor_source_container", + "distractor_target_container", + ], + ("plate", "tiered_basket"): ["distractor_obj", "distractor_source_container"], + ("placemat", "pan"): ["distractor_target_container"], + ("placemat", "pot"): ["distractor_obj"], + ("placemat", "tiered_basket"): ["distractor_source_container"], + ("placemat", "cardboard_box"): ["distractor_target_container"], +} + +distractor_config_for_posttrain = { + ("tray", "cardboard_box"): [], + ("tray", "pot"): [], + ("plate", "plate"): [], + ("placemat", "plate"): ["distractor_obj"], + ("plate", "cardboard_box"): ["distractor_obj"], + ("plate", "pan"): ["distractor_obj"], + ("placemat", "basket"): ["distractor_source_container"], + ("cutting_board", "pan"): ["distractor_source_container"], + ("cutting_board", "pot"): ["distractor_target_container"], + ("tray", "plate"): ["distractor_target_container"], + ("placemat", "bowl"): ["distractor_obj", "distractor_source_container"], + ("plate", "bowl"): ["distractor_obj", "distractor_source_container"], + ("cutting_board", "tiered_basket"): [ + "distractor_obj", + "distractor_target_container", + ], + ("cutting_board", "cardboard_box"): [ + "distractor_obj", + "distractor_target_container", + ], + ("tray", "tiered_basket"): [ + "distractor_source_container", + "distractor_target_container", + ], + ("cutting_board", "basket"): [ + "distractor_source_container", + "distractor_target_container", + ], + ("tray", "tiered_shelf"): [ + "distractor_obj", + "distractor_source_container", + "distractor_target_container", + ], + ("placemat", "tiered_shelf"): [ + "distractor_obj", + "distractor_source_container", + "distractor_target_container", + ], +} + +# Generate all task classes + +# Pre-train +pretrain_task_infos = generate_task_classes( + base_obj_cats, + base_container_combos, + prefix="PretrainPnPBase", + randomize_distractor_configs=False, + distractor_configs=distractor_config_for_pretrain_base, + obj_instance_split="A", + postfix="SplitA", +) +pretrain_task_infos.extend( + generate_task_classes( + base_obj_cats, + novel_container_combos, + prefix="PretrainPnPBase", + randomize_distractor_configs=False, + distractor_configs=distractor_config_for_pretrain_base, + obj_instance_split="A", + postfix="SplitA", + ) +) +pretrain_task_infos.extend( + generate_task_classes( + novel_obj_cats, + base_container_combos, + prefix="PretrainPnPNovel", + randomize_distractor_configs=False, + distractor_configs=distractor_config_for_pretrain_novel, + obj_instance_split="A", + postfix="SplitA", + ) +) + +# Post-train +posttrain_task_infos = generate_task_classes( + novel_obj_cats, + novel_container_combos, + prefix="PosttrainPnPNovel", + randomize_distractor_configs=False, + distractor_configs=distractor_config_for_posttrain, + obj_instance_split="A", + postfix="SplitA", +) + +eval_task_infos = generate_task_classes( + novel_obj_cats, + novel_container_combos, + prefix="EvalPnPNovel", + randomize_distractor_configs=False, + distractor_configs=distractor_config_for_posttrain, + obj_instance_split="B", + postfix="SplitB", +) + + +distractor_config_always_distractor_obj = deepcopy(distractor_config_for_posttrain) +for key, value in distractor_config_always_distractor_obj.items(): + if "distractor_obj" not in value: + if rng.random() < 0.5 and len(distractor_config_always_distractor_obj[key]) > 1: + # random drop one of the distractor keys + distractor_config_always_distractor_obj[key].remove( + rng.choice(distractor_config_always_distractor_obj[key]) + ) + distractor_config_always_distractor_obj[key].append("distractor_obj") + + +# generate posttrain tasks with a specific object group as target object +posttrain_specific_obj_task_infos = [] +for obj_group in ["fruit"]: + posttrain_specific_obj_task_infos.extend( + generate_task_classes( + [obj_group], + novel_container_combos, + prefix=f"PosttrainPnP{obj_group.title()}", + randomize_distractor_configs=False, + distractor_configs=distractor_config_always_distractor_obj, + # obj_instance_split="A", + # postfix="SplitA", + ) + ) + + +if __name__ == "__main__": + + RED = '\033[91m' + GREEN = '\033[92m' + YELLOW = '\033[93m' + BLUE = '\033[94m' + MAGENTA = '\033[95m' + CYAN = '\033[96m' + RESET = '\033[0m' # Resets color to terminal default + + # print pretrain task names + print(f"{GREEN}DC24 Pretrain task names: {len(pretrain_task_infos)} {RESET}") + for task_info in pretrain_task_infos: + print(f"{task_info['class_name']}") + + print() + # print posttrain task names + print(f"{GREEN}DC24 Posttrain task names: {len(posttrain_task_infos)} {RESET}") + for task_info in posttrain_task_infos: + print(f"{task_info['class_name']}") + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_5dc.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_5dc.py new file mode 100644 index 0000000000000000000000000000000000000000..2f8036a93e3aa4e72a3f327d9cc43d44db7ac23e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_5dc.py @@ -0,0 +1,40 @@ +import numpy as np +from typing import Tuple +from robocasa.environments.tabletop.tabletop_24dc import ( + PositionSampler as PositionSamplerOld, +) +from robocasa.environments.tabletop.tabletop_24dc import generate_task_classes + +# generate tasks with a specific object category as target object +obj_categories = ["can", "apple", "cucumber", "lemon", "bottled_water"] +container_combos = [ + ("plate", "bowl"), + ("placemat", "basket"), + ("cutting_board", "basket"), + ("tray", "plate"), + ("cutting_board", "pan"), +] +dc5_tasks_info = generate_task_classes( + obj_categories, + container_combos, + prefix="PnP5", + randomize_distractor_configs=False, # no distractor + distractor_configs=None, + postfix="NoDistractorSplitA", +) + + +if __name__ == "__main__": + + RED = "\033[91m" + GREEN = "\033[92m" + YELLOW = "\033[93m" + BLUE = "\033[94m" + MAGENTA = "\033[95m" + CYAN = "\033[96m" + RESET = "\033[0m" # Resets color to terminal default + + # print task names + print(f"{GREEN}DC5 tasks: {len(dc5_tasks_info)} {RESET}") + for task_info in dc5_tasks_info: + print(task_info["class_name"]) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_cabinet_door.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_cabinet_door.py new file mode 100644 index 0000000000000000000000000000000000000000..b072537b952098542335473e594af389281dacc0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_cabinet_door.py @@ -0,0 +1,179 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.utils.dexmg_utils import DexMGConfigHelper + + +class TabletopCabinetDoor(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic cabinet door manipulation tasks. + + Args: + behavior (str): "open" or "close". Used to define the desired + cabinet door manipulation behavior for the task + """ + + VALID_LAYOUTS = [5] + + def __init__(self, behavior=None, *args, **kwargs): + assert behavior in ["open", "close"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_table_references(self): + """ + Setup the table references for the cabinet door tasks + """ + super()._setup_table_references() + self.cabinet = self.get_fixture(FixtureType.DOOR_HINGE_SINGLE) + self.init_robot_base_pos = self.cabinet + + def get_ep_meta(self): + """ + Get the episode metadata for the cabinet door tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"{self.behavior} the cabinet door" + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the cabinet door tasks. + This includes setting the door state based on the behavior. + """ + super()._reset_internal() + if self.behavior == "open": + self.cabinet.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.cabinet.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the cabinet door tasks. + No objects needed for this task. + """ + return [] + + def _check_success(self): + """ + Check if the cabinet door manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + if self.behavior == "open": + return self.is_door_open() + elif self.behavior == "close": + return not self.is_door_open() + + return False + + def is_door_open(self): + """ + Check if the door is open. + + Returns: + bool: True if the door is open, False otherwise. + """ + door_state = self.cabinet.get_door_state(env=self)["door"] + return door_state >= 0.5 + + def get_object(self): + objects = dict() + objects["door"] = dict( + obj_name=self.cabinet.name + "_door_door", + obj_type="geom", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["open_door"] = int(self.is_door_open()) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec.subtask_1 = dict( + object_ref="door", + subtask_term_signal="open_door", + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec.subtask_1 = dict( + object_ref="door", + subtask_term_signal="open_door", + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec.subtask_2 = dict( + object_ref=None, + # subtask_term_signal="open_door_left", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + # task.task_spec_1.subtask_2 = dict( + # object_ref=None, + # subtask_term_signal=None, + # subtask_term_offset_range=None, + # selection_strategy="random", + # selection_strategy_kwargs=None, + # action_noise=0.05, + # num_interpolation_steps=5, + # num_fixed_steps=0, + # apply_noise_during_interpolation=True, + # ) + return task.to_dict() + + +class TabletopOpenCabinetDoor(TabletopCabinetDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="open", *args, **kwargs) + + +class TabletopCloseCabinetDoor(TabletopCabinetDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_cabinet_pnp.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_cabinet_pnp.py new file mode 100644 index 0000000000000000000000000000000000000000..833d097cf90d79730835ce98ee304848d54d83c7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_cabinet_pnp.py @@ -0,0 +1,246 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.environments.tabletop.tabletop_pnp import DEFAULT_DISTRACTOR_CONFIG +from robocasa.utils.dexmg_utils import DexMGConfigHelper +from robocasa.utils.object_utils import check_obj_in_receptacle, obj_inside_of + +DISTRACTOR_CONFIG = DEFAULT_DISTRACTOR_CONFIG.copy() +DISTRACTOR_CONFIG["regions"]["back_edge"]["objects"] = [ + { + "type": ["vegetable"], + "count": (1, 4), + } +] + + +class TabletopCabinetPnPClose(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the cabinet-based pick and place task. + + Args: + obj_groups (str): Object groups to sample the target object from. + exclude_obj_groups (str): Object groups to exclude from sampling the target object. + handedness (Optional[str]): Which hand to optimize object spawning for ("right" or "left"). + obj_scale (float): Scaling factor for the object. + behavior (str): "open" or "close" for cabinet door manipulation behavior. + """ + + VALID_LAYOUTS = [5] + NUM_OBJECTS = 1 + + def __init__( + self, + obj_groups="all", + exclude_obj_groups=None, + handedness="left", + obj_scale=1.0, + behavior="close", + distractor_config=DISTRACTOR_CONFIG, + use_distractors=True, + *args, + **kwargs, + ): + if handedness not in ("right", "left"): + raise ValueError("handedness must be 'right' or 'left'") + assert behavior in ["open", "close"], "Invalid behavior" + + self.obj_groups = obj_groups + self.exclude_obj_groups = exclude_obj_groups + self.handedness = handedness + self.obj_scale = obj_scale + self.behavior = behavior + + super().__init__( + *args, + **kwargs, + distractor_config=distractor_config, + use_distractors=use_distractors, + ) + + def _setup_table_references(self): + """ + Setup references for the cabinet and workspace. + """ + super()._setup_table_references() + self.cabinet = self.get_fixture(FixtureType.DOOR_HINGE_SINGLE) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.45, 0.55)) + ) + self.init_robot_base_pos = self.cabinet + + def get_ep_meta(self): + """ + Get the episode metadata for the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang(obj_name="obj") + ep_meta[ + "lang" + ] = f"pick up the {obj_lang}, place it into the cabinet and close the cabinet" + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the cabinet door tasks. + This includes setting the door state based on the behavior. + """ + super()._reset_internal() + if self.behavior == "open": + self.cabinet.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.cabinet.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Define object configurations for pick and place. + """ + cfgs = [] + handedness = ( + self.handedness if self.handedness else self.rng.choice(["left", "right"]) + ) + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + object_scale=self.obj_scale, + placement=dict( + fixture=self.counter, + size=(0.2, 0.2), + pos=((0.5, -0.8) if handedness == "right" else (-0.5, -0.8)), + ), + obj_registries=["objaverse"], + ) + ) + return cfgs + + def _check_success(self): + """ + Check if the object is successfully placed inside the cabinet. + """ + inside_of_cabinet = obj_inside_of( + env=self, + obj_name=self.objects["obj"].name, + fixture_id=self.cabinet, + partial_check=True, + ) + door_state_correct = ( + self.is_door_open() if self.behavior == "open" else self.is_door_closed() + ) + return inside_of_cabinet and door_state_correct + + def is_door_open(self): + """ + Check if the cabinet door is opened. + """ + door_state = self.cabinet.get_door_state(env=self)["door"] + return door_state >= 0.5 + + def is_door_closed(self): + """ + Check if the cabinet door is closed. + """ + door_state = self.cabinet.get_door_state(env=self)["door"] + return door_state <= 0.005 + + def get_object(self): + """ + Return object references for the task. + """ + objects = { + "obj": dict( + obj_name=self.objects["obj"].root_body, + obj_type="body", + obj_joint=None, + ), + "cabinet": dict( + obj_name=self.cabinet.name + "_door_door", + obj_type="geom", + obj_joint=None, + ), + } + return objects + + def get_subtask_term_signals(self): + """ + Define subtask termination signals. + """ + signals = { + "grasp_object": int( + self._check_grasp( + gripper=self.robots[0].gripper["left"], + object_geoms=self.objects["obj"], + ) + ), + "obj_in_cabinet": int( + OU.check_obj_fixture_contact(self, "obj", self.cabinet) + ), + } + return signals + + @staticmethod + def task_config(): + return { + "task_spec_1": { + "subtask_1": dict( + object_ref="obj", + subtask_term_signal="grasp_object", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + "subtask_2": dict( + object_ref="cabinet", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + }, + "task_spec_0": { + "subtask_1": dict( + object_ref="cabinet", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + }, + } + + +class PnPCupToCabinetClose(TabletopCabinetPnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="cup", *args, **kwargs, obj_scale=1.25) + + +class PnPBottleToCabinetClose(TabletopCabinetPnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="bottled_water", *args, **kwargs, obj_scale=1.1) + + +class PnPWineToCabinetClose(TabletopCabinetPnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="wine", *args, **kwargs, obj_scale=1) + + +class PnPCanToCabinetClose(TabletopCabinetPnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="can", *args, **kwargs) + + +class PnPAppleToCabinetClose(TabletopCabinetPnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="apple", *args, **kwargs, obj_scale=1.7) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_drawer_door.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_drawer_door.py new file mode 100644 index 0000000000000000000000000000000000000000..aae49640870f3ee63d7fb44d7fc04bfeecd60f1e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_drawer_door.py @@ -0,0 +1,120 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.utils.dexmg_utils import DexMGConfigHelper + + +class TabletopDrawerDoor(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic drawer door manipulation tasks. + + Args: + behavior (str): "open" or "close". Used to define the desired + drawer door manipulation behavior for the task + """ + + VALID_LAYOUTS = [4] + + def __init__(self, behavior=None, *args, **kwargs): + assert behavior in ["open", "close"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_table_references(self): + """ + Setup the table references for the drawer door tasks + """ + super()._setup_table_references() + self.drawer = self.get_fixture("drawer_tabletop_main_group") + self.init_robot_base_pos = self.drawer + + def get_ep_meta(self): + """ + Get the episode metadata for the drawer door tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"{self.behavior} the drawer door" + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the drawer door tasks. + This includes setting the door state based on the behavior. + """ + super()._reset_internal() + if self.behavior == "open": + self.drawer.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.drawer.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the drawer door tasks. + No objects needed for this task. + """ + return [] + + def _check_success(self): + """ + Check if the drawer door manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + door_state = self.drawer.get_door_state(env=self)["door"] + if self.behavior == "open": + return door_state >= 0.5 + elif self.behavior == "close": + return door_state <= 0.005 + + return False + + def get_object(self): + objects = dict() + objects["door"] = dict( + obj_name=self.drawer.name + "_door_handle_handle", + obj_type="geom", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["open_door"] = int(self._check_success()) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec.subtask_1 = dict( + object_ref="door", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + +class TabletopOpenDrawerDoor(TabletopDrawerDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="open", *args, **kwargs) + + +class TabletopCloseDrawerDoor(TabletopDrawerDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_drawer_pnp.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_drawer_pnp.py new file mode 100644 index 0000000000000000000000000000000000000000..d7bc3274b47a8ba687b1d26a0085d8b7044ecb19 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_drawer_pnp.py @@ -0,0 +1,292 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.environments.tabletop.tabletop_pnp import DEFAULT_DISTRACTOR_CONFIG +from robocasa.utils.dexmg_utils import DexMGConfigHelper +from robocasa.utils.object_utils import obj_inside_of + +DISTRACTOR_CONFIG = DEFAULT_DISTRACTOR_CONFIG.copy() +DISTRACTOR_CONFIG["regions"]["back_edge"]["objects"] = [ + { + "type": ["vegetable"], + "count": (1, 4), + } +] +DISTRACTOR_CONFIG["regions"]["back_edge"]["fixtures"] = [ + { + "type": "toaster", + "count": (0, 1), + }, + { + "type": "plant", + "count": (0, 1), + }, +] + + +class TabletopDrawerPnPClose(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic counter to container pick and place task. + + Args: + container_type (str): Type of container to place the object in. + + obj_groups (str): Object groups to sample the target object from. + + exclude_obj_groups (str): Object groups to exclude from sampling the target object. + + distractor_config (dict): Configuration for distractor objects. + + use_distractors (bool): Whether to use distractor objects. + + handedness (Optional[str]): Which hand to optimize object spawning for ("right" or "left"). + + source_container (str): Source container to sample the target object from. + + target_container (str): Target container to place the object in. + """ + + VALID_LAYOUTS = [4] + NUM_OBJECTS = 1 + + def __init__( + self, + obj_groups="all", + exclude_obj_groups=None, + source_container=None, + source_container_size=(0.5, 0.5), + target_container=None, + target_container_size=(0.5, 0.5), + handedness="left", + behavior="close", + obj_scale=1.0, + distractor_config=DISTRACTOR_CONFIG, + use_distractors=True, + *args, + **kwargs, + ): + if handedness is not None and handedness not in ("right", "left"): + raise ValueError("handedness must be 'right' or 'left'") + self.target_container = target_container + self.source_container = source_container + self.source_container_size = source_container_size + self.target_container_size = target_container_size + self.obj_groups = obj_groups + self.obj_scale = obj_scale + self.exclude_obj_groups = exclude_obj_groups + self.handedness = handedness + self.behavior = behavior + + super().__init__( + *args, + **kwargs, + distractor_config=distractor_config, + use_distractors=use_distractors, + ) + + def _setup_table_references(self): + """ + Setup the table references for the drawer door tasks + """ + super()._setup_table_references() + self.drawer = self.get_fixture("drawer_tabletop_main_group") + self.init_robot_base_pos = self.drawer + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.45, 0.55)) + ) + + def get_ep_meta(self): + """ + Get the episode metadata for the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang(obj_name="obj") + ep_meta[ + "lang" + ] = f"pick up the {obj_lang}, place it into the drawer and close the drawer" + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + handedness = ( + self.handedness + if self.handedness is not None + else self.rng.choice(["left", "right"]) + ) + # Add objects to manipulate + cfgs.append( + dict( + name=f"obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + object_scale=self.obj_scale, + placement=dict( + fixture=self.counter, + size=(0.2, 0.2), + pos=( + (0.5, -0.8) if handedness == "right" else (-0.5, -0.7) + ), # place object in right front corner if right handed + ), + obj_registries=["objaverse"], + ) + ) + return cfgs + + def _check_success(self): + """ + Check if the object is successfully placed inside the drawer. + """ + inside_of_drawer = obj_inside_of( + env=self, + obj_name=self.objects["obj"].name, + fixture_id=self.drawer, + partial_check=True, + ) + door_state = self.drawer.get_door_state(env=self)["door"] + door_state_correct = ( + door_state >= 0.5 if self.behavior == "open" else door_state <= 0.005 + ) + return inside_of_drawer and door_state_correct + + def get_object(self): + """ + Return object references for the task. + """ + objects = dict() + objects["obj"] = dict( + obj_name=self.objects["obj"].root_body, + obj_type="body", + obj_joint=None, + ) + objects["drawer"] = dict( + obj_name=self.drawer.name + "_bottom", + obj_type="geom", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["grasp_object"] = int( + self._check_grasp( + gripper=self.robots[0].gripper["left"], + object_geoms=self.objects["obj"], + ) + ) + signals["obj_in_drawer"] = int( + OU.check_obj_fixture_contact(self, "obj", self.drawer) + ) + + return signals + + def _reset_internal(self): + """ + Reset the environment internal state for the drawer door tasks. + This includes setting the door state based on the behavior. + """ + super()._reset_internal() + if self.behavior == "open": + self.drawer.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.drawer.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + @staticmethod + def task_config(): + return { + "task_spec_1": { + "subtask_1": dict( + object_ref="obj", + subtask_term_signal="grasp_object", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + "subtask_2": dict( + object_ref="drawer", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + }, + "task_spec_0": { + "subtask_1": dict( + object_ref="drawer", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + }, + } + + +class PnPCupToDrawerClose(TabletopDrawerPnPClose): + """ + Class encapsulating the atomic cup to bowl pick and place task. + A deliberately simple task used for testing. + + cup is chosen as it's easy to grasp and place. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="cup", *args, **kwargs, obj_scale=1.1) + + +class PnPBottleToDrawerClose(TabletopDrawerPnPClose): + """ + Class encapsulating the atomic bottle to bowl pick and place task. + A deliberately simple task used for testing. + + bottle is chosen as it's easy to grasp and place. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="bottled_water", *args, **kwargs, obj_scale=1.1) + + +class PnPWineToDrawerClose(TabletopDrawerPnPClose): + """ + Class encapsulating the atomic wine to bowl pick and place task. + A deliberately simple task used for testing. + + wine is chosen as it's easy to grasp and place. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="wine", *args, **kwargs, obj_scale=0.9) + + +class PnPCanToDrawerClose(TabletopDrawerPnPClose): + """ + Class encapsulating the atomic can to bowl pick and place task. + A deliberately simple task used for testing. + + can is chosen as it's easy to grasp and place. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="can", *args, **kwargs, obj_scale=1.2) + + +class PnPAppleToDrawerClose(TabletopDrawerPnPClose): + """ + Class encapsulating the atomic apple to bowl pick and place task. + A deliberately simple task used for testing. + + apple is chosen as it's easy to grasp and place. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="apple", *args, **kwargs, obj_scale=1.1) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_laptop.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_laptop.py new file mode 100644 index 0000000000000000000000000000000000000000..0a36c60239a44d0ac0f45f1dc6d011d3c746cf9e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_laptop.py @@ -0,0 +1,202 @@ +import numpy as np + +from robocasa.utils.dexmg_utils import DexMGConfigHelper +import robocasa.utils.object_utils as OU + +from robocasa import Tabletop +from robocasa.environments.tabletop.tabletop_pnp import DEFAULT_DISTRACTOR_CONFIG +from robocasa.models.fixtures import FixtureType +from robosuite.utils.mjcf_utils import string_to_array + +# Default distractor configuration for TabletopLaptopInteraction environment +DEFAULT_DISTRACTOR_CONFIG = { + "regions": { + "left_edge": { + "placement": { + "pos": (-1, 0), + "size": (0.4, 1.2), + }, + "fixtures": [ + { + "type": "toaster", + "count": (0, 1), + }, + { + "type": "paper_towel", + "count": (0, 1), + }, + { + "type": "plant", + "count": (0, 1), + }, + ], + "objects": [], + }, + "right_edge": { + "placement": { + "pos": (1, 0), + "size": (0.4, 1.2), + }, + "fixtures": [ + { + "type": "toaster", + "count": (0, 1), + }, + { + "type": "paper_towel", + "count": (0, 1), + }, + { + "type": "plant", + "count": (0, 1), + }, + ], + "objects": [], + }, + } +} + + +class TabletopLaptopInteraction(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic laptop interaction tasks. + """ + + VALID_LAYOUTS = [0] + + def __init__( + self, + behavior="open", + distractor_config=None, + use_distractors=True, + *args, + **kwargs + ): + assert behavior in ["open", "close"] + self.behavior = behavior + distractor_config = distractor_config or DEFAULT_DISTRACTOR_CONFIG + super().__init__( + distractor_config=distractor_config, + use_distractors=use_distractors, + *args, + **kwargs + ) + + def _reset_internal(self): + _, _, self._laptop = self.object_placements["obj"] + self._lid_joint = self._laptop.joints[0] + self._lid_joint_range = string_to_array( + self._laptop.get_joint("lid_hinge").attrib["range"] + ) + lid_range = np.max(self._lid_joint_range) - np.min(self._lid_joint_range) + closed_offset = 0.1 * lid_range + rnd_offset = self.rng.uniform(closed_offset) + lid_angle = ( + np.min(self._lid_joint_range) + closed_offset + rnd_offset + if self.behavior == "open" + else np.max(lid_range) - rnd_offset + ) + self.sim.data.set_joint_qpos(self._lid_joint, lid_angle) + super()._reset_internal() + + def _setup_table_references(self): + super()._setup_table_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.45, 0.55)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + if self.behavior == "open": + ep_meta["lang"] = "open lid of the laptop" + elif self.behavior == "close": + ep_meta["lang"] = "close lid of the laptop" + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=["laptop"], + placement=dict(fixture=self.counter, size=(0.5, 0.5), pos=(0.0, 0.0)), + ) + ) + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, obj_name="obj") + lid_qpos = self.sim.data.get_joint_qpos(self._lid_joint) + closed = lid_qpos <= np.deg2rad(10) + opened = lid_qpos >= np.deg2rad(85) + if self.behavior == "open": + return opened and gripper_obj_far + elif self.behavior == "close": + return closed and gripper_obj_far + + def get_object(self): + objects = dict() + objects["obj"] = dict( + obj_name=self.objects["obj"].root_body, obj_type="body", obj_joint=None + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["contact_laptop"] = int( + self.check_contact( + self.robots[0].gripper["right"], + self.objects["obj"], + ) + ) + return signals + + @staticmethod + def task_config(): + # task_spec_0 for right hand, task_spec_1 for left hand + task = DexMGConfigHelper.AttrDict() + task.task_spec_0.subtask_1 = dict( + object_ref="obj", + subtask_term_signal="contact_laptop", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_0.subtask_2 = dict( + object_ref="obj", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + +class TabletopLaptopOpen(TabletopLaptopInteraction): + def __init__(self, *args, **kwargs): + super().__init__(behavior="open", *args, **kwargs) + + +class TabletopLaptopClose(TabletopLaptopInteraction): + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave.py new file mode 100644 index 0000000000000000000000000000000000000000..564b9c45b03b984e20800bdde6e980aeed64d635 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave.py @@ -0,0 +1,121 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.utils.dexmg_utils import DexMGConfigHelper + + +class TabletopMicrowavePressButton(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic microwave press button tasks. + + Args: + behavior (str): "turn_on" or "turn_off". Used to define the desired + microwave manipulation behavior for the task + """ + + VALID_LAYOUTS = [2] + + def __init__(self, behavior="turn_on", *args, **kwargs): + assert behavior in ["turn_on", "turn_off"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_table_references(self): + """ + Setup the kitchen references for the microwave tasks + """ + super()._setup_table_references() + self.microwave = self.get_fixture(FixtureType.MICROWAVE) + if self.behavior == "turn_off": + self.microwave._turned_on = True + self.init_robot_base_pos = self.microwave + + def get_ep_meta(self): + """ + Get the episode metadata for the microwave tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + if self.behavior == "turn_on": + ep_meta["lang"] = "press the start button on the microwave" + elif self.behavior == "turn_off": + ep_meta["lang"] = "press the stop button on the microwave" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the microwave tasks. This includes the object placement configurations. + Place the object inside the microwave and on top of another container object inside the microwave + + Returns: + list: List of object configurations. + """ + cfgs = [] + + return cfgs + + def _check_success(self): + """ + Check if the microwave manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + turned_on = self.microwave.get_state()["turned_on"] + gripper_button_far = self.microwave.gripper_button_far( + self, button="start_button" if self.behavior == "turn_on" else "stop_button" + ) + + if self.behavior == "turn_on": + return turned_on and gripper_button_far + elif self.behavior == "turn_off": + return not turned_on and gripper_button_far + + def get_object(self): + objects = dict() + objects["button"] = dict( + obj_name=self.microwave.name + "_start_button", + obj_type="geom", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["press_button"] = int(self._check_success()) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec.subtask_1 = dict( + object_ref="button", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + +class TabletopTurnOnMicrowave(TabletopMicrowavePressButton): + def __init__(self, behavior=None, *args, **kwargs): + super().__init__(behavior="turn_on", *args, **kwargs) + + +class TabletopTurnOffMicrowave(TabletopMicrowavePressButton): + def __init__(self, behavior=None, *args, **kwargs): + super().__init__(behavior="turn_off", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave_door.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave_door.py new file mode 100644 index 0000000000000000000000000000000000000000..72b7e91ba7bd481e221f8274221f0e37dafd1e9d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave_door.py @@ -0,0 +1,119 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.utils.dexmg_utils import DexMGConfigHelper + + +class TabletopMicrowaveDoor(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic microwave door manipulation tasks. + + Args: + behavior (str): "open" or "close". Used to define the desired + microwave door manipulation behavior for the task + """ + + VALID_LAYOUTS = [2] + + def __init__(self, behavior=None, *args, **kwargs): + assert behavior in ["open", "close"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_table_references(self): + """ + Setup the table references for the microwave door tasks + """ + super()._setup_table_references() + self.microwave = self.get_fixture(FixtureType.MICROWAVE) + self.init_robot_base_pos = self.microwave + + def get_ep_meta(self): + """ + Get the episode metadata for the microwave door tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"{self.behavior} the microwave door" + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the microwave door tasks. + This includes setting the door state based on the behavior. + """ + super()._reset_internal() + if self.behavior == "open": + self.microwave.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.microwave.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the microwave door tasks. + No objects needed for this task. + """ + return [] + + def _check_success(self): + """ + Check if the microwave door manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + door_state = self.microwave.get_door_state(env=self)["door"] + + if self.behavior == "open": + return door_state >= 0.5 + elif self.behavior == "close": + return door_state <= 0.005 + + def get_object(self): + objects = dict() + objects["door"] = dict( + obj_name=self.microwave.name + "_door_handle", + obj_type="geom", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["open_door"] = int(self._check_success()) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec.subtask_1 = dict( + object_ref="door", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + +class TabletopOpenMicrowaveDoor(TabletopMicrowaveDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="open", *args, **kwargs) + + +class TabletopCloseMicrowaveDoor(TabletopMicrowaveDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave_pnp.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave_pnp.py new file mode 100644 index 0000000000000000000000000000000000000000..e5d5cfc3d19b689a59fe80ea5d972f7a298f9980 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_microwave_pnp.py @@ -0,0 +1,232 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.environments.tabletop.tabletop_pnp import DEFAULT_DISTRACTOR_CONFIG +from robocasa.utils.dexmg_utils import DexMGConfigHelper +from robocasa.utils.object_utils import obj_inside_of + +DISTRACTOR_CONFIG = DEFAULT_DISTRACTOR_CONFIG.copy() +DISTRACTOR_CONFIG["regions"]["back_edge"]["objects"] = [ + { + "type": ["vegetable"], + "count": (1, 4), + } +] + + +class TabletopMicrowavePnPClose(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the microwave-based pick and place task. + + Args: + obj_groups (str): Object groups to sample the target object from. + exclude_obj_groups (str): Object groups to exclude from sampling the target object. + handedness (Optional[str]): Which hand to optimize object spawning for ("right" or "left"). + obj_scale (float): Scaling factor for the object. + behavior (str): "open" or "close" for microwave door manipulation behavior. + """ + + VALID_LAYOUTS = [2] + NUM_OBJECTS = 1 + + def __init__( + self, + obj_groups="all", + exclude_obj_groups=None, + handedness="right", + obj_scale=1.0, + behavior="close", + distractor_config=DISTRACTOR_CONFIG, + use_distractors=True, + *args, + **kwargs, + ): + if handedness not in ("right", "left"): + raise ValueError("handedness must be 'right' or 'left'") + assert behavior in ["open", "close"], "Invalid behavior" + + self.obj_groups = obj_groups + self.exclude_obj_groups = exclude_obj_groups + self.handedness = handedness + self.obj_scale = obj_scale + self.behavior = behavior + + super().__init__( + *args, + **kwargs, + distractor_config=distractor_config, + use_distractors=use_distractors, + ) + + def _setup_table_references(self): + """ + Setup references for the microwave and workspace. + """ + super()._setup_table_references() + self.microwave = self.get_fixture(FixtureType.MICROWAVE) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.45, 0.55)) + ) + self.init_robot_base_pos = self.microwave + + def get_ep_meta(self): + """ + Get the episode metadata for the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang(obj_name="obj") + ep_meta[ + "lang" + ] = f"pick up the {obj_lang}, place it into the microwave and close the microwave" + return ep_meta + + def _get_obj_cfgs(self): + """ + Define object configurations for pick and place. + """ + cfgs = [] + handedness = ( + self.handedness if self.handedness else self.rng.choice(["left", "right"]) + ) + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + object_scale=self.obj_scale, + placement=dict( + fixture=self.counter, + size=(0.2, 0.2), + pos=((0.5, -0.8) if handedness == "right" else (-0.5, -0.2)), + ), + obj_registries=["objaverse"], + ) + ) + return cfgs + + def _check_success(self): + """ + Check if the object is successfully placed inside the microwave. + """ + inside_of_microwave = obj_inside_of( + env=self, + obj_name=self.objects["obj"].name, + fixture_id=self.microwave, + partial_check=True, + ) + door_state = self.microwave.get_door_state(env=self)["door"] + door_state_correct = ( + door_state >= 0.5 if self.behavior == "open" else door_state <= 0.005 + ) + return inside_of_microwave and door_state_correct + + def get_object(self): + """ + Return object references for the task. + """ + objects = { + "obj": dict( + obj_name=self.objects["obj"].root_body, + obj_type="body", + obj_joint=None, + ), + "microwave": dict( + obj_name=self.microwave.name + "_door_handle", + obj_type="geom", + obj_joint=None, + ), + } + return objects + + def get_subtask_term_signals(self): + """ + Define subtask termination signals. + """ + signals = { + "grasp_object": int( + self._check_grasp( + gripper=self.robots[0].gripper["right"], + object_geoms=self.objects["obj"], + ) + ), + "obj_in_microwave": int( + OU.check_obj_fixture_contact(self, "obj", self.microwave) + ), + } + return signals + + def _reset_internal(self): + """ + Reset the environment for the microwave PnP task. + """ + super()._reset_internal() + if self.behavior == "open": + self.microwave.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.microwave.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + @staticmethod + def task_config(): + return { + "task_spec_0": { + "subtask_1": dict( + object_ref="obj", + subtask_term_signal="grasp_object", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + "subtask_2": dict( + object_ref="microwave", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + }, + "task_spec_1": { + "subtask_1": dict( + object_ref="microwave", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.0, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ), + }, + } + + +class PnPCupToMicrowaveClose(TabletopMicrowavePnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="cup", *args, **kwargs, obj_scale=1.25) + + +class PnPCornToMicrowaveClose(TabletopMicrowavePnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="corn", *args, **kwargs, obj_scale=1.1) + + +class PnPPotatoToMicrowaveClose(TabletopMicrowavePnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="potato", *args, **kwargs, obj_scale=1.3) + + +class PnPEggplantToMicrowaveClose(TabletopMicrowavePnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="eggplant", *args, **kwargs, obj_scale=1.4) + + +class PnPMilkToMicrowaveClose(TabletopMicrowavePnPClose): + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="milk", *args, **kwargs, obj_scale=1) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_multi_pnp.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_multi_pnp.py new file mode 100644 index 0000000000000000000000000000000000000000..3872f37a200c2425149867f5d4c060b6879d3c53 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_multi_pnp.py @@ -0,0 +1,232 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.utils.dexmg_utils import DexMGConfigHelper + + +class PutAllObjectsInContainer(Tabletop, DexMGConfigHelper): + """ + Class for tasks where multiple objects need to be placed in a container. + Objects are randomly spawned on the counter and need to be placed in the container. + + Args: + container_type (str): Type of container to place objects in. + + num_objects (int): Number of objects to spawn and manipulate. + + obj_groups (list): List of object groups to sample target objects from. + + exclude_obj_groups (list): Object groups to exclude from sampling target objects. + + handedness (str): Which hand to optimize object spawning for ("right" or "left"). + """ + + VALID_LAYOUTS = [0] + NUM_OBJECTS = 3 + + def __init__( + self, + obj_groups=None, + exclude_obj_groups=None, + container_type="container", + handedness="right", + *args, + **kwargs, + ): + if handedness is not None and handedness not in ("right", "left"): + raise ValueError("handedness must be 'right' or 'left'") + self.container_type = container_type + self.obj_groups = obj_groups or ["vegetable", "fruit", "can"] + self.exclude_obj_groups = exclude_obj_groups + self.handedness = handedness + super().__init__(*args, **kwargs) + + def _setup_table_references(self): + super()._setup_table_references() + + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.5, 0.5)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + container_lang = self.get_obj_lang(obj_name="container") + obj_langs = [ + self.get_obj_lang(obj_name=f"obj_{i}") for i in range(self.NUM_OBJECTS) + ] + if len(obj_langs) == 1: + ep_meta["lang"] = f"put the {obj_langs[0]} into the {container_lang}" + else: + instruction = f"put the {obj_langs[0]}" + for obj in obj_langs[1:-1]: + instruction += f", then the {obj}" + instruction += ( + f", and finally the {obj_langs[-1]} into the {container_lang}" + ) + ep_meta["lang"] = instruction + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + handedness = ( + self.handedness + if self.handedness is not None + else self.rng.choice(["left", "right"]) + ) + + # Add container + cfgs.append( + dict( + name="container", + obj_groups=self.container_type, + placement=dict( + fixture=self.counter, + size=(0.5, 0.5), + pos=((0, -0.5)), + ), + ) + ) + + # Add objects to manipulate + for i in range(self.NUM_OBJECTS): + cfgs.append( + dict( + name=f"obj_{i}", + obj_groups=self.obj_groups[i % len(self.obj_groups)], + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.3, 0.3), + pos=( + (0.5, -1) if handedness == "right" else (-0.5, -1) + ), # place object in right front corner if right handed + ), + ) + ) + return cfgs + + def _check_success(self): + # Check if all objects are in the container + all_objects_in_container = True + for i in range(self.NUM_OBJECTS): + if not OU.check_obj_in_receptacle(self, f"obj_{i}", "container"): + all_objects_in_container = False + break + + gripper_empty = all( + OU.gripper_obj_far(self, obj_name=f"obj_{i}") + for i in range(self.NUM_OBJECTS) + ) + + return all_objects_in_container and gripper_empty + + def get_object(self): + objects = dict() + for i in range(self.NUM_OBJECTS): + objects[f"obj_{i}"] = dict( + obj_name=self.objects[f"obj_{i}"].root_body, + obj_type="body", + obj_joint=None, + ) + objects["container"] = dict( + obj_name=self.objects["container"].root_body, + obj_type="body", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + # TODO: support both hands + signals = dict() + prev_signals = getattr(self, "_prev_signals", {}) + prev_obj_in_container = True # First object has no prerequisites + for i in range(self.NUM_OBJECTS): + # Grasp signal can only be true if previous object is in container + grasp_check = self._check_grasp( + gripper=self.robots[0].gripper["right"], + object_geoms=self.objects[f"obj_{i}"], + ) + grasp_signal = f"grasp_obj_{i}" + signals[grasp_signal] = int(grasp_check and prev_obj_in_container) + + # Container signal can only be true if object is grasped and previous object is in container + in_container = OU.check_obj_in_receptacle(self, f"obj_{i}", "container") + container_signal = f"obj_{i}_in_container" + signals[container_signal] = int(in_container and prev_obj_in_container) + + # Update prerequisite for next iteration + prev_obj_in_container = signals[container_signal] + + # Store signals for next iteration + self._prev_signals = signals.copy() + return signals + + @staticmethod + def task_config(): + task_spec_0 = {} + for i in range(PutAllObjectsInContainer.NUM_OBJECTS): + # Subtask to grasp object i + task_spec_0[f"subtask_{2*i+1}"] = dict( + object_ref=f"obj_{i}", + subtask_term_signal=f"grasp_obj_{i}", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + # Subtask to move object i to container + task_spec_0[f"subtask_{2*i+2}"] = dict( + object_ref="container", + subtask_term_signal=f"obj_{i}_in_container", + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + + # Set final subtask's termination signal to 0 + task_spec_0[f"subtask_{2*PutAllObjectsInContainer.NUM_OBJECTS}"][ + "subtask_term_signal" + ] = None + + return { + "task_spec_0": task_spec_0, + "task_spec_1": { + "subtask_1": dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + }, + } + + +class PutAllObjectsInBasket(PutAllObjectsInContainer): + """ + Class for tasks where multiple objects need to be placed in a basket. + Objects are randomly spawned on the counter and need to be placed in the basket. + """ + + def __init__(self, *args, **kwargs): + super().__init__(container_type="basket", *args, **kwargs) + + +class PutAllObjectsOnPlate(PutAllObjectsInContainer): + """ + Class for tasks where multiple objects need to be placed on a plate. + """ + + def __init__(self, *args, **kwargs): + super().__init__(container_type="plate", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_object_showcase.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_object_showcase.py new file mode 100644 index 0000000000000000000000000000000000000000..9b7c148728f54ab321994d7943750b02f18d5dd7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_object_showcase.py @@ -0,0 +1,50 @@ +from robocasa.environments.tabletop.tabletop import * + + +class TabletopObjectShowcase(Tabletop): + """ + Class for displaying a single object on the tabletop. + + Args: + obj_groups (str): Object groups to sample the target object from. + exclude_obj_groups (str): Object groups to exclude from sampling the target object. + """ + + VALID_LAYOUTS = [0] + + def __init__(self, obj_groups="all", exclude_obj_groups=None, *args, **kwargs): + self.obj_groups = obj_groups + self.exclude_obj_groups = exclude_obj_groups + super().__init__(*args, **kwargs) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + ep_meta["lang"] = f"observe the {obj_lang}. the task cannot be completed." + return ep_meta + + def _setup_table_references(self): + super()._setup_table_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.45, 0.55)) + ) + self.init_robot_base_pos = self.counter + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + placement=dict( + fixture=self.counter, + size=(1, 1), + pos=(0.0, 0.0), # center of table + ), + ) + ) + return cfgs + + def _check_success(self): + return False diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_pnp.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_pnp.py new file mode 100644 index 0000000000000000000000000000000000000000..f77d5c89afe8e9cc970964de2f6971d1a00617d1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/environments/tabletop/tabletop_pnp.py @@ -0,0 +1,2081 @@ +from robocasa.environments.tabletop.tabletop import * +from robocasa.utils.dexmg_utils import DexMGConfigHelper +from robosuite.models.objects import BallObject +from robosuite.utils.mjcf_utils import string_to_array + + +# Default distractor configuration for TabletopPnP environment +DEFAULT_DISTRACTOR_CONFIG = { + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.4), + }, + "fixtures": [ + { + "type": "toaster", + "count": (0, 1), + }, + { + "type": "paper_towel", + "count": (0, 1), + }, + { + "type": "plant", + "count": (1, 2), + }, + ], + "objects": [], + } + } +} + + +class TabletopPnP(Tabletop, DexMGConfigHelper): + """ + Class encapsulating the atomic counter to container pick and place task. + + Args: + container_type (str): Type of container to place the object in. + + obj_groups (str): Object groups to sample the target object from. + + exclude_obj_groups (str): Object groups to exclude from sampling the target object. + + distractor_config (dict): Configuration for distractor objects. + + use_distractors (bool): Whether to use distractor objects. + + handedness (Optional[str]): Which hand to optimize object spawning for ("right" or "left"). + + source_container (str): Source container to sample the target object from. + + target_container (str): Target container to place the object in. + """ + + VALID_LAYOUTS = [0] + + def __init__( + self, + obj_groups="all", + exclude_obj_groups=None, + source_container=None, + source_container_size=(0.5, 0.5), + target_container=None, + target_container_size=(0.5, 0.5), + distractor_config=DEFAULT_DISTRACTOR_CONFIG, + use_distractors=True, + handedness="right", + *args, + **kwargs, + ): + if handedness is not None and handedness not in ("right", "left"): + raise ValueError("handedness must be 'right' or 'left'") + self.target_container = target_container + self.source_container = source_container + self.source_container_size = source_container_size + self.target_container_size = target_container_size + self.obj_groups = obj_groups + self.exclude_obj_groups = exclude_obj_groups + self.handedness = handedness + + super().__init__( + distractor_config=distractor_config, + use_distractors=use_distractors, + *args, + **kwargs, + ) + + def _setup_table_references(self): + super()._setup_table_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.45, 0.55)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + source_container_lang = ( + self.get_obj_lang(obj_name="obj_container") + if self.source_container + else "counter" + ) + target_container_lang = ( + self.get_obj_lang(obj_name="container") + if self.target_container + else "counter" + ) + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the {source_container_lang} and place it in the {target_container_lang}" + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + + if self.target_container: + cfgs.append( + dict( + name="container", + obj_groups=self.target_container, + placement=dict( + fixture=self.counter, + size=self.target_container_size, + pos=(0.9, -0.3) if self.handedness == "right" else (-0.9, -0.3), + ), + ) + ) + + # Randomize handedness per invoke rather than storing it + handedness = ( + self.handedness if self.handedness else self.rng.choice(["left", "right"]) + ) + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + placement=dict( + fixture=self.counter, + size=( + self.source_container_size + if self.source_container + else (0.3, 0.3) + ), + pos=(0.5, -0.8) if handedness == "right" else (-0.5, -0.8), + try_to_place_in=self.source_container, + ), + ) + ) + return cfgs + + def _check_success(self): + if self.target_container: + gripper_container_far = OU.any_gripper_obj_far(self, obj_name="container") + gripper_obj_far = OU.any_gripper_obj_far(self, obj_name="obj") + obj_in_container = OU.check_obj_in_receptacle(self, "obj", "container") + obj_on_counter = OU.check_obj_fixture_contact(self, "obj", self.counter) + container_upright = OU.check_obj_upright(self, "container", threshold=0.8) + return ( + gripper_container_far + and gripper_obj_far + and obj_in_container + and not obj_on_counter + and container_upright + ) + else: + gripper_obj_far = OU.any_gripper_obj_far(self, obj_name="obj") + obj_on_counter = OU.check_obj_fixture_contact(self, "obj", self.counter) + return gripper_obj_far and obj_on_counter + + def get_object(self): + objects = dict() + objects["obj"] = dict( + obj_name=self.objects["obj"].root_body, obj_type="body", obj_joint=None + ) + + objects["container"] = dict( + obj_name=self.objects["container"].root_body, + obj_type="body", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["grasp_object"] = int( + self._check_grasp( + gripper=self.robots[0].gripper["right"], + object_geoms=self.objects["obj"], + ) + ) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec_0.subtask_1 = dict( + selection_object_ref="container", + object_ref="obj", + subtask_term_signal="grasp_object", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_0.subtask_2 = dict( + object_ref="container", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + def visualize_spawn_region(self, obj_name="container"): + """ + Draws a single site representing the full spawn region as a 3D box, cylinder, or sphere. + """ + import robocasa.utils.object_utils as OU + import numpy as np + import mujoco + + highest_spawn_region = OU.get_highest_spawn_region(self, self.objects[obj_name]) + + for spawn in self.objects[obj_name].spawns: + if spawn != highest_spawn_region: + continue + + # Get spawn region parameters + region_points = OU.calculate_spawn_region(self, spawn) + spawn_type = spawn.get("type", "box") + + # Create or update geom + self.viewer.update() + current_geom = None + for geom_idx in range(self.viewer.viewer.user_scn.ngeom): + if self.viewer.viewer.user_scn.geoms[geom_idx].label == spawn.get( + "name" + ): + current_geom = self.viewer.viewer.user_scn.geoms[geom_idx] + break + if current_geom is None: + self.viewer.viewer.user_scn.ngeom += 1 + current_geom = self.viewer.viewer.user_scn.geoms[ + self.viewer.viewer.user_scn.ngeom - 1 + ] + + if spawn_type == "box": + p0, px, py, pz = region_points + v_x = px - p0 + v_y = py - p0 + v_z = pz - p0 + center = p0 + 0.5 * (v_x + v_y + v_z) + half_size = np.array( + [ + np.linalg.norm(v_x) / 2.0, + np.linalg.norm(v_y) / 2.0, + np.linalg.norm(v_z) / 2.0, + ] + ) + R = np.column_stack( + ( + v_x / np.linalg.norm(v_x), + v_y / np.linalg.norm(v_y), + v_z / np.linalg.norm(v_z), + ) + ) + geom_type = mujoco.mjtGeom.mjGEOM_BOX + + elif spawn_type == "cylinder": + p0, axis_vector, radius = region_points + height = np.linalg.norm(axis_vector) + center = p0 + 0.5 * axis_vector + half_size = np.array([radius, height / 2, radius]) + z_axis = axis_vector / height + x_axis = ( + np.array([1, 0, 0]) if abs(z_axis[1]) < 0.9 else np.array([0, 1, 0]) + ) + y_axis = np.cross(z_axis, x_axis) + x_axis = np.cross(y_axis, z_axis) + R = np.column_stack((x_axis, y_axis, z_axis)) + geom_type = mujoco.mjtGeom.mjGEOM_CYLINDER + + elif spawn_type == "sphere": + center, radius = region_points + half_size = np.array([radius, radius, radius]) + R = np.eye(3) + geom_type = mujoco.mjtGeom.mjGEOM_SPHERE + + else: + raise ValueError(f"Invalid spawn type: {spawn_type}") + + mujoco.mjv_initGeom( + current_geom, + type=geom_type, + size=half_size, + pos=center, + mat=R.reshape(9, 1), + rgba=np.array([0, 1, 0, 0.8]), + ) + current_geom.label = spawn.get("name") + + def visualize_bounding_box(self, obj_name="obj"): + """ + Draws a single site representing the full container spawn region as a 3D box. + """ + import numpy as np + import robocasa.utils.transform_utils as T + + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj_name]]) + obj_quat = T.convert_quat( + np.array(self.sim.data.body_xquat[self.obj_body_id[obj_name]]), to="xyzw" + ) + + bbox_points = self.objects[obj_name].get_bbox_points( + trans=obj_pos, rot=obj_quat + ) + + p0, px, py, pz = bbox_points[:4] + + v_x = px - p0 + v_y = py - p0 + v_z = pz - p0 + center = p0 + 0.5 * (v_x + v_y + v_z) + half_extent_x = np.linalg.norm(v_x) / 2.0 + half_extent_y = np.linalg.norm(v_y) / 2.0 + half_extent_z = np.linalg.norm(v_z) / 2.0 + half_size = np.array([half_extent_x, half_extent_y, half_extent_z]) + + x_axis = v_x / np.linalg.norm(v_x) + y_axis = v_y / np.linalg.norm(v_y) + z_axis = v_z / np.linalg.norm(v_z) + + R = np.column_stack((x_axis, y_axis, z_axis)) + + import mujoco + + self.viewer.update() + current_geom = None + for geom_idx in range(self.viewer.viewer.user_scn.ngeom): + if self.viewer.viewer.user_scn.geoms[geom_idx].label == obj_name: + current_geom = self.viewer.viewer.user_scn.geoms[geom_idx] + break + if current_geom is None: + self.viewer.viewer.user_scn.ngeom += 1 + current_geom = self.viewer.viewer.user_scn.geoms[ + self.viewer.viewer.user_scn.ngeom - 1 + ] + mujoco.mjv_initGeom( + current_geom, + type=mujoco.mjtGeom.mjGEOM_BOX, + size=half_size, + pos=center, + mat=R.reshape(9, 1), + rgba=np.array([0, 0, 1, 0.8]), + ) + current_geom.label = obj_name + + +class PnPOnionToBowl(TabletopPnP): + """ + Class encapsulating the atomic onion to bowl pick and place task. + A deliberately simple task used for testing. + + Onion is chosen as it's easy to grasp and place. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="onion", target_container="bowl", *args, **kwargs) + + +class PnPCanToBowl(TabletopPnP): + """ + Class encapsulating the atomic can to bowl pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(obj_groups="can", target_container="bowl", *args, **kwargs) + + +class PnPCupToPlate(TabletopPnP): + """ + Class encapsulating the atomic cup to plate pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="cup", + target_container="plate", + distractor_config={ + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.5), + }, + "objects": [ + { + "type": "tiered_basket", + "count": (0, 1), + }, + { + "type": "basket", + "count": 1, + }, + { + "type": "mug_tree", + "count": 1, + }, + ], + } + } + }, + *args, + **kwargs, + ) + + +class PnPAppleToPlate(TabletopPnP): + """ + Class encapsulating the atomic apple to plate pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="apple", + target_container="plate", + distractor_config={ + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.6), + }, + "objects": [ + { + "type": "bowl", + "count": 1, + }, + { + "type": "vegetable", + "count": (1, 2), + }, + { + "type": "mug", + "count": (0, 1), + }, + { + "type": "clock", + "count": 1, + }, + { + "type": "coffee_pod", + "count": 1, + }, + { + "type": "kettle_non_electric", + "count": 1, + }, + ], + } + } + }, + *args, + **kwargs, + ) + + +class PnPMilkToBasket(TabletopPnP): + """ + Class encapsulating the atomic milk to basket pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="milk", + target_container="basket", + distractor_config={ + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.5), + }, + "objects": [ + { + "type": "fruit", + "count": (2, 3), + }, + { + "type": "clock", + "count": (1, 2), + }, + { + "type": "cup", + "count": (1, 2), + }, + { + "type": "tiered_basket", + "count": 1, + }, + ], + } + } + }, + use_distractors=True, + *args, + **kwargs, + ) + + +class PnPKettleToPlate(TabletopPnP): + """ + Class encapsulating the atomic kettle to plate pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="kettle_non_electric", + target_container="plate", + distractor_config=None, + use_distractors=False, + *args, + **kwargs, + ) + + +class PnPFruitToPlacemat(TabletopPnP): + """ + Class encapsulating the atomic fruit to mat pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="fruit", + target_container="placemat", + target_container_size=(0.7, 0.7), + distractor_config={ + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.4), + }, + "objects": [ + { + "type": "basket", + "count": (1, 2), + } + ], + }, + "center": { + "placement": { + "pos": (0, 0.3), + "size": (0.8, 0.4), + }, + "objects": [ + { + "type": "vegetable", + "count": (2, 3), + }, + { + "type": "milk", + "count": 1, + }, + ], + }, + } + }, + *args, + **kwargs, + ) + + +class PnPCounterToPlate(TabletopPnP): + """ + Class encapsulating the atomic counter to plate pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(target_container="plate", *args, **kwargs) + + +class PnPCounterToBowl(TabletopPnP): + """ + Class encapsulating the atomic counter to bowl pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(target_container="bowl", *args, **kwargs) + + +class PnPCounterToCuttingBoard(TabletopPnP): + """ + Class encapsulating the atomic counter to cutting board pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(target_container="cutting_board", *args, **kwargs) + + +class PnPCounterToPot(TabletopPnP): + """ + Class encapsulating the atomic counter to pot pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + target_container="pot", target_container_size=(0.7, 0.7), *args, **kwargs + ) + + +class PnPCounterToPan(TabletopPnP): + """ + Class encapsulating the atomic counter to pan pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(target_container="pan", *args, **kwargs) + + +class PnPPlateToPlate(TabletopPnP): + """ + Class encapsulating the atomic plate to plate pick and place task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit", "dairy"], + *args, + **kwargs, + ): + super().__init__( + source_container="plate", + target_container="plate", + distractor_config={ + "regions": { + "center": { + "placement": { + "pos": (0, 0.5), + "size": (0.8, 0.8), + }, + "objects": [ + {"type": "bowl", "count": (1, 2)}, + {"type": "vegetable", "count": (1, 3)}, + {"type": "fruit", "count": (1, 3)}, + ], + }, + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.6), + }, + "objects": [ + {"type": "mug_tree", "count": 1}, + {"type": "basket", "count": (0, 2)}, + ], + }, + } + }, + use_distractors=True, + obj_groups=obj_groups, + *args, + **kwargs, + ) + + +class PnPMilkPlateToPlate(TabletopPnP): + """ + Class encapsulating the atomic milk plate to plate pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="milk", + distractor_config={ + "regions": { + "center": { + "placement": { + "pos": (0, 0), + "size": (0.6, 0.6), + }, + "objects": [ + {"type": "bowl", "count": (1, 2)}, + {"type": "vegetable", "count": (1, 2)}, + {"type": "fruit", "count": (1, 2)}, + ], + }, + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.5), + }, + "objects": [ + {"type": "mug_tree", "count": 1}, + {"type": "basket", "count": (0, 2)}, + ], + }, + } + }, + use_distractors=True, + source_container="plate", + target_container="plate", + *args, + **kwargs, + ) + + +class PnPVegetableBowlToPlate(TabletopPnP): + """ + Class encapsulating the atomic pick and place task where a vegetable is placed in a bowl and then transferred to an empty plate. + Other plates with + """ + + VALID_LAYOUTS = [0] + + def __init__(self, *args, **kwargs): + super().__init__( + target_container="plate", + source_container="bowl", + obj_groups="vegetable", + distractor_config={ + "regions": { + "center": { + "placement": { + "pos": (0, 0), + "size": (0.8, 0.8), + }, + "objects": [ + {"type": "fruit", "count": (1, 3)}, + {"type": "vegetable", "count": (1, 2)}, + {"type": "basket", "count": (0, 1)}, + {"type": "rubix_cube", "count": 1}, + {"type": "milk", "count": (0, 1)}, + {"type": "placemat", "count": (0, 1)}, + {"type": "bowl", "count": (1, 2)}, + ], + } + } + }, + use_distractors=True, + *args, + **kwargs, + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + veg_lang = self.get_obj_lang(obj_name="obj") + ep_meta[ + "lang" + ] = f"pick the {veg_lang} from the bowl and place it on the empty plate" + return ep_meta + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + cfgs.append( + dict( + name="distractor_milk_1", + obj_groups="milk", + placement=dict( + fixture=self.counter, + size=(0.5, 0.5), + pos=(1, 0.5), + try_to_place_in="plate", + ), + ) + ) + cfgs.append( + dict( + name="distractor_rubix_cube_1", + obj_groups="rubix_cube", + placement=dict( + fixture=self.counter, + size=(0.5, 0.5), + pos=(-1, 0.5), + try_to_place_in="plate", + ), + ) + ) + cfgs.append( + dict( + name="distractor_bowl_1", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + size=(0.5, 0.5), + pos=(0.5, 1), + optional=True, + ), + ) + ) + cfgs.append( + dict( + name="distractor_cup_1", + obj_groups="cup", + placement=dict( + fixture=self.counter, + size=(0.5, 0.5), + pos=(-0.5, 1), + optional=True, + ), + ) + ) + return cfgs + + +class PnPObjectsToShelf(TabletopPnP): + """ + Class encapsulating the atomic objects to shelf pick and place task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit", "dairy"], + *args, + **kwargs, + ): + super().__init__( + target_container="tiered_shelf", + target_container_size=(0.7, 0.4), + obj_groups=obj_groups, + distractor_config=None, + use_distractors=False, + *args, + **kwargs, + ) + + +class PnPObjectsToShelfLevel(TabletopPnP): + """ + Class encapsulating the atomic objects to specific shelf level pick and place task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit", "dairy"], + *args, + **kwargs, + ): + super().__init__( + target_container="tiered_shelf", + target_container_size=(0.7, 0.4), + obj_groups=obj_groups, + *args, + **kwargs, + ) + self.target_site_id = None + + def _get_obj_cfgs(self): + # place close to back of table instead of front of table + cfgs = super()._get_obj_cfgs() + cfgs[0]["placement"]["pos"] = ( + (0.9, 0.4) if self.handedness == "right" else (-0.9, 0.4) + ) + return cfgs + + def _load_model(self): + super()._load_model() + _, _, ref_obj = self.object_placements["container"] + self.target_site_id, _ = ref_obj.get_random_spawn( + self.rng, exclude_disabled=True + ) + + def _check_success(self): + obj_on_shelf = bool( + self.objects["container"].closest_spawn_id(self, self.objects["obj"]) + == self.target_site_id + ) + return obj_on_shelf and super()._check_success() + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + source_container_lang = "counter" + target_container_lang = self.get_obj_lang(obj_name="container") + ep_meta["lang"] = ( + f"pick the {obj_lang} from the {source_container_lang} and place it " + f"on the level #{self.target_site_id + 1} of the the {target_container_lang}" + ) + return ep_meta + + +class PnPObjectsShelfToCounter(TabletopPnP): + """ + Class encapsulating the atomic objects from shelf to counter task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit"], + *args, + **kwargs, + ): + super().__init__( + source_container="tiered_shelf", + source_container_size=(0.7, 0.4), + obj_groups=obj_groups, + *args, + **kwargs, + ) + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + cfgs[0]["placement"]["pos"] = ( + (0.9, 0.4) if self.handedness == "right" else (-0.9, 0.4) + ) + for c in cfgs: + if c["name"] == "obj": + c["placement"]["site_id"] = -1 + return cfgs + + +class PnPObjectsShelfLevelToLevel(TabletopPnP): + """ + Class encapsulating the atomic objects from one shelf level to another level task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit"], + *args, + **kwargs, + ): + super().__init__( + source_container="tiered_shelf", + source_container_size=(0.7, 0.4), + obj_groups=obj_groups, + *args, + **kwargs, + ) + self.target_site_id = None + + def _get_obj_cfgs(self): + # put shelf on back of table instead of front of table + cfgs = super()._get_obj_cfgs() + cfgs[0]["placement"]["pos"] = ( + (0.9, 0.4) if self.handedness == "right" else (-0.9, 0.4) + ) + return cfgs + + def _load_model(self): + super()._load_model() + _, _, ref_obj = self.object_placements["obj_container"] + self.target_site_id, _ = ref_obj.get_random_spawn( + self.rng, exclude_disabled=True + ) + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + for c in cfgs: + if c["name"] == "obj": + c["placement"]["site_id"] = -1 + return cfgs + + def _check_success(self): + gripper_container_far = OU.gripper_obj_far(self, obj_name="obj_container") + gripper_obj_far = OU.gripper_obj_far(self, obj_name="obj") + obj_in_container = OU.check_obj_in_receptacle(self, "obj", "obj_container") + obj_on_shelf = bool( + self.objects["obj_container"].closest_spawn_id(self, self.objects["obj"]) + == self.target_site_id + ) + obj_on_counter = OU.check_obj_fixture_contact(self, "obj", self.counter) + return ( + gripper_container_far + and gripper_obj_far + and obj_in_container + and obj_on_shelf + and not obj_on_counter + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + source_container_lang = self.get_obj_lang(obj_name="obj_container") + ep_meta["lang"] = ( + f"pick the {obj_lang} from the {source_container_lang} and place it " + f"on the level #{self.target_site_id + 1} of the the {source_container_lang}" + ) + return ep_meta + + +class PnPObjectsToTieredBasket(TabletopPnP): + """ + Class encapsulating the atomic objects to tiered basket pick and place task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit", "dairy"], + *args, + **kwargs, + ): + super().__init__( + target_container="tiered_basket", + obj_groups=obj_groups, + *args, + **kwargs, + ) + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + shelf_pos, shelf_rot = _PnpTieredBasketUtils.get_shelf_pose(self) + for c in cfgs: + if c["name"] == "container": + c["placement"]["pos"] = shelf_pos + c["placement"]["rotation"] = shelf_rot + return cfgs + + +class PnPObjectsToTieredBasketLevel(TabletopPnP): + """ + Class encapsulating the atomic objects to specific tiered basket level pick and place task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit", "dairy"], + *args, + **kwargs, + ): + super().__init__( + target_container="tiered_basket", + target_container_size=(0.7, 0.5), + obj_groups=obj_groups, + *args, + **kwargs, + ) + self.target_site_id = None + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + shelf_pos, shelf_rot = _PnpTieredBasketUtils.get_shelf_pose(self) + for c in cfgs: + if c["name"] == "container": + c["placement"]["pos"] = shelf_pos + c["placement"]["rotation"] = shelf_rot + return cfgs + + def _load_model(self): + super()._load_model() + _, _, ref_obj = self.object_placements["container"] + self.target_site_id, _ = ref_obj.get_random_spawn( + self.rng, exclude_disabled=True + ) + + def _check_success(self): + obj_on_shelf = bool( + self.objects["container"].closest_spawn_id(self, self.objects["obj"]) + == self.target_site_id + ) + return obj_on_shelf and super()._check_success() + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + source_container_lang = "counter" + target_container_lang = self.get_obj_lang(obj_name="container") + ep_meta["lang"] = ( + f"pick the {obj_lang} from the {source_container_lang} and place it " + f"on the level #{self.target_site_id + 1} of the the {target_container_lang}" + ) + return ep_meta + + +class PnPObjectsTieredBasketToCounter(TabletopPnP): + """ + Class encapsulating the atomic objects from tiered basket to counter task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit"], + *args, + **kwargs, + ): + super().__init__( + source_container="tiered_basket", + source_container_size=(0.7, 0.5), + obj_groups=obj_groups, + *args, + **kwargs, + ) + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + shelf_pos, shelf_rot = _PnpTieredBasketUtils.get_shelf_pose(self) + for c in cfgs: + if c["name"] == "obj": + c["placement"]["site_id"] = -1 + c["placement"]["pos"] = shelf_pos + c["placement"]["rotation"] = shelf_rot + return cfgs + + +class PnPObjectsTieredBasketLevelToLevel(TabletopPnP): + """ + Class encapsulating the atomic objects from one tiered basket level to another level task. + """ + + def __init__( + self, + obj_groups=["vegetable", "fruit"], + *args, + **kwargs, + ): + super().__init__( + source_container="tiered_basket", + source_container_size=(0.7, 0.5), + obj_groups=obj_groups, + *args, + **kwargs, + ) + self.target_site_id = None + + def _load_model(self): + super()._load_model() + _, _, ref_obj = self.object_placements["obj_container"] + self.target_site_id, _ = ref_obj.get_random_spawn( + self.rng, exclude_disabled=True + ) + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + shelf_pos, shelf_rot = _PnpTieredBasketUtils.get_shelf_pose(self) + for c in cfgs: + if c["name"] == "obj": + c["placement"]["site_id"] = -1 + c["placement"]["pos"] = shelf_pos + c["placement"]["rotation"] = shelf_rot + return cfgs + + def _check_success(self): + gripper_container_far = OU.gripper_obj_far(self, obj_name="obj_container") + gripper_obj_far = OU.gripper_obj_far(self, obj_name="obj") + obj_in_container = OU.check_obj_in_receptacle(self, "obj", "obj_container") + obj_on_shelf = bool( + self.objects["obj_container"].closest_spawn_id(self, self.objects["obj"]) + == self.target_site_id + ) + obj_on_counter = OU.check_obj_fixture_contact(self, "obj", self.counter) + return ( + gripper_container_far + and gripper_obj_far + and obj_in_container + and obj_on_shelf + and not obj_on_counter + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + source_container_lang = self.get_obj_lang(obj_name="obj_container") + ep_meta["lang"] = ( + f"pick the {obj_lang} from the {source_container_lang} and place it " + f"on the level #{self.target_site_id + 1} of the the {source_container_lang}" + ) + return ep_meta + + +class _PnpTieredBasketUtils: + """Utils for tired basket tasks.""" + + @staticmethod + def get_shelf_pose(task: TabletopPnP): + handedness = ( + task.handedness if task.handedness else task.rng.choice(["left", "right"]) + ) + shelf_pos = (0.75, 0.3) if handedness == "right" else (-0.75, 0.3) + shelf_rotation = ( + (-5 * np.pi / 8, -7 * np.pi / 8) + if handedness == "right" + else (-3 * np.pi / 8, -1 * np.pi / 8) + ) + return shelf_pos, shelf_rotation + + +class PnPRubixCubeBasketToCounter(TabletopPnP): + """ + Class encapsulating the atomic basket to counter pick and place task. + AKA taking objects out of the basket + """ + + def __init__(self, *args, **kwargs): + super().__init__( + source_container="basket", + obj_groups="rubix_cube", + distractor_config={ + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.5), + }, + "objects": [ + { + "type": "plate", + "count": 1, + }, + { + "type": "tiered_basket", + "count": (0, 1), + }, + { + "type": "tiered_shelf", + "count": (0, 1), + }, + ], + } + } + }, + use_distractors=True, + *args, + **kwargs, + ) + + def get_object(self): + objects = dict() + objects["obj"] = dict( + obj_name=self.objects["obj"].root_body, obj_type="body", obj_joint=None + ) + + objects["obj_container"] = dict( + obj_name=self.objects["obj_container"].root_body, + obj_type="body", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["grasp_object"] = int( + self._check_grasp( + gripper=self.robots[0].gripper["right"], + object_geoms=self.objects["obj"], + ) + ) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec_0.subtask_1 = dict( + object_ref="obj", + subtask_term_signal="grasp_object", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_0.subtask_2 = dict( + object_ref="obj_container", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + +class PnPCupToPlateNoDistractors(TabletopPnP): + """ + Class encapsulating the atomic cup to plate pick and place task without distractors. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups="cup", + target_container="plate", + distractor_config=None, + use_distractors=False, + source_container_size=(0.5, 0.3), + target_container_size=(0.5, 0.3), + *args, + **kwargs, + ) + + +class PnPCupToDishRackUpperLevel(TabletopPnP): + """ + Class encapsulating the atomic cup to dish rack pick and place task. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups=["cup", "milk"], + target_container=[ + "objects/sketchfab/dish_rack/dish_rack_0/model.xml", + "objects/sketchfab/dish_rack/dish_rack_4/model.xml", + ], + distractor_config=None, + use_distractors=False, + source_container_size=(0.5, 0.3), + target_container_size=(0.7, 0.5), + *args, + **kwargs, + ) + self.target_site_id = 1 + + def _get_obj_cfgs(self): + # place close to back of table instead of front of table + cfgs = super()._get_obj_cfgs() + # container + cfgs[0]["placement"] = dict( + fixture=self.counter, + size=(0.9, 0.4), + pos=(1.0, -1.0), + rotation=(-np.pi, np.pi), + ) + # object + cfgs[1]["placement"] = dict( + fixture=self.counter, + size=(0.6, 0.2), + pos=(1.0, -1.0), + ) + return cfgs + + def _load_model(self): + super()._load_model() + _, _, ref_obj = self.object_placements["container"] + + # robot0_cotrainview=dict( + # pos=[0.22, 0.05, 0.0425], + # quat=[0.67397475,0.21391128, -0.21391128, -0.67397475], + # camera_attribs=dict(fovy="90"), + # parent_body="robot0_head_pitch", + # ), + camera = find_elements( + root=self.model.worldbody, + tags="camera", + attribs={"name": "robot0_cotrainview"}, + ) + if camera is None: + camera = ET.Element("camera") + camera.set("mode", "fixed") + camera.set("name", "robot0_cotrainview") + camera.set("pos", "0.22 0.05 0.0425") + camera.set("xyaxes", "-0.01 -1. 0. 0.85 0. 0.5") + camera.set("fovy", "90") + cam_root = find_elements( + root=self.model.worldbody, + tags="body", + attribs={"name": "robot0_head_pitch"}, + ) + cam_root.append(camera) + + def compute_robot_base_placement_pose(self, offset=None): + robot_base_pos, robot_base_ori = super().compute_robot_base_placement_pose( + offset + ) + # Randomization for the table + robot_base_pos += np.array([0.05, 0.05, 0]) + return robot_base_pos, robot_base_ori + + def _check_success(self): + obj_on_shelf = OU.check_obj_in_site( + self, "obj", "container", self.target_site_id + ) + return obj_on_shelf and super()._check_success() + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + target_container_lang = self.get_obj_lang(obj_name="container") + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the {target_container_lang} and place it on the level #{self.target_site_id + 1} of the the {target_container_lang}" + return ep_meta + + +class PnPBreadBasketToBowl(TabletopPnP): + """ + Class encapsulating the atomic pick and place task where a piece of bread in a basket is then moved to a bowl. + """ + + def __init__(self, *args, **kwargs): + kwargs["style_ids"] = [4] + super().__init__( + obj_groups=[ + "objects/objaverse/bread/bread_1/model.xml", + "objects/objaverse/bread/bread_17/model.xml", + "objects/objaverse/bread/bread_20/model.xml", + "objects/objaverse/bread/bread_21/model.xml", + ], + source_container="basket", + target_container="bowl", + distractor_config=None, + use_distractors=False, + source_container_size=(0.5, 0.1), + target_container_size=(0.5, 0.1), + *args, + **kwargs, + ) + + def _get_obj_cfgs(self): + cfgs = [] + + if self.target_container: + cfgs.append( + dict( + name="container", + obj_groups=self.target_container, + placement=dict( + fixture=self.counter, + size=self.target_container_size, + inner_margin=0.1, + ensure_object_boundary_in_range=False, + pos=(0.5, -0.9) if self.handedness == "right" else (-0.5, -0.9), + ), + ) + ) + + # Randomize handedness per invoke rather than storing it + handedness = ( + self.handedness if self.handedness else self.rng.choice(["left", "right"]) + ) + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + placement=dict( + fixture=self.counter, + size=( + self.source_container_size + if self.source_container + else (0.3, 0.3) + ), + ensure_object_boundary_in_range=False, + pos=(0.6, -0.9) if handedness == "right" else (-0.6, -0.9), + try_to_place_in=self.source_container, + ), + ) + ) + return cfgs + + +class PnPPouring(TabletopPnP): + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups=["primitive"], + source_container="cup", + target_container="bowl", + distractor_config=None, + use_distractors=False, + *args, + **kwargs, + ) + + def _get_obj_cfgs(self): + cfgs = [] + + if self.target_container: + cfgs.append( + dict( + name="container", + obj_groups=self.target_container, + placement=dict( + fixture=self.counter, + size=(0.8, 0.4), + pos=(0.2, -0.8), + ), + ) + ) + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.5, 0.2), + pos=(0.4, -0.9), + try_to_place_in=self.source_container, + ), + ) + ) + return cfgs + + def _load_model(self): + super()._load_model() + camera = find_elements( + root=self.model.worldbody, + tags="camera", + attribs={"name": "robot0_cotrainview"}, + ) + if camera is None: + camera = ET.Element("camera") + camera.set("mode", "fixed") + camera.set("name", "robot0_cotrainview") + camera.set("pos", "0.22 0.05 0.0425") + camera.set("xyaxes", "-0.01 -1. 0. 0.85 0. 0.5") + camera.set("fovy", "90") + cam_root = find_elements( + root=self.model.worldbody, + tags="body", + attribs={"name": "robot0_head_pitch"}, + ) + cam_root.append(camera) + + def compute_robot_base_placement_pose(self, offset=None): + robot_base_pos, robot_base_ori = super().compute_robot_base_placement_pose( + offset + ) + # Randomization for the table + robot_base_pos -= self.rng.uniform(0, 0.05, 3) + return robot_base_pos, robot_base_ori + + def _create_objects(self): + """ + Creates and places objects in the tabletop environment. + Helper function called by _load_model() + """ + # add objects + self.objects = {} + self.object_cfgs = self._get_obj_cfgs() + num_objects = len(self.object_cfgs) + exclude_cat = [] + self.object_cfgs.extend(self._get_distractor_obj_cfgs()) + addl_obj_cfgs = [] + for obj_num, cfg in enumerate(self.object_cfgs): + cfg["type"] = "object" + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + if obj_num >= num_objects: + # objects part of distractors + cfg["exclude_cat"] = exclude_cat + + if cfg["name"] == "obj": + model = BallObject( + name="ball_obj", + size=[0.02], + density=50.0, + friction=None, + rgba=self.rng.uniform(0, 1, size=3).tolist() + [1.0], + ) + cfg["info"] = { + "groups_containing_sampled_obj": [ + "all", + "peach", + "fruit", + "food", + "in_container", + ], + "groups": ["ball"], + "cat": "primitive", + } + self.objects["obj"] = model + self.model.merge_objects([model]) + else: + model, info = self._create_obj(cfg) + if obj_num < num_objects: + # objects part of the task + exclude_cat.append(info["cat"]) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + try_to_place_in = cfg["placement"].get("try_to_place_in", None) + + # place object in a container and add container as an object to the scene + if try_to_place_in and ( + "in_container" in cfg["info"]["groups_containing_sampled_obj"] + ): + container_cfg = { + "name": cfg["name"] + "_container", + "obj_groups": cfg["placement"].get("try_to_place_in"), + "placement": deepcopy(cfg["placement"]), + "type": "object", + } + + container_kwargs = cfg["placement"].get("container_kwargs", None) + if container_kwargs is not None: + for k, v in container_kwargs.items(): + container_cfg[k] = v + + # add in the new object to the model + addl_obj_cfgs.append(container_cfg) + model, info = self._create_obj(container_cfg) + container_cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + reference = container_cfg["name"] + site_id = cfg["placement"].get("site_id", None) + if site_id is not None: + reference = (reference, site_id) + + # modify object config to lie inside of container + cfg["placement"] = dict( + size=(0.01, 0.01), + ensure_object_boundary_in_range=False, + sample_args=dict( + reference=reference, + ), + ) + + # place the additional objects (usually containers) in first + self.object_cfgs = addl_obj_cfgs + self.object_cfgs + + # # remove objects that didn't get created + # self.object_cfgs = [cfg for cfg in self.object_cfgs if "model" in cfg] + + def get_object(self): + objects = dict() + objects["obj"] = dict( + obj_name=self.objects["obj"].root_body, obj_type="BODY", obj_joint=None + ) + + objects["obj_container"] = dict( + obj_name=self.objects["obj_container"].root_body, + obj_type="body", + obj_joint=None, + ) + + objects["container"] = dict( + obj_name=self.objects["container"].root_body, + obj_type="body", + obj_joint=None, + ) + return objects + + def get_subtask_term_signals(self): + signals = dict() + signals["grasp_obj_container"] = int( + self._check_grasp( + gripper=self.robots[0].gripper["right"], + object_geoms=self.objects["obj_container"], + ) + ) + return signals + + @staticmethod + def task_config(): + task = DexMGConfigHelper.AttrDict() + task.task_spec_0.subtask_1 = dict( + object_ref="obj_container", + subtask_term_signal="grasp_obj_container", + subtask_term_offset_range=(5, 10), + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_0.subtask_2 = dict( + object_ref="container", + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + task.task_spec_1.subtask_1 = dict( + object_ref=None, + subtask_term_signal=None, + subtask_term_offset_range=None, + selection_strategy="random", + selection_strategy_kwargs=None, + action_noise=0.05, + num_interpolation_steps=5, + num_fixed_steps=0, + apply_noise_during_interpolation=True, + ) + return task.to_dict() + + +class PnPFruitToPlate(TabletopPnP): + def __init__(self, *args, **kwargs): + super().__init__( + obj_groups=["vegetable", "fruit"], + target_container="plate", + source_container_size=(0.5, 0.3), + target_container_size=(0.5, 0.3), + distractor_config={ + "regions": { + "back_edge": { + "placement": { + "pos": (0, 1), + "size": (1.2, 0.4), + }, + "objects": [ + { + "type": "basket", + "count": (1, 2), + } + ], + }, + "center": { + "placement": { + "pos": (0.5, -0.9), + "size": (0.3, 0.3), + }, + "objects": [ + { + "type": ["vegetable", "fruit"], + "count": (2, 4), + }, + { + "type": "milk", + "count": 1, + }, + ], + }, + } + }, + *args, + **kwargs, + ) + + def _get_obj_cfgs(self): + cfgs = super()._get_obj_cfgs() + cfgs[0]["placement"]["size"] = (0.7, 0.7) + return cfgs + + def _create_objects(self): + """ + Creates and places objects in the tabletop environment. + Helper function called by _load_model() + """ + # add objects + self.objects = {} + exclude_cat = [] + if "object_cfgs" in self._ep_meta: + self.object_cfgs = self._ep_meta["object_cfgs"] + for obj_num, cfg in enumerate(self.object_cfgs): + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + model, info = self._create_obj(cfg) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + else: + self.object_cfgs = self._get_obj_cfgs() + unique_obj_num = len(self.object_cfgs) + self.object_cfgs.extend(self._get_distractor_obj_cfgs()) + addl_obj_cfgs = [] + for obj_num, cfg in enumerate(self.object_cfgs): + cfg["type"] = "object" + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + cfg["exclude_cat"] = exclude_cat + model, info = self._create_obj(cfg) + cfg["info"] = info + if obj_num < unique_obj_num: + exclude_cat.append(info["cat"]) + self.objects[model.name] = model + self.model.merge_objects([model]) + + try_to_place_in = cfg["placement"].get("try_to_place_in", None) + + # place object in a container and add container as an object to the scene + if try_to_place_in and ( + "in_container" in cfg["info"]["groups_containing_sampled_obj"] + ): + container_cfg = { + "name": cfg["name"] + "_container", + "obj_groups": cfg["placement"].get("try_to_place_in"), + "placement": deepcopy(cfg["placement"]), + "type": "object", + } + + container_kwargs = cfg["placement"].get("container_kwargs", None) + if container_kwargs is not None: + for k, v in container_kwargs.items(): + container_cfg[k] = v + + # add in the new object to the model + addl_obj_cfgs.append(container_cfg) + model, info = self._create_obj(container_cfg) + container_cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + # modify object config to lie inside of container + cfg["placement"] = dict( + size=(0.01, 0.01), + ensure_object_boundary_in_range=False, + sample_args=dict( + reference=container_cfg["name"], + ), + ) + + # place the additional objects (usually containers) in first + self.object_cfgs = addl_obj_cfgs + self.object_cfgs + + # # remove objects that didn't get created + # self.object_cfgs = [cfg for cfg in self.object_cfgs if "model" in cfg] + + +class PnPFruitToPlateSplitA(PnPFruitToPlate): + def __init__(self, *args, **kwargs): + kwargs["obj_instance_split"] = "A" + super().__init__(*args, **kwargs) + + +class PnPFruitToPlateSplitB(PnPFruitToPlate): + def __init__(self, *args, **kwargs): + kwargs["obj_instance_split"] = "B" + super().__init__(*args, **kwargs) + + +class PnPCylindricalToPlate(TabletopPnP): + """ + Class for picking and placing cylindrical objects (bottled_drink, bottled_water, boxed_drink, can, milk) onto a plate. + """ + + def __init__(self, *args, **kwargs): + super().__init__( + target_container="plate", + obj_groups=["bottled_drink", "bottled_water", "boxed_drink", "can", "milk"], + distractor_config=None, + use_distractors=False, + source_container_size=(0.5, 0.3), + target_container_size=(0.5, 0.3), + *args, + **kwargs, + ) + + +COTRAIN_REAL_MATCHED_ROBOT_INITIAL_POSE = [ + -0.22963779, + -0.38363408, + 0.14360377, + -1.5289252, + -0.2897802, + -0.07134621, + -0.04550289, + -0.10933163, + 0.43292055, + -0.15983289, + -1.48233023, + 0.2359135, + 0.26184522, + 0.00830735, +] + + +class PnPMilkPlateToPlateCotrain(PnPMilkPlateToPlate): + def __init__(self, *args, **kwargs): + kwargs.update( + { + "layout_ids": [3], + "source_container_size": (0.5, 0.3), + "target_container_size": (0.5, 0.3), + } + ) + super().__init__(*args, **kwargs) + + def _load_model(self): + super()._load_model() + table = find_elements( + root=self.model.worldbody, + tags="body", + attribs={"name": "table_main_group_main"}, + ) + if "euler" in table.attrib: + del table.attrib["euler"] + table.set("xyaxes", "1 0.12 0 0 1 0") + + # robot0_cotrainview=dict( + # pos=[0.22, 0.05, 0.0425], + # quat=[0.67397475,0.21391128, -0.21391128, -0.67397475], + # camera_attribs=dict(fovy="90"), + # parent_body="robot0_head_pitch", + # ), + camera = find_elements( + root=self.model.worldbody, + tags="camera", + attribs={"name": "robot0_cotrainview"}, + ) + if camera is None: + camera = ET.Element("camera") + camera.set("mode", "fixed") + camera.set("name", "robot0_cotrainview") + camera.set("pos", "0.22 0.05 0.0425") + camera.set("xyaxes", "-0.01 -1. 0. 0.85 0. 0.5") + camera.set("fovy", "90") + cam_root = find_elements( + root=self.model.worldbody, + tags="body", + attribs={"name": "robot0_head_pitch"}, + ) + cam_root.append(camera) + + # Randomization for the camera + randomize_range = { + "xyaxes": (-0.02, 0.02), + "fov": (-5, 5), + "pos": (-0.02, 0.02), + } + angle_type = "xyaxes" + camera_orientation = string_to_array(camera.get(angle_type)) + camera_fov = string_to_array(camera.get("fovy")) + camera_pos = string_to_array(camera.get("pos")) + camera_orientation += self.rng.uniform( + randomize_range["xyaxes"][0], randomize_range["xyaxes"][1], 6 + ) + camera_fov += self.rng.uniform( + randomize_range["fov"][0], randomize_range["fov"][1], 1 + ) + camera_pos += self.rng.uniform( + randomize_range["pos"][0], randomize_range["pos"][1], 3 + ) + + camera.set(angle_type, array_to_string(camera_orientation)) + camera.set("fovy", array_to_string(camera_fov)) + camera.set("pos", array_to_string(camera_pos)) + + def compute_robot_base_placement_pose(self, offset=None): + robot_base_pos, robot_base_ori = super().compute_robot_base_placement_pose( + offset + ) + # Randomization for the table + robot_base_pos += np.array([0.05, 0.05, 0]) + robot_base_pos -= self.rng.uniform(0, 0.05, 3) + return robot_base_pos, robot_base_ori + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + # Randomization for joints + joint_rand_strength = 0.2 + rand_joint_names = [] + for name in self.sim.model.joint_names: + if "robot0_" in name: + rand_joint_names.append(name) + joint_ids = [self.sim.model.joint_name2id(name) for name in rand_joint_names] + joint_pos = np.array(COTRAIN_REAL_MATCHED_ROBOT_INITIAL_POSE) + new_joint_pos = np.array(joint_pos) + self.rng.uniform( + -joint_rand_strength, joint_rand_strength, len(joint_pos) + ) + self.sim.data.qpos[joint_ids] = new_joint_pos + self.sim.forward() + + +class PnPAppleToPlateCotrain(PnPAppleToPlate): + def __init__(self, *args, **kwargs): + kwargs.update( + { + "layout_ids": [3], + "source_container_size": (0.5, 0.3), + "target_container_size": (0.5, 0.3), + } + ) + super().__init__(*args, **kwargs) + + def _load_model(self): + super()._load_model() + table = find_elements( + root=self.model.worldbody, + tags="body", + attribs={"name": "table_main_group_main"}, + ) + if "euler" in table.attrib: + del table.attrib["euler"] + table.set("xyaxes", "1 0.12 0 0 1 0") + + # robot0_cotrainview=dict( + # pos=[0.22, 0.05, 0.0425], + # quat=[0.67397475,0.21391128, -0.21391128, -0.67397475], + # camera_attribs=dict(fovy="90"), + # parent_body="robot0_head_pitch", + # ), + camera = find_elements( + root=self.model.worldbody, + tags="camera", + attribs={"name": "robot0_cotrainview"}, + ) + if camera is None: + camera = ET.Element("camera") + camera.set("mode", "fixed") + camera.set("name", "robot0_cotrainview") + camera.set("pos", "0.22 0.05 0.0425") + camera.set("xyaxes", "-0.01 -1. 0. 0.85 0. 0.5") + camera.set("fovy", "90") + cam_root = find_elements( + root=self.model.worldbody, + tags="body", + attribs={"name": "robot0_head_pitch"}, + ) + cam_root.append(camera) + + # Randomization for the camera + randomize_range = { + "xyaxes": (-0.02, 0.02), + "fov": (-5, 5), + "pos": (-0.02, 0.02), + } + angle_type = "xyaxes" + camera_orientation = string_to_array(camera.get(angle_type)) + camera_fov = string_to_array(camera.get("fovy")) + camera_pos = string_to_array(camera.get("pos")) + camera_orientation += self.rng.uniform( + randomize_range["xyaxes"][0], randomize_range["xyaxes"][1], 6 + ) + camera_fov += self.rng.uniform( + randomize_range["fov"][0], randomize_range["fov"][1], 1 + ) + camera_pos += self.rng.uniform( + randomize_range["pos"][0], randomize_range["pos"][1], 3 + ) + + camera.set(angle_type, array_to_string(camera_orientation)) + camera.set("fovy", array_to_string(camera_fov)) + camera.set("pos", array_to_string(camera_pos)) + + def compute_robot_base_placement_pose(self, offset=None): + robot_base_pos, robot_base_ori = super().compute_robot_base_placement_pose( + offset + ) + # Randomization for the table + robot_base_pos += np.array([0.05, 0.05, 0]) + robot_base_pos -= self.rng.uniform(0, 0.05, 3) + return robot_base_pos, robot_base_ori + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + # Randomization for joints + joint_rand_strength = 0.2 + rand_joint_names = [] + for name in self.sim.model.joint_names: + if "robot0_" in name: + rand_joint_names.append(name) + joint_ids = [self.sim.model.joint_name2id(name) for name in rand_joint_names] + joint_pos = np.array(COTRAIN_REAL_MATCHED_ROBOT_INITIAL_POSE) + new_joint_pos = np.array(joint_pos) + self.rng.uniform( + -joint_rand_strength, joint_rand_strength, len(joint_pos) + ) + self.sim.data.qpos[joint_ids] = new_joint_pos + self.sim.forward() diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/dark_wood/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/dark_wood/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..38b7d06789938b42a43096ed07e2d178f2098df4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/dark_wood/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/fuji/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/fuji/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..904fd35631787b7571bc262e4a771d5958635d37 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/fuji/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/knife_block_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/knife_block_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..90c144a0f681d214c0b3b8fa39c993491a6de971 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/knife_block_1/model.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..eb289a5a57000b3fd7b94ab1a6228ed8f6ff0ab5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood/model.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e41317c61ea5d3f4aef0ff947416ee1b89f8671 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_2/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a945c09920b3a962bbae3c80d2a9953f900ce9e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_3/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/light_switches/white_wide_switch/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/light_switches/white_wide_switch/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f5f40bce6986324312b3faf68443a11c41fa1d6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/light_switches/white_wide_switch/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/outlets/simple_white/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/outlets/simple_white/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..9cad808552da712ad8cc34c515c70d5714a383de --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/outlets/simple_white/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..fc9c3d988d56ef00b092fcb033631075bf505e1b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_1/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..fcc4263fc94fd1ffcce3e2604e8177ac05c19d2b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_2/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e1652093ac13e542e3b8f4b14b4ac11d32f4237 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_3/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_4/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_4/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..1b7f9635e7769a7ab2c254d0724beaa0b4a6113d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_4/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_5/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_5/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..e548afbb9224330ba57e092dc74e0ef1fc3d7d5e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_5/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/aloe/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/aloe/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f59f52be2bef33f18866248c54b4e787968748b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/aloe/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/dodekaeder/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/dodekaeder/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..534bcfd50b33beec85447eacb536f59a146e8f90 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/dodekaeder/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/senecio/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/senecio/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee974108af4dc75e7720ef7770ab09064ac86b7e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/senecio/model.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/spikey_in_white_pot/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/spikey_in_white_pot/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..54d44e27bbff673cdcd943bcaa237af3ae003116 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/plants/spikey_in_white_pot/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/rattan_stool/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/rattan_stool/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..85b536d3178ba0195a07ad3716684b95f6dbb4d4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/rattan_stool/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..b68924ae241a0584513172f9655cf21656a95f68 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_1/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..427b2eef8ba9c2c9bd68b0281c7898c20ff16661 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_2/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..be2125837690a3f983cda4cd47b7d2c971091dde --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_1_3/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d653739135ae2e3a48fbf386b20ace5eeaba60b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/stools/stool_2/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..8038e0ca91e148d4b227461d5c63d68be0e8eded --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_1/model.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..238b19bf4fb3755ff02c19e0934ac8514c288d1c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_2/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ce47311dabd184949619d1286e23dc50c65e428 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_3/model.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/black_plastic/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/black_plastic/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf3195d941d0f5ce3be02d6c7561a6129e5d420f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/black_plastic/model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b3441d6dce3260a234f6f321893848a7c915dcf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..448623589304795b25c71139edf30f082f691960 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg/model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..920bc56d319627c2f3edbfcfe136ed0bcfde01ed --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg_2/model.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/rack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/rack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..605dfc8cbe678b7529bde6486d21d31d707f9e55 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/accessories/utensil_racks/rack_1/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_hinge.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_hinge.xml new file mode 100644 index 0000000000000000000000000000000000000000..52f11f1c59c8feb65af025ac965ec8280830877a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_hinge.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_housing.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_housing.xml new file mode 100644 index 0000000000000000000000000000000000000000..b848292cf30dc79a9e7df833254c091dd4f564a6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_housing.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_open.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_open.xml new file mode 100644 index 0000000000000000000000000000000000000000..eef1097bc99d341b80847f2f5bc355bdf63930f1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_open.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/divided_window.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/divided_window.xml new file mode 100644 index 0000000000000000000000000000000000000000..e88908536f21c8498175b31bb88d5d1ca827ae7a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/divided_window.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/full_window.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/full_window.xml new file mode 100644 index 0000000000000000000000000000000000000000..784520ef6025c441258df1333f2231e647639ed3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/full_window.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/raised.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/raised.xml new file mode 100644 index 0000000000000000000000000000000000000000..e407488c09a1dfedb37248f9b31351dd8f1d5500 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/raised.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shaker.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shaker.xml new file mode 100644 index 0000000000000000000000000000000000000000..73cd4428ee4ca57ba172c4ac66fb64f16b92b31d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shaker.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shelf.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shelf.xml new file mode 100644 index 0000000000000000000000000000000000000000..3649625e26d30254ab62bec60f1d1e071bb65bda --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shelf.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/slab.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/slab.xml new file mode 100644 index 0000000000000000000000000000000000000000..696e08782235be3d726985b3f77a58a834c5951f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_panels/slab.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_single.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_single.xml new file mode 100644 index 0000000000000000000000000000000000000000..e4fb19ecd8b5f83367aa3b062ef50a85a2040bb6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/cabinet_single.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/drawer.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/drawer.xml new file mode 100644 index 0000000000000000000000000000000000000000..047fdb356c2cb48da051e4d571b17de88000fa6e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/drawer.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/panel.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/panel.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e41172af77ac29026df162c346ca61f7abb4fa1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/cabinets/panel.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..bbec45fa2e9e9fe9bb17b7ccade56cf579977498 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso/model.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..59713e44a441acff05a4d5bccdce115580d8f14d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso_2/model.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/nespresso/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/nespresso/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c663a430487d83b6b4bd3dd6135f0f22ed6c92b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/nespresso/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/white/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/white/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..85b2719b90890f205969c098a2e77a7e02229026 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/coffee_machines/white/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/counters/counter/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/counters/counter/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e98c8d4bb011a687a05ec96cedf7f424243b579 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/counters/counter/model.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/counters/counter_with_opening/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/counters/counter_with_opening/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..85d400630a95209f10e7c837ceddabc3c1ae16e3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/counters/counter_with_opening/model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/basic_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/basic_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..4aace8e6bc482a1fa30e93c9fe0e2a3200475af9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/basic_stainless/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c26b8d0175c90365fdb7853307d142a1053e2476 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/pack_1/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..49b90a3c1dfe173b70eca8cb60d5879b5abb343e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/dishwashers/pack_2/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/cabinet.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/cabinet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a0f4932a1a1b6689e2e29040734ef6cc8c21b8f6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/cabinet.yaml @@ -0,0 +1,90 @@ +default: + texture: textures/wood/wood_grain_1.png + handle_type: bar + handle_config: + texture: textures/metals/bright_metal.png + + +#### panel textures #### +white: + texture: textures/flat/white.png +black: + texture: textures/flat/black.png +dark_gray: + texture: textures/flat/dark_gray.png +gray: + texture: textures/flat/gray.png +light_gray: + texture: textures/flat/light_gray.png +lighter_gray: + texture: textures/flat/lighter_gray.png +blue_gray: + texture: textures/flat/blue_gray.png +dark_blue: + texture: textures/flat/dark_blue.png +light_green: + texture: textures/flat/light_green.png +light_blue: + texture: textures/flat/light_blue.png +warm_white: + texture: textures/flat/warm_white.png +dark_wood_parquet: + texture: textures/wood/dark_wood_parquet.png +light_wood_parquet: + texture: textures/wood/light_wood_parquet.png +warm_wood_parquet: + texture: textures/wood/warm_wood_parquet.png +warm_wood_grain: + texture: textures/wood/warm_wood_grain_2.png +walnut_wood_grain: + texture: textures/wood/walnut_wood_grain.png +gray_wood_grain: + texture: textures/wood/gray_wood_grain.png +light_wood_planks_shelves: + texture: textures/wood/light_wood_planks.png +dark_wood_planks_shelves: + texture: textures/wood/dark_wood_planks.png +rustic_wood_shelves: + texture: textures/wood/greenheart_wood_grain.png +wood_grain_shelves: + texture: textures/wood/wood_planks_2.png +wood_grain_shelves_2: + texture: textures/wood/wood_grain_3.png + + +#### panel shapes #### +slab: + panel_type: slab +raised: + panel_type: raised +shaker: + panel_type: shaker +divided_window: + panel_type: divided_window +full_window_blurred: + panel_type: full_window + panel_config: + opacity: 0.4 +full_window_clear: + panel_type: full_window + panel_config: + opacity: 0.1 + + +#### handle shapes #### +handle_boxed: + handle_type: boxed +handle_knob: + handle_type: knob + + +#### handle textures #### +handle_brass: + handle_config: + texture: textures/metals/brass.png +handle_black: + handle_config: + texture: textures/flat/black.png +handle_dark_gray: + handle_config: + texture: textures/flat/dark_gray.png \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/coffee_machine.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/coffee_machine.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0927658a906a3834f448d5076fb37bbfe1a85627 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/coffee_machine.yaml @@ -0,0 +1,17 @@ +default: + name: coffee_machine + size: [null, null, 0.44] + xml: fixtures/coffee_machines/delonghi_espresso + +delonghi_espresso: + size: [null, null, 0.44] + xml: fixtures/coffee_machines/delonghi_espresso + +delonghi_espresso_2: + size: [null, null, 0.38] + xml: fixtures/coffee_machines/delonghi_espresso_2 + +nespresso: + name: coffee_machine + size: [null, null, 0.31] + xml: fixtures/coffee_machines/nespresso \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/floor.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/floor.yaml new file mode 100644 index 0000000000000000000000000000000000000000..99be747ddc5c48b71f7dd4cfd39d0235b5a8f37c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/floor.yaml @@ -0,0 +1,68 @@ +default: + texture: textures/wood/gray_wood_planks.png + +wood: + texture: textures/wood/wood_planks.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" +wood_2: + texture: textures/wood/wood_planks_2.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + +gray_wood: + texture: textures/wood/gray_wood_planks.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + +dark_wood: + texture: textures/wood/dark_wood_planks.png + +light_wood: + texture: textures/wood/light_wood_planks.png +light_wood_2: + texture: textures/wood/light_wood_planks_2.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" +light_wood_long: + texture: textures/wood/light_wood_planks_long.png + rgba: [1, 1, 1, 1] + +warm_wood: + texture: textures/wood/warm_wood_planks.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + +concrete_tiles: + texture: textures/tiles/concrete_tiles.png + mat_attrib: + texrepeat: "0.5 0.5" + texuniform: "true" +flower_ceramic_tiles: + texture: textures/tiles/flower_ceramic.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + +# rustic +wood_3: + texture: textures/wood/wood_planks_3.png + mat_attrib: + texrepeat: "0.75 0.75" + texuniform: "true" + +# mediterranean +orange_tiles: + texture: textures/tiles/orange_tiles.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + +# transitional_1 +dark_wood_planks: + texture: textures/wood/dark_wood_planks_2.png diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/framed_window.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/framed_window.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b9df2491ba66af1fb705aa9cc03d1857822c3d8f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/framed_window.yaml @@ -0,0 +1,3 @@ +default: + texture: textures/wood/dark_wood_planks.png + window_bak: textures/flat/warm_white.png \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/fridge.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/fridge.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bba812f817c33227b33c18bb4995f739a09a77d8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/fridge.yaml @@ -0,0 +1,18 @@ +default: + name: fridge + size: [null, null, 1] + +pack_1: + xml: fixtures/fridges/pack_1 + +pack_2: + xml: fixtures/fridges/pack_2 + +modern: + xml: fixtures/fridges/modern + +full_height_doors: + xml: fixtures/fridges/full_height_doors + +four_doors: + xml: fixtures/fridges/four_doors \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/hood.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/hood.yaml new file mode 100644 index 0000000000000000000000000000000000000000..08de0232778681ba3eff8cca23d6a9b86e060ffc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/hood.yaml @@ -0,0 +1,14 @@ +default: + xml: fixtures/hoods/simple_silver + +simple_silver: + xml: fixtures/hoods/simple_silver + +tall_stainless: + xml: fixtures/hoods/tall_stainless + +pack_1: + xml: fixtures/hoods/pack_1 + +pack_2: + xml: fixtures/hoods/pack_2 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/microwave.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/microwave.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3bb330bd73aa4d3a3a58d857897cb0fb35c5ea8c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/microwave.yaml @@ -0,0 +1,18 @@ +default: + alignment: bottom_front + size: [0.8, -1, -1] + +standard: + xml: fixtures/microwaves/standard + +gray: + xml: fixtures/microwaves/gray + +hamilton_beach: + xml: fixtures/microwaves/hamilton_beach + +pack_1: + xml: fixtures/microwaves/pack_1 + +pack_2: + xml: fixtures/microwaves/pack_2 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/oven.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/oven.yaml new file mode 100644 index 0000000000000000000000000000000000000000..788f840ebd49b7c46d0a9ea9483a41449c4a6e31 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/oven.yaml @@ -0,0 +1,20 @@ +default: + xml: fixtures/ovens/pack_1 + +pack_1: + xml: fixtures/ovens/pack_1 + +beko: + xml: fixtures/ovens/beko + +gorenje: + xml: fixtures/ovens/gorenje + +westerfeld: + xml: fixtures/ovens/westerfeld + +gorenje_dark: + xml: fixtures/ovens/gorenje_dark + +bosch: + xml: fixtures/ovens/bosch \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/sink.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/sink.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a4ba9608298bfc846a8919e7cdb6aed91df6bf81 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/sink.yaml @@ -0,0 +1,29 @@ +default: + size: [null, 0.55, null] + +concrete_sink: + xml: fixtures/sinks/concrete_sink + +white_sink: + xml: fixtures/sinks/white_sink + +1_bin_wide_top_handle: + xml: fixtures/sinks/1_bin_wide_top_handle + +1.5_bins_storage_left_stainless: + xml: fixtures/sinks/1.5_bins_storage_left_stainless + +1_bin_storage_left_white_silver: + xml: fixtures/sinks/1_bin_storage_left_white_silver + +1_bin_storage_right_dark: + xml: fixtures/sinks/1_bin_storage_right_dark + +2_bins_farmhouse: + xml: fixtures/sinks/2_bins_farmhouse + +2_bins_stainless: + xml: fixtures/sinks/2_bins_stainless + +# brown_metal: +# xml: fixtures/sinks/brown_metal_sink \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/utensil_holder.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/utensil_holder.yaml new file mode 100644 index 0000000000000000000000000000000000000000..296434ee267205c9655db2120d7e360434c799e0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/utensil_holder.yaml @@ -0,0 +1,12 @@ +default: + name: utensil_holder + scale: 0.35 + +holder_1: + xml: fixtures/accessories/utensil_holders/holder_1 + +holder_2: + xml: fixtures/accessories/utensil_holders/holder_2 + +holder_3: + xml: fixtures/accessories/utensil_holders/holder_3 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/wall.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/wall.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2156046a86e1f0df6d7cf76e81784cc9e4f8f5a1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fixture_registry/wall.yaml @@ -0,0 +1,122 @@ +default: + quat: [-0.7071068, 0.7071068, 0, 0] + texture: textures/bricks/white_bricks.png + mat_attrib: + texrepeat: "3 3" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +red_bricks: + texture: textures/bricks/red_bricks.png +white_bricks: + texture: textures/bricks/white_bricks_2.png + mat_attrib: + texrepeat: "1.75 1.75" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" +playground: + texture: textures/albedo.png + mat_attrib: + texrepeat: "2 2" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +white_tiles: + texture: textures/tiles/white_tiles.png + mat_attrib: + texrepeat: "2 2" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" +white_square_tiles: + texture: textures/tiles/white_square_tiles.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# coastal +black_square_tiles: + texture: textures/tiles/black_square_tiles.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# mediterranean +orange_square_tiles: + texture: textures/tiles/orange_square_tiles.png + mat_attrib: + texrepeat: "2 2" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# traditional_2 +diamond_tiles: + texture: textures/tiles/diamond_tiles.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# flat textures +white_plaster: + texture: textures/flat/plaster.png +white: + texture: textures/flat/white.png +warm_white: + texture: textures/flat/warm_white.png + +concrete: + texture: textures/others/concrete.png + +# transitional_1 +diamond_marble_parquet: + texture: textures/tiles/diamond_marble_parquet.png + +# transitional_2 +diamond_white_tiles: + texture: textures/tiles/diamond_white_tiles.png + mat_attrib: + texrepeat: "5 5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# traditional_1 +varied_marble_tiles: + texture: textures/tiles/varied_marble_tiles.png + +# modern_1 +marble: + texture: textures/marble/marble_2.png + mat_attrib: + texrepeat: "0.75 0.75" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# modern_2 +black_marble_tiles: + texture: textures/tiles/black_marble_tiles.png + mat_attrib: + texrepeat: "0.75 0.75" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# rustic +wood_planks: + texture: textures/wood/wood_planks_wall.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/four_doors/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/four_doors/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..31881124b1aea94f7e9939f8ea6f5cdc12293497 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/four_doors/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/full_height_doors/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/full_height_doors/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..b018bc0620863e98dfdad9d7d72e835786d6fc2d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/full_height_doors/model.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/modern/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/modern/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..426d1aab0acc1c3af64743c5cd5c04a495cf9bb5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/modern/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6a1940a2f7c7e3c002803b60b628903ebf4d9c1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/pack_1/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c44c70907907729ae1fbb4a3990e27390f974a8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/fridges/pack_2/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..2c3efee529f0219e0de5839274eee255029c389e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/pack_1/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..b628cad0ef5583e021fb29306b2b39ac42a9b93c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/pack_2/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/simple_silver/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/simple_silver/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e6cca2204aa7ebc1506f549060fc342486aa97a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/simple_silver/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/tall_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/tall_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..205055b96e7594c57fb754e3615fc8cae8a7085c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/hoods/tall_stainless/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/curved_door/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/curved_door/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..91609e037efff71f1b64019b9b134b5ca8475724 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/curved_door/model.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/gray/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/gray/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..08aa0f613ca6869d856131d7f57eb10a57856f82 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/gray/model.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/hamilton_beach/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/hamilton_beach/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0de090118c20a006740868e82906ebefefd316af --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/hamilton_beach/model.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..28a85784437d230219fac15cfd036624839e4da4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/pack_1/model.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..626ecd726cc3424ca853a945ec838ed56abca535 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/pack_2/model.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/silver_black_metal/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/silver_black_metal/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..55bcd99639a9d5ba9e3db3b001268c3748678c5f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/silver_black_metal/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/square_with_button/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/square_with_button/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b24a755c7d3c462949291f739b6e6a440dcf6f2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/square_with_button/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/standard/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/standard/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..90bb3ff10a7a2bbe27a30b39e93c1f7eaee3199c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/microwaves/standard/model.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/beko/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/beko/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..26005c916247b64fc8a5a419a9971d6cb30cc331 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/beko/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/bosch/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/bosch/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..24ef5cfdba17667af3c8cbc4cef5349341382fc7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/bosch/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/gorenje/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/gorenje/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..10e42069905ee72716e692cae891ca868174b1e5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/gorenje/model.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/gorenje_dark/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/gorenje_dark/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..11557b9e55672f1247ee5c3b1825ddb2255fecbc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/gorenje_dark/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c5d0b69a5371865c20e1c2a9d6efb9d46eac0380 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/pack_1/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/westerfeld/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/westerfeld/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..16bd81b116c9a3490330a04e7874907f2fa14f18 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/ovens/westerfeld/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1.5_bins_storage_left_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1.5_bins_storage_left_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..017274b85d0af6e7293650cf5bc88a10613859a5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1.5_bins_storage_left_stainless/model.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_storage_left_white_silver/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_storage_left_white_silver/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..e7eda8d0e6a0dd26b58d5b17a4aea89c24a794f4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_storage_left_white_silver/model.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_storage_right_dark/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_storage_right_dark/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..350a66bfbc3293e9475877ffb44d552a944030c4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_storage_right_dark/model.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_wide_top_handle/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_wide_top_handle/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..1819859ef088bffb8fabc6ca926fe45b3bccea5e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/1_bin_wide_top_handle/model.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_farmhouse/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_farmhouse/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..f25bb4c0c6d99b0cdf6cf885f4cfb65eb6fc4503 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_farmhouse/model.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..52ef7c497f505ab22af9d5475713565d31fb7513 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_stainless/model.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_storage_left_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_storage_left_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..50cde576a070a352ab8de313b095d520a627774a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/2_bins_storage_left_stainless/model.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/brown_metal_sink/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/brown_metal_sink/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..2a663f37012e93c57b33d3df94ee7c0637e3ed4d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/brown_metal_sink/model.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/concrete_sink/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/concrete_sink/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..197a99ea6429cb2647bb380cb5f3729d94f93a7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/concrete_sink/model.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/white_sink/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/white_sink/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..cab35a8b43ad4d1c97f935384be6a5848f07d785 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/sinks/white_sink/model.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/basic_sleek_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/basic_sleek_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..f65c5d6ac459f543e28b6787a377b27cad009b94 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/basic_sleek_induc/model.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/coil_burners_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/coil_burners_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..d6693eedc0e8661ea6576cfa4ce2559571a1ff7b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/coil_burners_induc/model.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/dual_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/dual_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..577a61092f42081bd532c5f686403e35d0385b2f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/dual_gas/model.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/frigidaire_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/frigidaire_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..08aafb2502a1459da00ac2281dce0d9dc7ce73b0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/frigidaire_gas/model.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/simple_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/simple_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..db0473db39bc0c4909cb329d4e6cf586c0c8cfb7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/simple_gas/model.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/square_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/square_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0bf920637cc060cf1bfcfabfd4c8f98c5ba7ab15 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/square_gas/model.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/whirlpool_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/whirlpool_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb35220e37d1fc6ccf8e63a33be8e2a345a9775c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/whirlpool_induc/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/wolf_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/wolf_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..634f8a01d1a70813f0bba535255ef34ef43af0ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/wolf_gas/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/zline_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/zline_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..23e75e6626ae29ef03258300c59b8ea635c77b70 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stoves/zline_gas/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/alborz_top_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/alborz_top_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c51313fe09167b488cb124d815c9510392651103 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/alborz_top_gas/model.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/pack_1_top_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/pack_1_top_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..25a9767f714727f51b0ed1515cb6721937627e0e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/pack_1_top_gas/model.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/pack_1_top_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/pack_1_top_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6bd2372cb3967719ce6babf0e95b9a9217d302f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/pack_1_top_induc/model.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/sleek_silver_top_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/sleek_silver_top_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..409e3283ae93664db1b63c07db0238ac1d16d9cc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/stovetops/sleek_silver_top_gas/model.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/basic_popup/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/basic_popup/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..289860b79c5494d08b177720d333f191fdb29542 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/basic_popup/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/basic_popup_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/basic_popup_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0aa1d417682beb4a692f4b459cff7f89578c2a75 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/basic_popup_2/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/boxy/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/boxy/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..e5917240b819321db80a299b4284ce9ff3c28363 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/boxy/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/fancy/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/fancy/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..f2126133d4cda53baea7ef8a7e968cb81c0c45e4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/fancy/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/vintage/model.xml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/vintage/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..d137ea7bf1879d0e91cfd5013cedefacf5166f67 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/fixtures/toasters/vintage/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_large.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d19804c3d6b704361a0679c2105a60fe20e22b95 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_large.yaml @@ -0,0 +1,613 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [3.04, 1.5, 0.02] + pos: [3.04, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [3.04, 1.5, 0.1] + pos: [3.04, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [3, 1.5, 0.02] + pos: [0, -3, 1.5] + + - name: wall_left_backing + type: wall + + backing: true + wall_side: left + size: [3, 1.5, 0.1] + pos: [0, -3, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [3, 1.5, 0.02] + pos: [6.08, -3, 1.5] + + - name: wall_right_backing + type: wall + + backing: true + wall_side: right + size: [3, 1.5, 0.1] + pos: [6.08, -3, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + attach_to: wall + pos: [3.0, null, 1.2] + + - name: utensil_rack + type: utensil_rack + attach_to: wall + pos: [1.9, null, 1.15] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -1.8, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -1.9, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_right + pos: [null, -1.0, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_right + pos: [null, -2.5, 1.2] + + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [3.04, 3, 0.02] + pos: [3.04, -3, 0] + + - name: floor_backing + type: floor + + backing: true + size: [3.04, 3, 0.1] + pos: [3.04, -3, 0] + +# fixtures on the main wall +main_group: +# # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_main + type: counter + + size: [3, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_1 + type: counter + interior_obj: stovetop + + size: [1.5, 0.65, 0.92] + align_to: counter_main + side: right + obj_x_percent: 0.33 + obj_y_percent: 0.5 + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.88, 0.65, 0.92] + align_to: counter_1 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + pos: [0.325, -0.2, 1.85] + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: left + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_main + side: right + + - name: shelves_1 + type: open_cabinet + default_config_name: shelves + + size: [0.5, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + - name: shelves_2 + type: open_cabinet + default_config_name: shelves + + size: [0.6, 0.4, 0.92] + align_to: shelves_1 + side: right + offset: [1.1, 0, 0] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + - name: stack_4 + type: stack + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_4 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_1_main_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [0.35, 0.40] + pos: [0.20, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: stove + size: [0.5, 0.35] + pos: ["ref", 1.0] + rotation: [0, 0] + +# Group for island +front_group: + group_origin: [0, 0] + group_pos: [1.975, -4.075] + group_z_rot: 3.1415 + + bottom_row: + - name: counter_1 + type: counter + base_opening: [false, true] + + size: [2.55, 0.65, 0.92] + pos: [0, 0, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 0.40, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.40, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 0.40, 0.5] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.4] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: sink + type: sink + + - name: counter_1 + type: counter + interior_obj: sink + obj_x_percent: 0.5 + obj_y_percent: 0.15 + + size: [3, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: counter_corner_right + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.60, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + # Top row (cabinets and microwave) + top_row: + - name: window_group + type: framed_window + + size: [2, 0.05, 1.25] + num_windows: 3 + pos: [1.1, -0.25, 1.85] + ofs: [0.0, .24, -0.10] + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [2.7, -0.2, 1.85] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_1 + side: right + + counter_accessories: + - name: plant + type: plant + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: sink + loc: left + size: [0.4, 0.4] + pos: [null, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: sink + loc: right + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + +# # fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [5.9, -0.7] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: stack_left + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: left + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: left + + size: [0.5, 0.78, 2.26] + pos: [0.2, -0.21, 1.18] + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.78] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + + pos: [0.92, -0.21, 0.9] + interior_obj: fridge + + - name: fridge_top + type: hinge_cabinet + size: [fridge_housing, 0.78, null] + align_to: fridge_housing + alignment: front + side: top + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + - name: stack_right + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: right + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: right + + size: [0.5, 0.78, 2.26] + align_to: fridge_top + side: right + alignment: top_back + + - name: cab_top_corner + type: box + + size: [0.65, 0.78, 0.92] + align_to: stack_left + side: left + alignment: top_back + + - name: bottom_corner + type: box + + size: [0.05, 0.78, 0.89] + pos: [-0.075, -0.21, 0.445] + + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.78, 0.6] + # pos: [3.47, -0.21, 0.35] + align_to: stack_right + side: right + alignment: bottom_back + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.78, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.78, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.78, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.26 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + - name: side_bottom + type: stack + + levels: ["drawer", "drawer", "hinge_cabinet"] + percentages: [0.1327433628, 0.1327433628, 0.7345132744] + + configs: + hinge_cabinet: + panel_config: + handle_vpos: center + + size: [1, 0.78, 2.26] + align_to: bottom + side: right + alignment: bottom_back diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_small.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..582c3757987f18b965d544e4e5f62d72fba3989c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_small.yaml @@ -0,0 +1,520 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.2, 1.5, 0.02] + pos: [2.2, 0., 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [2.2, 1.5, 0.1] + pos: [2.2, 0., 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.5, 1.5, 0.02] + pos: [0, -2.5, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.5, 1.5, 0.1] + pos: [0, -2.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.5, 1.5, 0.02] + pos: [4.4, -2.5, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.5, 1.5, 0.1] + pos: [4.4, -2.5, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + attach_to: wall + pos: [4, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_left + pos: [null, -0.7, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -2.8, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -2.9, 1.2] + + - name: utensil_rack + type: utensil_rack + attach_to: wall_right + pos: [null, -0.5, 1.15] + + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.2, 2.5, 0.02] + pos: [2.2, -2.5, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.2, 2.5, 0.1] + pos: [2.2, -2.5, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_main + type: counter + + size: [3, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_main + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + pos: [0.325, -0.2, 1.85] + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: left + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: window_group + type: framed_window + + size: [1.45, 0.05, 1.25] + num_windows: 2 + ofs: [0.0, .20, -0.10] + align_to: cab_main + side: right + offset: [0.075, 0, 0] + + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: window_group + side: right + offset: [0.075, 0, 0] + + - name: cab_corner_3 + type: box + + size: [0.65, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + counter_accessories: + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + size: [1.0, 0.4] + pos: [1.0, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_main_main_group + size: [1.0, obj] + pos: [-1.0, 1.0] + rotation: [0, 0] + +# Group for island +front_group: + group_origin: [0, 0] + group_pos: [2.75, -3.15] + group_z_rot: 3.1415 + + bottom_row: + - name: counter_1 + type: counter + base_opening: [false, true] + overhang: 0 + + size: [1.9, 0.65, 0.92] + pos: [0, 0.025, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + - name: plant + type: plant + + placement: + fixture: counter_1_front_group + size: [1.0, 0.40] + pos: [0.0, 0.0] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.35, 0.40, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.40, 0.40, 0.5] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.4] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [0.5, 0.65, 0.92] + pos: [3.45, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_1 + side: left + alignment: top_back + + - name: counter_2 + type: counter + + size: [0.5, 0.65, 0.92] + align_to: stove + side: left + alignment: top_back + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + - name: fridge + type: fridge + + size: [null, null, 1.75] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_2 + side: left + alignment: bottom_back + interior_obj: fridge + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + configs: + single_cabinet: + orientation: left + + size: [0.5, 0.6, 0.84] + align_to: stove + side: left + alignment: top_back + offset: [0, 0.00, -0.03] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0, 0.00, -0.03] + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + pos: [3.45, -0.2, 1.85] + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: left + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + orientation: left + + size: [0.5, 0.4, 0.92] + align_to: microwave + alignment: bottom_back + side: left + + - name: cab_3 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, 0.55, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_left_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_2_left_group + size: [1.0, 0.35] + pos: [null, 1.0] + rotation: [0, 0] + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [4.4, -0.7] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_1 + type: counter + interior_obj: sink + + size: [2.1, 0.65, 0.92] + pos: [1.05, -0.325, 0.46] + # obj_x_percent: 0.476 + obj_x_percent: 0.238 + obj_y_percent: 0.5 + + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_1 + side: right + + - name: counter_corner_2 + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [0.5, -0.3, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_1 + side: right + alignment: top_back + + - name: stack_2 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.45, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0.5, -0.2, 1.85] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + counter_accessories: + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_right_group + sample_region_kwargs: + ref: sink + loc: "right" + size: [1.0, 0.40] + pos: ["ref", 1.0] + rotation: [0, 0] \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_large.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..79f9a8631d57f1a084a0fb63bdc2bf0136586d0e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_large.yaml @@ -0,0 +1,449 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.6, 1.5, 0.02] + pos: [2.6, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, false] + size: [2.6, 1.5, 0.1] + pos: [2.6, 0, 1.5] + + + - name: wall_left + type: wall + + wall_side: left + size: [2.95, 1.5, 0.02] + pos: [0, -2.95, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.95, 1.5, 0.1] + pos: [0, -2.95, 1.5] + + wall_accessories: + + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [2.9, null, 1.2] + + - name: outlet_2 + type: wall_accessory + + attach_to: wall_left + pos: [null, -1.0, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.3, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.4, null, 1.2] + + + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.6, 2.95, 0.02] + pos: [2.6, -2.95, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.6, 2.95, 0.1] + pos: [2.6, -2.95, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner_main + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_main + type: counter + + size: [1, 0.65, 0.92] + align_to: counter_corner_main + side: right + alignment: top_front + + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_1_right + type: counter + interior_obj: stovetop + + size: [2, 0.65, 0.92] + align_to: counter_main + side: right + obj_x_percent: 0.25 + obj_y_percent: 0.5 + + - name: fridge + type: fridge + + size: [null, null, 1.78] + + - name: fridge_housing + type: housing_cabinet + interior_obj: fridge + + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_1_right + side: right + alignment: bottom_back + + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [1.2, -0.2, 1.85] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1, 0.4, 0.92] + align_to: cab_main + side: right + offset: [1, 0, 0] + + - name: fridge_cab + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: toaster + type: toaster + + placement: + fixture: counter_1_right + sample_region_kwargs: + ref: shelves + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, 0.30] + pos: [null, 1.0] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.15] + group_z_rot: 1.5708 + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + orientation: left + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + pos: [0.7, -0.2, 1.85] + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_1 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.075, 0, 0] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: window_group + side: right + offset: [0.075, 0, 0.0] + + - name: cab_corner_3 + type: box + + size: [0.7, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_1_left + type: counter + interior_obj: sink + + size: [3, 0.65, 0.92] + pos: [1.95, -0.325, 0.46] + # positions sink directly underneath shelves + obj_x_percent: 0.5 + obj_y_percent: 0.5 + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1_left + side: right + + - name: island + type: counter + default_config_name: island + base_opening: [true, false] + + size: [2.45, 1.6, 0.92] + pos: [0.9, -2.95, 0.46] + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.6, 0.6] + pos: [0.05, -0.3, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.6, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: single_cabinet + orientation: left + panel_config: + handle_vpos: top + + size: [0.35, 0.6, 0.84] + pos: [0.625, -0.3, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_1 + side: right + alignment: top_back + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_left + sample_region_kwargs: + ref: sink + loc: right + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_left + sample_region_kwargs: + ref: sink + loc: "left" + size: [1.0, 0.30] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_corner_main + size: [0.40, "obj"] + pos: [0.0, 1.0] + # rotation: [-1.57, -1.57] + rotation: [0, 0] + + - name: plant + type: plant + + placement: + fixture: island + size: [1.0, 0.25] + pos: [null, null] + rotation: [0, 0] + +stool_group: + group_origin: [0, 0] + group_z_rot: -1.5708 + group_pos: [2.95, -3.25] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 0.7, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.7, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 0.7, 0.5] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_small.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3f1a742bbc2b0c0b9894260c62911efa0a70aefb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_small.yaml @@ -0,0 +1,403 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.6, 1.5, 0.02] + pos: [2.6, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [false, true] + size: [2.6, 1.5, 0.1] + pos: [2.6, 0, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.6, 1.5, 0.02] + pos: [5.2, -2.6, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.6, 1.5, 0.1] + pos: [5.2, -2.6, 1.5] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.6, 2.6, 0.02] + pos: [2.6, -2.6, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.6, 2.6, 0.1] + pos: [2.6, -2.6, 0] + + # Wall accessories (e.g. outlets, clocks, paintings) + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [4.55, null, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [1.8, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [1.9, null, 1.2] + + - name: utensil_rack + type: utensil_rack + + attach_to: wall + pos: [4.05, null, 1.2] + + - name: outlet_2 + type: wall_accessory + + attach_to: wall_right + pos: [null, -3, 1.2] + + # - name: pan_rack + # type: wall_accessory + # config_name: pan_rack + + # attach_to: wall_right + # pos: [null, -2.3, 1.2] + +# fixtures on the main wall +main_group: + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [2.05, -0.2, 1.85] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + align_to: cab_main + side: right + alignment: back + + - name: cab_corner_2 + type: box + + size: [0.4, 0.25, 0.92] + align_to: cab_corner + side: front + alignment: right + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_main + type: counter + interior_obj: sink + + size: [3, 0.65, 0.92] + pos: [3.05, -0.325, 0.46] + obj_x_percent: 0.5 + obj_y_percent: 0.50 + + - name: counter_corner_main + type: counter + hollow: [false, false] + overhang: 0 + + size: [0.65, 0.6, 0.92] + align_to: counter_main + side: right + alignment: back + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + pos: [2.05, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + # Decorations on counters + counter_accessories: + - name: plant + type: plant + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_1_main_group + size: [1.0, 0.25] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_corner_main + # sample_region_kwargs: + # ref: cab_main + size: [obj.y, 0.30] + pos: [1.0, -1.0] + rotation: [-1.57, -1.57] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_corner_main + # sample_region_kwargs: + # ref: cab_main + size: [0.40, 0.30] + pos: [-1.0, 1.0] + rotation: [0, 0] + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [5.2, -0.65] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [0.5, 0.65, 0.92] + pos: [0.25, -0.325, 0.46] + + - name: counter_corner_left + type: counter + hollow: [false, false] + + size: [0.05, 0.65, 0.92] + align_to: counter_1 + side: left + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_1 + side: right + alignment: top_back + + - name: counter_2 + type: counter + + size: [1.7, 0.65, 0.92] + align_to: stove + side: right + alignment: top_back + + - name: fridge + type: fridge + + size: [null, null, 1.78] + + - name: fridge_housing + type: housing_cabinet + interior_obj: fridge + + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_2 + side: right + alignment: bottom_back + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + pos: [0.25, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0.0, 0.0, -0.03] + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.7, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + orientation: left + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + pos: [0.25, -0.2, 1.85] + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: right + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_micro + alignment: top_back + side: right + offset: [0.00, 0.0, 0.0] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.2, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: cab_3 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + # Decorations on counters + counter_accessories: + - name: toaster + type: toaster + + placement: + fixture: counter_2 + size: [1.0, 0.40] + pos: [-1.0, 1.0] + rotation: [0, 0] + + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_2 + size: [0.60, 0.52] + pos: [1.0, 1.0] + rotation: [0, 0] + margin: 0.0 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_large.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5c8c6a8b93aca7ed1402b4c73644cc504669cf7f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_large.yaml @@ -0,0 +1,654 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [3.2, 1.5, 0.02] + pos: [3.2, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [3.2, 1.5, 0.1] + pos: [3.2, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.5, 1.5, 0.02] + pos: [0, -2.5, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.5, 1.5, 0.1] + pos: [0, -2.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.5, 1.5, 0.02] + pos: [6.4, -2.5, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.5, 1.5, 0.1] + pos: [6.4, -2.5, 1.5] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [3.2, 2.5, 0.02] + pos: [3.2, -2.5, 0] + + - name: floor_backing + type: floor + + backing: true + size: [3.2, 2.5, 0.1] + pos: [3.2, -2.5, 0] + + wall_accessories: + + - name: utensil_rack + type: utensil_rack + attach_to: wall_right + pos: [null, -2.0, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall + pos: [4.2, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall + pos: [4.1, null, 1.2] + + - name: outlet + type: wall_accessory + attach_to: wall_right + pos: [null, -0.6, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_right + pos: [null, -3.0, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_left + pos: [null, -2.4, 1.2] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_1 + type: counter + + size: [2, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_main + type: counter + interior_obj: stovetop + + size: [3, 0.65, 0.92] + align_to: counter_1 + side: right + obj_x_percent: 0.33 + obj_y_percent: 0.5 + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_main + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + pos: [0.325, -0.2, 1.85] + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: left + + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_1 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.075, 0, 0] + + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [0.95, 0.4, 0.92] + align_to: window_group + side: right + offset: [1.15, 0, 0] + + - name: cab_main + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: shelves + side: right + + - name: cab_corner_3 + type: box + + size: [0.75, 0.4, 0.92] + align_to: cab_main + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_2 + side: right + + - name: stack_4 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_4 + side: right + + - name: stack_6 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_5 + side: right + + counter_accessories: + + - name: knife_block + type: knife_block + + placement: + fixture: counter_1_main_group + size: [1.0, obj] + pos: [1.0, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_main_group + size: [1.0, 0.40] + pos: [-1.0, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: shelves_main_group + size: [1.0, 0.35] + pos: [null, 1.0] + rotation: [0, 0] + +# Group for island +island_group: + group_origin: [0, 0] + group_pos: [3.2, -2.725] + group_z_rot: 3.1415 + + island: + - name: sink + type: sink + + - name: island + type: counter + default_config_name: island + # base_opening: [false, true] + interior_obj: sink + + size: [2.5, 1.55, 0.92] + pos: [0, 0, 0.46] + obj_x_percent: 0.5 + obj_y_percent: 0.15 + + island_bottom_row: + - name: island_stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.60, 0.84] + pos: [0, -0.425, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: island_stack_1 + side: left + alignment: top_back + + - name: island_panel_cab_right + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.1, 1.45, 0.84] + pos: [1.2, 0, 0.47] + + - name: island_cab_right + type: stack + + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.65, 0.6, 0.84] + align_to: island_stack_1 + side: right + + - name: island_panel_cab_left + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.1, 1.45, 0.84] + pos: [-1.2, 0, 0.47] + + - name: island_base_box + type: box + + size: [2.3, 0.1, 0.89] + pos: [0, 0.2, 0.445] + + island_accessories: + - name: plant + type: plant + + placement: + fixture: island_island_group + size: [0.4, 0.4] + rotation: [0, 0] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 0.70, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.70, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 0.70, 0.5] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -3.5] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [2, 0.65, 0.92] + pos: [1.8, -0.325, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.6, 0.6] + pos: [0.4, -0.3, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.6, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + pos: [1.05, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.5, 0.4, 0.92] + pos: [1.55, -0.2, 1.85] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: shelves + side: right + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [6.4, -0.7] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [2, 0.65, 0.92] + pos: [1, -0.325, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.75] + + - name: fridge_housing + type: housing_cabinet + interior_obj: fridge + + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_1 + side: right + alignment: bottom_back + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [0.5, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0.5, -0.2, 1.85] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: fridge_cab + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, 0.40, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_right_group + size: [1.0, 0.52] + pos: [-1.0, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: toaster + type: toaster + + placement: + fixture: counter_1_right_group + size: [1.0, 0.40] + pos: [1.0, 0] + rotation: [0, 0] + + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_small.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..724494bb2276c57c93fca29770d327c1569c55e2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_small.yaml @@ -0,0 +1,483 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.2, 1.5, 0.02] + pos: [2.2, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [2.2, 1.5, 0.1] + pos: [2.2, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.25, 1.5, 0.02] + pos: [0, -2.25, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.25, 1.5, 0.1] + pos: [0, -2.25, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.25, 1.5, 0.02] + pos: [4.4, -2.25, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.25, 1.5, 0.1] + pos: [4.4, -2.25, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall_left + pos: [null, -1.0, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + + pos: [3.2, null, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_right + + pos: [null, -0.75, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -3.25, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -3.15, 1.2] + + - name: utensil_rack + type: utensil_rack + + attach_to: wall_left + pos: [null, -1.8, 1.2] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.2, 2.25, 0.02] + pos: [2.2, -2.25, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.2, 2.25, 0.1] + pos: [2.2, -2.25, 0] + +# fixtures on the main wall +main_group: + # Top row (cabinets and microwave) + top_row: + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + pos: [1.7, -0.25, 1.85] + num_windows: 3 + ofs: [0.0, .224, -0.10] + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [3.2, -0.2, 1.85] + + - name: cab_corner + type: box + + size: [0.7, 0.4, 0.92] + align_to: cab_main + side: right + alignment: back + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: right + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner_left + type: counter + hollow: [false, false] + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: sink + type: sink + + - name: counter_main + type: counter + interior_obj: sink + + size: [3, 0.65, 0.92] + align_to: counter_corner_left + side: right + obj_x_percent: 0.33 + obj_y_percent: 0.50 + + - name: counter_corner_right + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_main + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + pos: [0.95, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [0.85, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + counter_accessories: + + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: plant + type: plant + + placement: + fixture: counter_corner_left_main_group + size: [0.40, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [4.4, -0.65] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [0.5, 0.65, 0.92] + pos: [0.3, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_1 + side: right + alignment: top_back + + - name: counter_2 + type: counter + + size: [0.5, 0.65, 0.92] + align_to: stove + side: right + alignment: top_back + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.78] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_2 + side: right + alignment: bottom_back + interior_obj: fridge + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + # Cabinets built into counters + bottom_row_cabinets: + # - name: stack_1 + # type: stack + # # levels are specified from bottom up + # levels: ["hinge_cabinet", ["drawer", "drawer"]] + # percentages: [0.75, 0.25] + + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + configs: + single_cabinet: + panel_config: + handle_vpos: top + orientation: left + + size: [0.5, 0.6, 0.84] + pos: [0.3, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0.0, 0.00, -0.03] + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + orientation: left + + size: [0.5, 0.4, 0.92] + pos: [0.3, -0.2, 1.85] + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: right + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: microwave + alignment: bottom_back + side: right + + - name: cab_3 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, 0.55, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: knife_block + type: knife_block + + placement: + fixture: counter_1_right_group + size: [1.0, "obj"] + pos: [null, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_2_right_group + size: [1.0, 0.35] + pos: [null, 1.0] + rotation: [0, 0] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -3] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [2.8, 0.65, 0.92] + pos: [0.9, -0.325, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + pos: [-0.1, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0, -0.2, 1.85] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.3, 0.4, 0.92] + align_to: cab_1 + side: right + + counter_accessories: + + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: cab_1_left_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: shelves_left_group + size: [1.0, 0.40] + pos: [null, 0.5] + rotation: [0, 0] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/galley.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/galley.yaml new file mode 100644 index 0000000000000000000000000000000000000000..46dfb3c3464ccc66abc65f30ae34fab8304757ee --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/galley.yaml @@ -0,0 +1,384 @@ +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [1.6, 1.5, 0.02] + pos: [1.6, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [1.6, 1.5, 0.1] + pos: [1.6, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.8, 1.5, 0.02] + pos: [0, -2.8, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.8, 1.5, 0.1] + pos: [0, -2.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.8, 1.5, 0.02] + pos: [3.2, -2.8, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.8, 1.5, 0.1] + pos: [3.2, -2.8, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall_left + pos: [null, -2.6, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_right + + pos: [null, -3, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_right + + pos: [null, -1.5, 1.2] + + - name: untensil_rack + type: utensil_rack + attach_to: wall_left + + pos: [null, -3.3, 1.15] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_right + pos: [null, -3.5, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_right + pos: [null, -3.6, 1.2] + + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [1.6, 2.8, 0.02] + pos: [1.6, -2.8, 0] + + - name: floor_backing + type: floor + + backing: true + size: [1.6, 2.8, 0.1] + pos: [1.6, -2.8, 0] + +# fixtures on the left wall +left_group: + group_origin: [0, 0] + group_pos: [0, -4.05] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.78] + pos: [3.58, -0.43, 0.89] + + - name: sink + type: sink + + - name: counter + type: counter + interior_obj: sink + + size: [3.8, 0.65, 0.92] + align_to: fridge + side: left + alignment: bottom_back + # pos: [2.15, -0.325, 0.46] + obj_x_percent: 0.735 + obj_y_percent: 0.5 + + + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [-0.19, -0.2, 1.85] + + - name: cab_2 + type: open_cabinet + default_config_name: shelves + + size: [0.8, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_2 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.075, 0, 0] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + pos: [-0.27, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [0.85, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + - name: stack_4 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_3 + side: right + + counter_accesories: + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_left_group + sample_region_kwargs: + ref: sink + size: [0.50, 0.25] + pos: ["ref", 1.0] + rotation: [0, 0] + +# fixtures on the right wall +main_group: + group_origin: [0, 0] + group_pos: [3.2, 0] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_main + type: counter + + size: [2, 0.65, 0.92] + pos: [1.0, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_main + side: right + alignment: top_back + + - name: counter_right + type: counter + + size: [2, 0.65, 0.92] + align_to: stove + alignment: top_back + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0.50, -0.2, 1.85] + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_main + side: right + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: right + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: microwave + alignment: bottom_back + side: right + + - name: cab_3 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_2 + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [0.5, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0, 0.0, -0.03] + + - name: stack_4 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_1_main_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [1.0, 0.30] + pos: [null, 1.0] + rotation: [0, 0] + + - name: toaster + type: toaster + + placement: + fixture: counter_right_main_group + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_left_group + sample_region_kwargs: + ref: cab_1_left_group + size: [1, obj] + pos: [null, 1.0] + rotation: [0, 0] \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/one_wall_large.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/one_wall_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f8309b25936b47b221f6b54d5573104af60ca4c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/one_wall_large.yaml @@ -0,0 +1,424 @@ +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [3.15, 1.5, 0.02] + pos: [2.15, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + # whether backing is extended on the left/right side + backing_extended: [true, true] + size: [3.15, 1.5, 0.1] + pos: [2.15, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.5, 1.5, 0.02] + pos: [-1, -2.5, 1.5] + + - name: wall_left_backing + type: wall + + backing: true + wall_side: left + size: [2.5, 1.5, 0.1] + pos: [-1, -2.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.5, 1.5, 0.02] + pos: [5.3, -2.5, 1.5] + + - name: wall_right_backing + type: wall + + backing: true + wall_side: right + size: [2.5, 1.5, 0.1] + pos: [5.3, -2.5, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [3.15, 2.5, 0.02] + pos: [2.15, -2.5, 0] + + - name: floor_backing + type: floor + + backing: true + size: [3.15, 2.5, 0.1] + pos: [2.15, -2.5, 0] + + # Wall accessories (e.g. outlets, clocks, paintings) + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [3.8, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + + pos: [2, null, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.5, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.6, null, 1.2] + + - name: utensil_rack + type: utensil_rack + + attach_to: wall + pos: [2.75, null, 1.3] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_main + type: counter + + size: [1, 0.65, 0.92] + pos: [1.75, -0.325, 0.46] + + - name: stovetop + type: stovetop + + - name: counter_1 + type: counter + interior_obj: stovetop + + size: [1, 0.65, 0.92] + align_to: counter_main + side: right + obj_x_percent: 0.5 + obj_y_percent: 0.5 + + - name: counter_2 + type: counter + + size: [1.8, 0.65, 0.92] + align_to: counter_1 + side: right + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.78, 0.6] + pos: [0.85, -0.39, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.78, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.78, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.78, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.88] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: micro_housing + side: left + alignment: top_back + interior_obj: fridge + + - name: fridge_top + type: hinge_cabinet + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + alignment: front + side: top + stack_height: 2.6 + stack_fixtures: ["fridge_housing"] + + # Top row (cabinets and microwave) + top_row: + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + pos: [1.75, -0.2, 1.85] + + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + alignment: back + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [0.8, 0.4, 0.92] + align_to: cab_main + side: right + offset: [1, 0, 0] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + align_to: shelves + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.75, -0.3, 0.47] + + - name: stack_4 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_4 + side: right + + - name: stack_6 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + align_to: stack_5 + side: right + + # Decorations on counters + counter_accessories: + - name: knife_block + type: knife_block + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, obj] + pos: [null, 1.0] + rotation: [0, 0] + + - name: toaster + type: toaster + + placement: + fixture: counter_2 + sample_region_kwargs: + ref: shelves + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_2 + sample_region_kwargs: + ref: shelves + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_2 + sample_region_kwargs: + ref: cab_2 + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + +island_group: + group_origin: [0, 0] + group_pos: [2.75, -1.65] + group_z_rot: 3.1415 + + island: + - name: sink + type: sink + + - name: island_counter + type: counter + default_config_name: island + # base_opening: [false, true] + interior_obj: sink + + size: [2.75, 1.4, 0.92] + pos: [0, 1.0, 0.46] + obj_x_percent: 0.5 + obj_y_percent: 0.15 + + island_bottom_row: + - name: island_stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.60, 0.84] + pos: [0, 0.63, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: island_stack_1 + side: right + alignment: top_back + + - name: island_panel_cab_right + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.2, 1.35, 0.84] + pos: [1.25, 1.0, 0.47] + + - name: island_cab_left + type: stack + + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.65, 0.6, 0.84] + align_to: island_stack_1 + side: left + + - name: island_panel_cab_left + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.2, 1.35, 0.84] + pos: [-1.25, 1.0, 0.47] + + - name: island_base_box + type: box + + size: [2.35, 0.1, 0.89] + pos: [0, 1.2, 0.445] + + # island_accessories: + # - name: plant + # type: plant + + # placement: + # fixture: island_counter + # # sample_region_kwargs: + # # ref: cab_1 + # size: [0.40, 0.40] + # # pos: [null, 1.0] + # rotation: [0, 0] + + chairs: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 1.6, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 1.6, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 1.6, 0.5] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/one_wall_small.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/one_wall_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0944a4a7e2ec03e2f5d1b76630916678fc60906d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/one_wall_small.yaml @@ -0,0 +1,305 @@ +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.75, 1.5, 0.02] + pos: [2.75, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [2.75, 1.5, 0.1] + pos: [2.75, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.5, 1.5, 0.02] + pos: [0, -1.5, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [1.5, 1.5, 0.1] + pos: [0, -1.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.5, 1.5, 0.02] + pos: [5.5, -1.5, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [1.5, 1.5, 0.1] + pos: [5.5, -1.5, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.75, 1.50, 0.02] + pos: [2.75, -1.50, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.75, 1.50, 0.1] + pos: [2.75, -1.50, 0] + + # Wall accessories (e.g. outlets, clocks, paintings) + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [4.1, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + + pos: [2, null, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [2.5, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [2.61, null, 1.2] + + # - name: pan_rack + # type: wall_accessory + # config_name: pan_rack + + # attach_to: wall + # pos: [1.25, null, 1.325] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_main + type: counter + interior_obj: sink + + size: [2.5, 0.65, 0.92] + pos: [1.5, -0.325, 0.46] + + obj_x_percent: 0.40 + obj_y_percent: 0.50 + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_main + side: right + alignment: top_back + + - name: counter_right + type: counter + + size: [0.7, 0.65, 0.92] + align_to: stove + alignment: top_back + side: right + + - name: fridge + type: fridge + + size: [null, null, 1.75] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_right + side: right + alignment: bottom_back + interior_obj: fridge + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + orientation: left + default_config_name: cab_top + + size: [0.5, 0.40, 0.92] + pos: [0.5, -0.20, 1.85] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + align_to: cab_1 + side: right + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + align_to: cab_2 + side: right + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_main + alignment: back_bottom + side: right + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.40, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_3 + type: open_cabinet + default_config_name: shelves + num_shelves: 3 + + size: [0.7, 0.40, 0.92] + align_to: microwave + side: right + alignment: bottom_back + + - name: cab_4 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.60, 0.84] + pos: [0.5, -0.30, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.60, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.60, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + - name: stack_4 + type: stack + + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.7, 0.60, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0.0, 0.0, -0.03] + + # Decorations on counters + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_1 + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: toaster + type: toaster + + placement: + fixture: counter_right + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, obj] + pos: [null, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, 0.25] + pos: [null, 1.0] + rotation: [0, 0] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/playground.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/playground.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b9b50003ddcfd9b0977df1cab066681c89ad7a8d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/playground.yaml @@ -0,0 +1,206 @@ +# version of one wall large arena, with integrated stove and microwave + + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_main + type: counter + + size: [4, 0.65, 1] + pos: [3.25, -0.325, 0.5] + obj_x_percent: 0.625 + obj_y_percent: 0.5 + + interior_obj: stovetop + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + + size: [1, 0.45, 1.0] + pos: [1.75, -0.25, 2.10] + + - name: cab_main + type: hinge_cabinet + + size: [1, 0.45, 1.0] + align_to: cab_1 + side: right + + - name: hood + type: hood + size: [stovetop, 0.60, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + # - name: cab_2 + # type: single_cabinet + + # size: [0.5, 0.45, 0.75] + # align_to: microwave + # alignment: bottom_back + # side: right + + # - name: cab_3 + # type: open_cabinet + # default_config_name: shelves + # num_shelves: 3 + + # size: [1.5, 0.45, 0.75] + # align_to: cab_2 + # side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.92] + pos: [1.5, -0.30, 0.51] + + - name: stack_2 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.92] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.92] + align_to: stack_2 + side: right + + - name: stack_4 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.92] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.92] + align_to: stack_4 + side: right + + + wall_stack: + - name: bottom + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer"] + percentages: [0.50, 0.50] + size: [0.8, 0.6, 0.60] + pos: [0.85, -0.30, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, null] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.6, 0.70] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + + +island_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 3.1415 + + island: + - name: sink + type: sink + + - name: island + type: counter + default_config_name: island + hollow: [false, false] + interior_obj: sink + + size: [3, 1.2, 1] + pos: [0, 0.75, 0.5] + obj_x_percent: 0.5 + obj_y_percent: 0.15 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/wraparound.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/wraparound.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b77315277170cd9a0ce4cfd6c1cab56641ce9697 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_layouts/wraparound.yaml @@ -0,0 +1,653 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [3.1, 1.5, 0.02] + pos: [2.8, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [3.1, 1.5, 0.1] + pos: [2.8, 0, 1.5] + + - name: wall_front + type: wall + + wall_side: front + size: [1.15, 1.5, 0.02] + pos: [0.85, -3.4, 1.5] + + - name: wall_front_backing + type: wall + + backing: true + backing_extended: [true, false] + wall_side: front + size: [1.15, 1.5, 0.1] + pos: [0.85, -3.4, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.7, 1.5, 0.02] + pos: [-0.3, -1.7, 1.5] + + - name: wall_left_backing + type: wall + + backing: true + wall_side: left + size: [1.7, 1.5, 0.1] + pos: [-0.3, -1.7, 1.5] + + - name: wall_left_2 + type: wall + + wall_side: left + size: [0.525, 1.5, 0.02] + pos: [2.075, -3.975, 1.5] + + - name: wall_2_left_backing + type: wall + + backing: true + wall_side: left + size: [0.525, 1.5, 0.1] + pos: [2.075, -3.975, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.25, 1.5, 0.02] + pos: [5.9, -2.25, 1.5] + + - name: wall_right_backing + type: wall + + backing: true + wall_side: right + size: [2.25, 1.5, 0.1] + pos: [5.9, -2.25, 1.5] + + wall_accessories: + - name: utensil_rack + type: utensil_rack + attach_to: wall + pos: [3.9, null, 1.15] + + - name: outlet + type: wall_accessory + attach_to: wall + pos: [1.9, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + pos: [5.4, null, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_left + pos: [null, -1.6, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left_2 + pos: [null, -3.8, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left_2 + pos: [null, -3.7, 1.2] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.95, 1.425, 0.02] + pos: [2.95, -1.425, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.95, 1.425, 0.1] + pos: [2.95, -1.425, 0] + + - name: floor_front + type: floor + + # position such that the top left corner is (0, 0) + size: [1.9125, 0.7875, 0.02] + pos: [3.9875, -3.7125, 0] + + - name: floor_front_backing + type: floor + + backing: true + size: [1.9125, 0.7875, 0.1] + pos: [3.9875, -3.7125, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_main + type: counter + + size: [3, 0.65, 0.92] + pos: [1.2, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_main + side: right + alignment: top_back + + - name: counter_1 + type: counter + + size: [1.8, 0.65, 0.92] + align_to: stove + side: right + alignment: top_front + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_1 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.25, 0.4, 0.92] + pos: [0.525, -0.2, 1.85] + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_main + side: right + + - name: hood + type: hood + size: [stove, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stove + side: top + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.65, 0.4, 0.92] + offset: [0.95, 0, 0.0] + align_to: cab_1 + side: right + + - name: cab_corner_3 + type: box + + size: [0.65, 0.4, 0.92] + align_to: shelves + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: right_corner_box + type: box + + size: [0.3, 0.6, 0.84] + align_to: stack_1 + side: left + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0, 0, -0.03] + + - name: stack_4 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + align_to: stack_3 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_main_group + size: [1.0, 0.52] + pos: [1.0, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: stove + size: [0.6, 0.30] + pos: ["ref", 1.0] + rotation: [0, 0] + + - name: plant + type: plant + + placement: + fixture: counter_corner_2_main_group + size: [0.4, 0.4] + pos: [0.0, -1.0] + rotation: [0, 0] + + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.4] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: fridge + type: fridge + + size: [0.9, 0.72, 1.75] + + - name: fridge_housing + type: housing_cabinet + + pos: [2.7, -0.05, 0.875] + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + interior_obj: fridge + + - name: fridge_top + type: hinge_cabinet + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + alignment: front + side: top + stack_height: 2.32 + stack_fixtures: ["fridge_housing"] + + - name: stack_left + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: left + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: left + + size: [0.58, 0.7, 2.32] + align_to: fridge_housing + side: left + alignment: bottom_back + + - name: stack_right + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: right + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: right + + size: [0.58, 0.7, 2.32] + align_to: fridge_housing + side: right + alignment: bottom_back + + - name: box_left_top + type: box + size: [0.65, 0.7, 0.92] + + align_to: stack_left + side: left + alignment: top_back + + - name: box_left_bottom + type: box + size: [0.65, 0.7, 0.89] + + align_to: stack_left + side: left + alignment: bottom_back + + - name: box_right_top + type: box + size: [0.65, 0.7, 0.92] + + align_to: stack_right + side: right + alignment: top_back + + - name: box_right_bottom + type: box + size: [0.65, 0.7, 0.89] + + align_to: stack_right + side: right + alignment: bottom_back + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [5.9, 1.55] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_1 + type: counter + interior_obj: sink + + size: [1.99, 0.65, 0.92] + pos: [3.255, -0.325, 0.46] + obj_x_percent: 0.75 + obj_y_percent: 0.15 + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.10, 0.65, 0.92] + align_to: counter_1 + side: left + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [3.75, -0.3, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_1 + side: left + alignment: top_back + + - name: stack_2 + type: stack + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.6, 0.84] + align_to: dishwasher + side: left + alignment: top_back + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [3.25, -0.2, 1.85] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + orientation: left + + size: [0.5, 0.4, 0.92] + align_to: cab_1 + side: left + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_1 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.225, 0, 0] + + counter_accessories: + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_right_group + sample_region_kwargs: + ref: sink + loc: left + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + +# fixtures on the left wall +front_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -3.4] + group_z_rot: 3.1415 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [1.575, 0.65, 0.92] + pos: [-0.4875, -0.325, 0.46] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.875, 0.6, 0.84] + pos: [-0.8375, -0.3, 0.47] + + # Top row (cabinets and microwave) + top_row: + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [0.9, 0.4, 0.92] + pos: [-0.85, -0.2, 1.85] + + # - name: cab_corner + # type: box + + # size: [0.4, 0.4, 0.92] + # align_to: shelves + # side: right + + # - name: cab_corner_2 + # type: box + + # size: [0.4, 0.3, 0.92] + # align_to: cab_corner + # side: front + # alignment: right + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.6, 0.6] + pos: [-1.675, -0.3, 0.35] + + - name: cab_middle + type: hinge_cabinet + size: [0.8, 0.6, 0.60] + align_to: bottom + alignment: front + panel_config: + handle_vpos: center + side: top + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + padding: [null, [-0.01, null], null] + align_to: cab_middle + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.45 + stack_fixtures: ["bottom", "cab_middle", "micro_housing"] + +island_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [4, -2.55] + group_z_rot: 3.1415 + + # Bottom row (counters and stoves) + bottom_row: + - name: island + type: counter + default_config_name: island + base_opening: [false, true] + overhang: 0 + + size: [2.25, 1, 0.92] + pos: [-0.8, 0.65, 0.46] + +stool_group: + group_origin: [0, 0] + group_z_rot: 3.1415 + group_pos: [4.8, -3.15] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.6, 0.5, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.5, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.6, 0.5, 0.5] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/coastal.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/coastal.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9ffacaa0e3a3abcbf92fbf0ea4f0940546f1e3c2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/coastal.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [shaker, dark_blue, handle_boxed, handle_brass] + shelves: light_wood_planks_shelves + cab_top: [divided_window, dark_blue, handle_boxed, handle_brass] + cab_top_small: [full_window_clear, dark_blue, handle_brass] +counter: + default: dark_blue_base_marble_top + island: dark_blue_base_marble_top +floor: flower_ceramic_tiles +wall: white_square_tiles + +# fixtures using models +sink: concrete_sink +stove: frigidaire_gas +microwave: hamilton_beach +oven: pack_1 +stovetop: pack_1_top_induc +hood: pack_2 +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +toaster: basic_popup_2 +paper_towel: holder_4 +stool: stool_1_1 +knife_block: knife_block_1 +utensil_rack: black_plastic +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/farmhouse.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/farmhouse.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c7e889b0bb3a98537a8b7449f6a6a06ff457e302 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/farmhouse.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [shaker, gray_wood_grain] + cab_top: [divided_window, gray_wood_grain] + cab_top_small: [full_window_clear, gray_wood_grain] + shelves: warm_white +counter: + default: gray_wood_base_marble_top + island: gray_wood_base_marble_top +floor: gray_wood +wall: white_bricks + +# fixtures using models +sink: concrete_sink +stove: frigidaire_gas +microwave: gray +oven: beko +stovetop: pack_1_top_induc +hood: pack_1 +fridge: full_height_doors +dishwasher: basic_stainless + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup_2 +knife_block: light_wood_2 +paper_towel: holder_4 +stool: rattan_stool +utensil_rack: metal +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/industrial.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/industrial.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7449082482a7d737ef736d89d598af3cedd72be3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/industrial.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [gray, shaker] + shelves: dark_wood_planks_shelves +counter: + default: gray_base_marble_top + island: gray_base_tiled_wood_top +floor: concrete_tiles +wall: red_bricks +openings_wall: default + +# fixtures using models +sink: concrete_sink +stove: basic_sleek_induc +microwave: pack_1 +oven: pack_1 +stovetop: sleek_silver_top_gas +hood: simple_silver +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +toaster: boxy +paper_towel: holder_2 +utensil_rack: metal +knife_block: light_wood_3 +stool: rattan_stool +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/mediterranean.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/mediterranean.yaml new file mode 100644 index 0000000000000000000000000000000000000000..752022347862fb68be8357fffa56b766bb2cab99 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/mediterranean.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: warm_wood_grain + cab_top: [divided_window, warm_wood_grain] + cab_top_small: [full_window_clear, warm_wood_grain] + shelves: gray +counter: + default: wood_base_dark_marble_top + island: cream_base_wood_parquet_top +floor: orange_tiles +wall: orange_square_tiles + +# fixtures using models +sink: 1_bin_wide_top_handle +stove: square_gas +microwave: hamilton_beach +oven: westerfeld +stovetop: sleek_silver_top_gas +hood: pack_2 +fridge: four_doors +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +toaster: boxy +knife_block: light_wood_2 +paper_towel: holder_4 +stool: rattan_stool +utensil_rack: black_plastic +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/modern_1.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/modern_1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4824d7e234594970533423211845bce2d87d3125 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/modern_1.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [slab, blue_gray, handle_dark_gray] + shelves: light_wood_parquet +counter: + default: blue_gray_base_white_top + island: blue_gray_base_white_top +floor: light_wood_2 +wall: marble + +# fixtures using models +sink: 2_bins_stainless +stove: square_gas +microwave: pack_1 +oven: pack_1 +stovetop: sleek_silver_top_gas +hood: pack_1 +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +paper_towel: holder_2 +stool: rattan_stool +toaster: vintage +knife_block: light_wood_3 +utensil_rack: metal_cg_2 +utensil_holder: holder_2 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/modern_2.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/modern_2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dce03ba708da9ce836c51204f4daba78c6df0fa0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/modern_2.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [dark_gray, handle_brass, handle_boxed] + cab_top: [full_window_blurred, dark_gray, handle_brass, handle_boxed] + cab_top_small: [full_window_blurred, dark_gray, handle_brass, handle_boxed] + shelves: wood_grain_shelves +counter: + default: white_base_marble_top_3 + island: white_base_marble_top_3 +floor: wood +wall: black_marble_tiles + +# fixtures using models +sink: 1_bin_storage_right_dark +stove: basic_sleek_induc +microwave: standard +oven: beko +stovetop: pack_1_top_gas +hood: tall_stainless +fridge: modern +dishwasher: basic_stainless + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +paper_towel: holder_2 +stool: stool_1_1 +toaster: fancy +knife_block: light_wood_2 +utensil_rack: metal_cg_2 +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/playground.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/playground.yaml new file mode 100644 index 0000000000000000000000000000000000000000..90b71d9944e922d60699980fb98724ca24921159 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/playground.yaml @@ -0,0 +1,30 @@ +# fixtures using primitive geoms +cabinet: + default: [gray, shaker] + shelves: dark_wood_planks_shelves +counter: + default: gray_base_marble_top + island: gray_base_tiled_wood_top +floor: concrete_tiles +wall: playground +openings_wall: default + +# fixtures using models +sink: concrete +stove: electric_range +microwave: standard +oven: samsung +stovetop: samsung_top_gas +hood: simple_silver +fridge: pack_2 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: default +paper_towel: default +utensil_rack: default +wall_accessory: default +box: default +window: default +framed_window: default diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/rustic.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/rustic.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e922cb739388c792579d4fe2b339ed8475b31982 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/rustic.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [light_green, shaker] + shelves: rustic_wood_shelves +counter: + default: green_base_wood_top + island: green_base_granite_top +floor: wood_3 +wall: wood_planks + +# fixtures using models +sink: concrete_sink +stove: square_gas +microwave: gray +oven: bosch +stovetop: sleek_silver_top_gas +hood: pack_2 +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup_2 +wall_accessory: default +knife_block: light_wood_3 +paper_towel: holder_2 +stool: stool_1_1 +utensil_rack: metal +utensil_holder: holder_1 +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/scandanavian.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/scandanavian.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6862e43ab0aae57ec789942119b4ec8ce87a2768 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/scandanavian.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [white, slab] + shelves: white +counter: + default: default + island: default +floor: light_wood_long +wall: white_tiles + +# fixtures using models +sink: white_sink +stove: frigidaire_gas +microwave: pack_1 +oven: westerfeld +stovetop: sleek_silver_top_gas +hood: simple_silver +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup +paper_towel: holder_2 +utensil_rack: metal +stool: stool_1_2 +knife_block: light_wood_3 +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/traditional_1.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/traditional_1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..397c56a916d833d04618486ed84e822aff304f85 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/traditional_1.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [raised, white] + cab_top: [divided_window, white] + cab_top_small: [raised, white] + shelves: warm_wood_parquet +counter: + default: white_base_marble_top + island: warm_wood_base_marble_top +floor: warm_wood +wall: varied_marble_tiles + +# fixtures using models +sink: 1_bin_wide_top_handle +stove: frigidaire_gas +microwave: standard +oven: gorenje +stovetop: pack_1_top_gas +hood: simple_silver +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +toaster: vintage +knife_block: light_wood_2 +paper_towel: holder_2 +stool: rattan_stool +utensil_rack: metal +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/traditional_2.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/traditional_2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..303a210dad0396e6a127cb53519b873b86778b2d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/traditional_2.yaml @@ -0,0 +1,33 @@ +# fixtures using primitive geoms +cabinet: + default: [raised, walnut_wood_grain, handle_dark_gray] + shelves: warm_wood_parquet +counter: + default: warm_wood_base_granite_top + island: warm_wood_base_granite_top +floor: wood_2 +wall: diamond_tiles + +# fixtures using models +sink: 1_bin_wide_top_handle +stove: frigidaire_gas +microwave: gray +oven: gorenje_dark +stovetop: pack_1_top_induc +hood: pack_2 +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +wall_accessory: default +knife_block: light_wood_3 +paper_towel: holder_4 +stool: stool_1_3 +utensil_rack: metal +utensil_holder: holder_3 +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/transitional_1.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/transitional_1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..46d43bc13e5b4ba6be2f61313decc6b0bb2b979b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/transitional_1.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [lighter_gray, shaker, handle_black, handle_boxed] + shelves: wood_grain_shelves_2 +counter: + default: white_base_marble_top_2 + island: white_base_marble_top_2 +floor: dark_wood_planks +wall: diamond_marble_parquet + +# fixtures using models +sink: white_sink +stove: basic_sleek_induc +microwave: standard +oven: beko +stovetop: pack_1_top_induc +hood: tall_stainless +fridge: modern +dishwasher: basic_stainless + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup +wall_accessory: default +knife_block: knife_block_1 +paper_towel: holder_2 +stool: stool_1_2 +utensil_rack: metal_cg_2 +utensil_holder: holder_2 +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/transitional_2.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/transitional_2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..465a1b1921e3a07fb479e5c6fdf1295b72fb1c24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/kitchen_styles/transitional_2.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: light_gray + cab_top: [full_window_clear, light_gray] + cab_top_small: [full_window_clear, light_gray] + shelves: dark_wood_planks_shelves +counter: + default: gray_base_marble_top_2 + island: white_base_marble_island +floor: dark_wood +wall: diamond_white_tiles + +# fixtures using models +sink: 1_bin_storage_right_dark +stove: square_gas +microwave: gray +oven: gorenje_dark +stovetop: sleek_silver_top_gas +hood: pack_1 +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +toaster: basic_popup_2 +knife_block: light_wood_3 +paper_towel: holder_4 +stool: stool_1_2 +utensil_rack: metal +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/cluttered_tabletop.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/cluttered_tabletop.yaml new file mode 100644 index 0000000000000000000000000000000000000000..81a77a073a54cfbb7db77be0092fa120f9e5bf4d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/cluttered_tabletop.yaml @@ -0,0 +1,100 @@ +# tabletop with distraction fixtures on the table + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +main_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 0 + + table: + - name: table + type: counter + default_config_name: table + + size: [1.22, 0.75, 0.92] + pos: [0, 0, 0.46] + + cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.61, 0.75, 0.84] + pos: [-0.305, 0, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [0.61, 0.75, 0.84] + align_to: stack_1 + side: right + + table_accessories: + - name: coffee_machine + type: coffee_machine + placement: + fixture: table_main_group + pos: [-1, 0] # place on left side of table + size: ["obj", 0.6] + rotation: 0 + margin: 0 + + - name: plant + type: plant + placement: + fixture: table_main_group + pos: [1, 1] + size: ["obj", 0.6] + rotation: 0 + margin: 0 + + - name: toaster + type: toaster + placement: + fixture: table_main_group + pos: [0, 1] + size: [1, "obj"] + rotation: 0 + margin: 0 + + - name: paper_towel + type: paper_towel + placement: + fixture: table_main_group + pos: [1, -1] + size: ["obj", 0.6] + rotation: 0 + margin: 0 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop.yaml new file mode 100644 index 0000000000000000000000000000000000000000..40077f6fe74e3cf4c9e6176fdd5ca2d2908ae455 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop.yaml @@ -0,0 +1,63 @@ +# scene with an empty tabletop + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +main_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 0 + + table: + - name: table + type: counter + default_config_name: table + + size: [1.22, 0.75, 0.92] + pos: [0, 0, 0.46] + + cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.61, 0.75, 0.84] + pos: [-0.305, 0, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [0.61, 0.75, 0.84] + align_to: stack_1 + side: right diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_cotrain.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_cotrain.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7494941b8855c8430194f9db5ea6d94947479383 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_cotrain.yaml @@ -0,0 +1,45 @@ +# scene with an empty tabletop + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +main_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 0 + + table: + - name: table + type: counter + default_config_name: table + + size: [1.2, 0.7, 1.00] + pos: [0, 0, 0.495] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_cabinet.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_cabinet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3b460666ac122d9ad00d1e624c9b2670d13b9754 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_cabinet.yaml @@ -0,0 +1,84 @@ +# tabletop scene with a microwave on the table + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +main_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 0 + + table: + - name: table + type: counter + default_config_name: table + + size: [1.22, 0.75, 0.92] + pos: [0, 0, 0.46] + + cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.61, 0.75, 0.84] + pos: [-0.305, 0, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [0.61, 0.75, 0.84] + align_to: stack_1 + side: right + + table_accessories: + - name: cabinet_tabletop + type: single_cabinet + size: [0.3, 0.3, 0.8] + placement: + fixture: table_main_group + # pos: [0.1, 0.2] + pos: [0, 0.05] + size: [0, 0] + rotation: 0 + margin: 0 + + - name: paper_towel + type: paper_towel + placement: + fixture: table_main_group + pos: [-1, -1] + size: ["obj", 0.6] + rotation: 0 + margin: 0 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_drawer.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_drawer.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4e2b21f2c43e2a941213cc086774e3cee4e1ba39 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_drawer.yaml @@ -0,0 +1,83 @@ +# tabletop scene with a microwave on the table + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +main_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 0 + + table: + - name: table + type: counter + default_config_name: table + + size: [1.22, 0.75, 0.92] + pos: [0, 0, 0.46] + + cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.61, 0.75, 0.84] + pos: [-0.305, 0, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [0.61, 0.75, 0.84] + align_to: stack_1 + side: right + + table_accessories: + - name: drawer_tabletop + type: drawer + size: [0.45, 0.30, 0.25] + placement: + fixture: table_main_group + pos: [0.4, 0.4] + size: [0, 0] + rotation: 0 + margin: 0 + + - name: paper_towel + type: paper_towel + placement: + fixture: table_main_group + pos: [-1, -1] + size: ["obj", 0.6] + rotation: 0 + margin: 0 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_microwave.yaml b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_microwave.yaml new file mode 100644 index 0000000000000000000000000000000000000000..22f7d671bf57e06d0d47e9e247abe01a10235e40 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/assets/scenes/tabletop_layouts/tabletop_with_microwave.yaml @@ -0,0 +1,86 @@ +# tabletop scene with a microwave on the table + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +main_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 0 + + table: + - name: table + type: counter + default_config_name: table + + size: [1.22, 0.75, 0.92] + pos: [0, 0, 0.46] + + cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.61, 0.75, 0.84] + pos: [-0.305, 0, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [0.61, 0.75, 0.84] + align_to: stack_1 + side: right + + table_accessories: + - name: microwave + type: microwave + size: [0.35, 0.4, 0.3] + placement: + fixture: table_main_group + # pos: [0.3, 0.4] + pos: [0.3, 0.2] + # size: [0.8, 0.5] + size: [0, 0] + rotation: 0 + margin: 0 + + + - name: paper_towel + type: paper_towel + placement: + fixture: table_main_group + pos: [-1, -1] + size: ["obj", 0.6] + rotation: 0 + margin: 0 diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/__init__.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1ac011def690701e1ba67ab06200f8a40600d8cc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/__init__.py @@ -0,0 +1,6 @@ +from .box_pattern_object import BoxPatternObject +from .needle import NeedleObject +from .ring_tripod import RingTripodObject +from .bin import Bin +from .lid import Lid +from .pot_with_handles import PotWithHandlesObject diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/bin.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/bin.py new file mode 100644 index 0000000000000000000000000000000000000000..777ba77ff1bf1942635711c475c7404a99af3a1c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/bin.py @@ -0,0 +1,211 @@ +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.models.objects import CompositeObject +from robosuite.utils.mjcf_utils import CustomMaterial, add_to_dict + + +class Bin(CompositeObject): + """ + Generates a four-walled bin container with an open top. + Args: + name (str): Name of this Bin object + bin_size (3-array): (x,y,z) full size of bin + wall_thickness (float): How thick to make walls of bin + transparent_walls (bool): If True, walls will be semi-translucent + friction (3-array or None): If specified, sets friction values for this bin. None results in default values + density (float): Density value to use for all geoms. Defaults to 1000 + use_texture (bool): If true, geoms will be defined by realistic textures and rgba values will be ignored + rgba (4-array or None): If specified, sets rgba values for all geoms. None results in default values + material: If specified, use this material + upside_down (bool): if True, construct and initialize the Bin so the bottom geom is at the top + """ + + def __init__( + self, + name, + bin_size=(0.3, 0.3, 0.15), + wall_thickness=0.01, + transparent_walls=True, + friction=None, + density=1000.0, + use_texture=True, + rgba=(0.2, 0.1, 0.0, 1.0), + material=None, + upside_down=False, + add_second_base=False, + transparent_base=False, + ): + # Set name + self._name = name + + # Set object attributes + self.bin_size = np.array(bin_size) + self.wall_thickness = wall_thickness + self.transparent_walls = transparent_walls + self.friction = friction if friction is None else np.array(friction) + self.density = density + self.use_texture = use_texture + self.rgba = rgba + self.bin_mat_name = "dark_wood_mat" + + # if box should be constructed and initialized upside down + self.upside_down = upside_down + + # if box should have a second base (so it will be a closed box) + self.add_second_base = add_second_base + if self.add_second_base: + assert not self.upside_down + + # if base(s) should be transparent + self.transparent_base = transparent_base + + self.has_material = material is not None + if self.has_material: + assert isinstance(material, CustomMaterial) + self.material = material + self.bin_mat_name = self.material.mat_attrib["name"] + else: + # default material + tex_attrib = { + "type": "cube", + } + mat_attrib = { + "texrepeat": "3 3", + "specular": "0.4", + "shininess": "0.1", + } + bin_mat = CustomMaterial( + texture="WoodDark", + tex_name="dark_wood", + mat_name=self.bin_mat_name, + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + self.material = bin_mat + + # Element references + self._base_geom = "base" + if self.add_second_base: + self._second_base_geom = "base2" + + # Other private attributes + self._important_sites = {} + + # Create dictionary of values to create geoms for composite object and run super init + super().__init__(**self._get_geom_attrs()) + + # Define materials we want to use for this object + self.append_material(self.material) + + def _get_geom_attrs(self): + """ + Creates geom elements that will be passed to superclass CompositeObject constructor + Returns: + dict: args to be used by CompositeObject to generate geoms + """ + # Initialize dict of obj args that we'll pass to the CompositeObject constructor + base_args = { + "total_size": self.bin_size / 2.0, + "name": self.name, + "locations_relative_to_center": True, + "obj_types": "all", + "density": self.density, + } + obj_args = {} + + # Base(s) + base_geom_loc = (0, 0, -(self.bin_size[2] - self.wall_thickness) / 2) + if self.upside_down: + base_geom_loc = ( + base_geom_loc[0], + base_geom_loc[1], + -1.0 * base_geom_loc[2], + ) + if self.transparent_base: + base_rgba = (1.0, 1.0, 1.0, 0.3) + base_mat = None + else: + base_rgba = None if self.use_texture else self.rgba + base_mat = self.bin_mat_name if self.use_texture else None + + base_geom_names = [self._base_geom] + base_geom_locs = [base_geom_loc] + if self.add_second_base: + base_geom_names.append(self._second_base_geom) + base_geom_locs.append( + (base_geom_loc[0], base_geom_loc[1], -1.0 * base_geom_loc[2]) + ) + + for base_g_name, base_g_loc in zip(base_geom_names, base_geom_locs): + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=base_g_loc, + geom_quats=(1, 0, 0, 0), + geom_sizes=( + np.array((self.bin_size[0], self.bin_size[1], self.wall_thickness)) + - np.array((self.wall_thickness, self.wall_thickness, 0)) + ) + / 2, + geom_names=base_g_name, + geom_rgbas=base_rgba, + geom_materials=base_mat, + geom_frictions=self.friction, + ) + + # Walls + x_vals = np.array( + [ + 0, + -(self.bin_size[0] - self.wall_thickness) / 2, + 0, + (self.bin_size[0] - self.wall_thickness) / 2, + ] + ) + y_vals = np.array( + [ + -(self.bin_size[1] - self.wall_thickness) / 2, + 0, + (self.bin_size[1] - self.wall_thickness) / 2, + 0, + ] + ) + w_vals = np.array( + [self.bin_size[0], self.bin_size[1], self.bin_size[0], self.bin_size[1]] + ) + r_vals = np.array([np.pi / 2, 0, -np.pi / 2, np.pi]) + if self.transparent_walls: + wall_rgba = (1.0, 1.0, 1.0, 0.3) + wall_mat = None + else: + wall_rgba = None if self.use_texture else self.rgba + wall_mat = self.bin_mat_name if self.use_texture else None + for i, (x, y, w, r) in enumerate(zip(x_vals, y_vals, w_vals, r_vals)): + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=(x, y, 0), + geom_quats=T.convert_quat( + T.axisangle2quat(np.array([0, 0, r])), to="wxyz" + ), + geom_sizes=(self.wall_thickness / 2, w / 2, self.bin_size[2] / 2), + geom_names=f"wall{i}", + geom_rgbas=wall_rgba, + geom_materials=wall_mat, + geom_frictions=self.friction, + ) + + # Add back in base args and site args + obj_args.update(base_args) + + # Return this dict + return obj_args + + @property + def base_geoms(self): + """ + Returns: + list of str: geom names corresponding to bin base + """ + return [self.correct_naming(self._base_geom)] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/box_pattern_object.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/box_pattern_object.py new file mode 100644 index 0000000000000000000000000000000000000000..7affdf6c057c36545c09dbae48e673fe5c5a919d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/box_pattern_object.py @@ -0,0 +1,126 @@ +import numpy as np + +from robosuite.models.objects import CompositeObject +from robosuite.utils.mjcf_utils import add_to_dict +import robosuite.utils.transform_utils as T + + +class BoxPatternObject(CompositeObject): + """ + Generates shapes by using a pattern of unit-size boxes. + + Args: + name (str): Name of this Needle object + """ + + def __init__( + self, + name, + unit_size, + pattern, + rgba=None, + material=None, + density=100.0, + # solref=[0.02, 1.], + # solimp=[0.9, 0.95, 0.001], + friction=None, + ): + """ + Args: + unit_size (3d array / list): size of each unit block in each dimension + + pattern (3d array / list): array of normalized sizes specifying the + geometry of the shape. A "0" indicates the absence of a cube and + a "1" indicates the presence of a full unit block. The dimensions + correspond to z, x, and y respectively. + """ + self._name = name + self.rgba = rgba + self.material = material + self.density = density + self.friction = friction + + # number of blocks in z, x, and y + self.pattern = np.array(pattern) + self.nz, self.nx, self.ny = self.pattern.shape + self.unit_size = unit_size + self.total_size = [ + self.nx * unit_size[0], + self.ny * unit_size[1], + self.nz * unit_size[2], + ] + + # Other private attributes + self._important_sites = {} + + # Create dictionary of values to create geoms for composite object and run super init + super().__init__(**self._get_geom_attrs()) + + # Define materials we want to use for this object + if self.material is not None: + self.append_material(self.material) + + def _get_geom_attrs(self): + """ + Creates geom elements that will be passed to superclass CompositeObject constructor + + Returns: + dict: args to be used by CompositeObject to generate geoms + """ + # Initialize dict of obj args that we'll pass to the CompositeObject constructor + base_args = { + "total_size": self.total_size, + "name": self.name, + "locations_relative_to_center": False, + "obj_types": "all", + "density": self.density, + } + obj_args = {} + + geom_locations = [] + geom_sizes = [] + geom_names = [] + nz, nx, ny = self.pattern.shape + for k in range(nz): + for i in range(nx): + for j in range(ny): + if self.pattern[k, i, j] > 0: + geom_sizes.append( + [ + self.unit_size[0], + self.unit_size[1], + self.unit_size[2], + ] + ) + geom_locations.append( + [ + i * 2.0 * self.unit_size[0], + j * 2.0 * self.unit_size[1], + k * 2.0 * self.unit_size[2], + ] + ) + geom_names.append("{}_{}_{}".format(k, i, j)) + + # geom_rgbas = [rgba for _ in geom_locations] + # geom_frictions = [friction for _ in geom_locations] + for i in range(len(geom_locations)): + add_to_dict( + dic=obj_args, + geom_types="box", + # needle geom needs to be offset from boundary in (x, z) + geom_locations=tuple(geom_locations[i]), + geom_quats=(1, 0, 0, 0), + geom_sizes=tuple(geom_sizes[i]), + geom_names=geom_names[i], + geom_rgbas=self.rgba, + geom_materials=self.material.name + if self.material is not None + else None, + geom_frictions=None, + ) + + # Add back in base args and site args + obj_args.update(base_args) + + # Return this dict + return obj_args diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/lid.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/lid.py new file mode 100644 index 0000000000000000000000000000000000000000..3eb602bd9308bbe387e4648939d61c00c32f5520 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/lid.py @@ -0,0 +1,136 @@ +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.models.objects import CompositeObject +from robosuite.utils.mjcf_utils import CustomMaterial, add_to_dict + + +class Lid(CompositeObject): + """ + Generates a square lid with a simple handle. + Args: + name (str): Name of this Lid object + lid_size (3-array): (length, width, thickness) of lid + handle_size (3-array): (thickness, length, height) of handle + transparent (bool): If True, lid will be semi-translucent + friction (3-array or None): If specified, sets friction values for this lid. None results in default values + density (float): Density value to use for all geoms. Defaults to 1000 + use_texture (bool): If true, geoms will be defined by realistic textures and rgba values will be ignored + rgba (4-array or None): If specified, sets rgba values for all geoms. None results in default values + """ + + def __init__( + self, + name, + lid_size=(0.3, 0.3, 0.01), + handle_size=(0.02, 0.08, 0.03), + transparent=True, + friction=None, + density=250.0, + use_texture=True, + rgba=(0.2, 0.1, 0.0, 1.0), + ): + # Set name + self._name = name + + # Set object attributes + self.lid_size = np.array(lid_size) + self.handle_size = np.array(handle_size) + self.transparent = transparent + self.friction = friction if friction is None else np.array(friction) + self.density = density + self.use_texture = use_texture + self.rgba = rgba + self.lid_mat_name = "dark_wood_mat" + + # Element references + self._handle_geom = "handle" + + # Other private attributes + self._important_sites = {} + + # Create dictionary of values to create geoms for composite object and run super init + super().__init__(**self._get_geom_attrs()) + + # Define materials we want to use for this object + tex_attrib = { + "type": "cube", + } + mat_attrib = { + "texrepeat": "3 3", + "specular": "0.4", + "shininess": "0.1", + } + lid_mat = CustomMaterial( + texture="WoodDark", + tex_name="dark_wood", + mat_name=self.lid_mat_name, + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + self.append_material(lid_mat) + + def _get_geom_attrs(self): + """ + Creates geom elements that will be passed to superclass CompositeObject constructor + Returns: + dict: args to be used by CompositeObject to generate geoms + """ + full_height = self.lid_size[2] + self.handle_size[2] + full_size = np.array([self.lid_size[0], self.lid_size[1], full_height]) + # Initialize dict of obj args that we'll pass to the CompositeObject constructor + base_args = { + "total_size": full_size / 2.0, + "name": self.name, + "locations_relative_to_center": True, + "obj_types": "all", + } + obj_args = {} + + # Top + if self.transparent: + top_rgba = (1.0, 1.0, 1.0, 0.3) + top_mat = None + else: + top_rgba = None if self.use_texture else self.rgba + top_mat = self.lid_mat_name if self.use_texture else None + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=(0, 0, (-full_size[2] + self.lid_size[2]) / 2), + geom_quats=(1, 0, 0, 0), + geom_sizes=np.array((full_size[0], full_size[1], self.lid_size[2])) / 2, + geom_names="top", + geom_rgbas=top_rgba, + geom_materials=top_mat, + geom_frictions=self.friction, + density=self.density, + ) + + # Handle + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=(0, 0, (full_size[2] - self.handle_size[2]) / 2), + geom_quats=(1, 0, 0, 0), + geom_sizes=self.handle_size / 2, + geom_names=self._handle_geom, + geom_rgbas=None if self.use_texture else self.rgba, + geom_materials=self.lid_mat_name if self.use_texture else None, + geom_frictions=self.friction, + density=self.density * 2, + ) + + # Add back in base args and site args + obj_args.update(base_args) + + # Return this dict + return obj_args + + @property + def handle_geoms(self): + """ + Returns: + list of str: geom names corresponding to lid handle + """ + return [self.correct_naming(self._handle_geom)] diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/needle.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/needle.py new file mode 100644 index 0000000000000000000000000000000000000000..9dc6bb1fea50a76ba8c681643354596a7676e797 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/needle.py @@ -0,0 +1,109 @@ +import numpy as np + +from robosuite.models.objects import CompositeObject +from robosuite.utils.mjcf_utils import add_to_dict, CustomMaterial +import robosuite.utils.transform_utils as T + + +class NeedleObject(CompositeObject): + """ + Generates a needle with a handle (used in Threading task) + + Args: + name (str): Name of this Needle object + """ + + def __init__( + self, + name, + ): + + ### TODO: make this object more general (with more args and configuration options) later ### + + # Set object attributes + self._name = name + self.needle_mat_name = "darkwood_mat" + + # Other private attributes + self._important_sites = {} + + # Create dictionary of values to create geoms for composite object and run super init + super().__init__(**self._get_geom_attrs()) + + # Define materials we want to use for this object + tex_attrib = { + "type": "cube", + } + mat_attrib = { + "texrepeat": "1 1", + "specular": "0.4", + "shininess": "0.1", + } + needle_mat = CustomMaterial( + texture="WoodDark", + tex_name="darkwood", + mat_name="darkwood_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + self.append_material(needle_mat) + + def _get_geom_attrs(self): + """ + Creates geom elements that will be passed to superclass CompositeObject constructor + + Returns: + dict: args to be used by CompositeObject to generate geoms + """ + # Initialize dict of obj args that we'll pass to the CompositeObject constructor + base_args = { + "total_size": [0.02, 0.08, 0.02], + "name": self.name, + "locations_relative_to_center": False, + "obj_types": "all", + "density": 100.0, + } + obj_args = {} + + # make a skinny needle object with a large handle + needle_size = [0.005, 0.06, 0.005] + handle_size = [0.02, 0.02, 0.02] + + # Needle + add_to_dict( + dic=obj_args, + geom_types="box", + # needle geom needs to be offset from boundary in (x, z) + geom_locations=( + (handle_size[0] - needle_size[0]), + 0.0, + (handle_size[2] - needle_size[2]), + ), + geom_quats=(1, 0, 0, 0), + geom_sizes=tuple(needle_size), + geom_names="needle", + geom_rgbas=None, + geom_materials=self.needle_mat_name, + # make the needle low friction to ensure easy insertion + geom_frictions=(0.3, 5e-3, 1e-4), + ) + + # Handle + add_to_dict( + dic=obj_args, + geom_types="box", + # handle geom needs to be offset in y + geom_locations=(0.0, 2.0 * needle_size[1], 0.0), + geom_quats=(1, 0, 0, 0), + geom_sizes=tuple(handle_size), + geom_names="handle", + geom_rgbas=None, + geom_materials=self.needle_mat_name, + geom_frictions=None, + ) + + # Add back in base args and site args + obj_args.update(base_args) + + # Return this dict + return obj_args diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/pot_with_handles.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/pot_with_handles.py new file mode 100644 index 0000000000000000000000000000000000000000..d097cb515a2eddb0197fddc136418b60157ea448 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/pot_with_handles.py @@ -0,0 +1,404 @@ +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.models.objects import CompositeObject +from robosuite.utils.mjcf_utils import ( + BLUE, + GREEN, + RED, + CustomMaterial, + add_to_dict, + array_to_string, +) + + +class PotWithHandlesObject(CompositeObject): + """ + Generates the Pot object with side handles (used in TwoArmLift) + + Args: + name (str): Name of this Pot object + + body_half_size (3-array of float): If specified, defines the (x,y,z) half-dimensions of the main pot + body. Otherwise, defaults to [0.07, 0.07, 0.07] + + handle_radius (float): Determines the pot handle radius + + handle_length (float): Determines the pot handle length + + handle_width (float): Determines the pot handle width + + handle_friction (float): Friction value to use for pot handles. Defauls to 1.0 + + density (float): Density value to use for all geoms. Defaults to 1000 + + use_texture (bool): If true, geoms will be defined by realistic textures and rgba values will be ignored + + rgba_body (4-array or None): If specified, sets pot body rgba values + + rgba_handle_0 (4-array or None): If specified, sets handle 0 rgba values + + rgba_handle_1 (4-array or None): If specified, sets handle 1 rgba values + + solid_handle (bool): If true, uses a single geom to represent the handle + + thickness (float): How thick to make the pot body walls + """ + + def __init__( + self, + name, + body_half_size=(0.07, 0.07, 0.07), + handle_radius=0.01, + handle_length=0.09, + handle_width=0.09, + handle_friction=1.0, + density=1000, + use_texture=True, + rgba_body=None, + rgba_handle_0=None, + rgba_handle_1=None, + solid_handle=False, + thickness=0.01, # For body + ): + # Set name + self._name = name + + # Set object attributes + self.body_half_size = np.array(body_half_size) + self.thickness = thickness + self.handle_radius = handle_radius + self.handle_length = handle_length + self.handle_width = handle_width + self.handle_friction = handle_friction + self.density = density + self.use_texture = use_texture + self.rgba_body = np.array(rgba_body) if rgba_body else RED + self.rgba_handle_0 = np.array(rgba_handle_0) if rgba_handle_0 else GREEN + self.rgba_handle_1 = np.array(rgba_handle_1) if rgba_handle_1 else BLUE + self.solid_handle = solid_handle + + # Element references to be filled when generated + self._handle0_geoms = None + self._handle1_geoms = None + self.pot_base = None + + # Other private attributes + self._important_sites = {} + + # Create dictionary of values to create geoms for composite object and run super init + super().__init__(**self._get_geom_attrs()) + + # Define materials we want to use for this object + tex_attrib = { + "type": "cube", + } + mat_attrib = { + "texrepeat": "1 1", + "specular": "0.4", + "shininess": "0.1", + } + redwood = CustomMaterial( + texture="WoodRed", + tex_name="redwood", + mat_name="pot_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + greenwood = CustomMaterial( + texture="WoodGreen", + tex_name="greenwood", + mat_name="handle0_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + bluewood = CustomMaterial( + texture="WoodBlue", + tex_name="bluewood", + mat_name="handle1_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + self.append_material(redwood) + self.append_material(greenwood) + self.append_material(bluewood) + + def _get_geom_attrs(self): + """ + Creates geom elements that will be passed to superclass CompositeObject constructor + + Returns: + dict: args to be used by CompositeObject to generate geoms + """ + full_size = np.array( + ( + self.body_half_size, + self.body_half_size + self.handle_length * 2, + self.body_half_size, + ) + ) + # Initialize dict of obj args that we'll pass to the CompositeObject constructor + base_args = { + "total_size": full_size / 2.0, + "name": self.name, + "locations_relative_to_center": True, + "obj_types": "all", + } + site_attrs = [] + obj_args = {} + + # Initialize geom lists + self._handle0_geoms = [] + self._handle1_geoms = [] + + # Add main pot body + # Base geom + name = f"base" + self.pot_base = [name] + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=(0, 0, -self.body_half_size[2] + self.thickness / 2), + geom_quats=(1, 0, 0, 0), + geom_sizes=np.array( + [self.body_half_size[0], self.body_half_size[1], self.thickness / 2] + ), + geom_names=name, + geom_rgbas=None if self.use_texture else self.rgba_body, + geom_materials="pot_mat" if self.use_texture else None, + geom_frictions=None, + density=self.density, + ) + + # Walls + x_off = np.array( + [ + 0, + -(self.body_half_size[0] - self.thickness / 2), + 0, + self.body_half_size[0] - self.thickness / 2, + ] + ) + y_off = np.array( + [ + -(self.body_half_size[1] - self.thickness / 2), + 0, + self.body_half_size[1] - self.thickness / 2, + 0, + ] + ) + w_vals = np.array( + [ + self.body_half_size[0], + self.body_half_size[1], + self.body_half_size[0], + self.body_half_size[1], + ] + ) + r_vals = np.array([np.pi / 2, 0, -np.pi / 2, np.pi]) + for i, (x, y, w, r) in enumerate(zip(x_off, y_off, w_vals, r_vals)): + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=(x, y, 0), + geom_quats=T.convert_quat( + T.axisangle2quat(np.array([0, 0, r])), to="wxyz" + ), + geom_sizes=np.array([self.thickness / 2, w, self.body_half_size[2]]), + geom_names=f"body{i}", + geom_rgbas=None if self.use_texture else self.rgba_body, + geom_materials="pot_mat" if self.use_texture else None, + geom_frictions=None, + density=self.density, + ) + + # Add handles + main_bar_size = np.array( + [ + self.handle_width / 2 + self.handle_radius, + self.handle_radius, + self.handle_radius, + ] + ) + side_bar_size = np.array( + [self.handle_radius, self.handle_length / 2, self.handle_radius] + ) + handle_z = self.body_half_size[2] - self.handle_radius + for i, (g_list, handle_side, rgba) in enumerate( + zip( + [self._handle0_geoms, self._handle1_geoms], + [1.0, -1.0], + [self.rgba_handle_0, self.rgba_handle_1], + ) + ): + handle_center = np.array( + ( + 0, + handle_side * (self.body_half_size[1] + self.handle_length), + handle_z, + ) + ) + # Solid handle case + if self.solid_handle: + handle_center = np.array( + ( + 0, + handle_side * (self.body_half_size[1] + self.handle_length / 2), + handle_z, + ) + ) + name = f"handle{i}" + g_list.append(name) + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=handle_center, + geom_quats=(1, 0, 0, 0), + geom_sizes=np.array( + [ + self.handle_width / 2, + self.handle_length / 2, + self.handle_radius, + ] + ), + geom_names=name, + geom_rgbas=None if self.use_texture else rgba, + geom_materials=f"handle{i}_mat" if self.use_texture else None, + geom_frictions=(self.handle_friction, 0.005, 0.0001), + density=self.density, + ) + # Hollow handle case + else: + # Center bar + name = f"handle{i}_c" + g_list.append(name) + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=handle_center, + geom_quats=(1, 0, 0, 0), + geom_sizes=main_bar_size, + geom_names=name, + geom_rgbas=None if self.use_texture else rgba, + geom_materials=f"handle{i}_mat" if self.use_texture else None, + geom_frictions=(self.handle_friction, 0.005, 0.0001), + density=self.density, + ) + # Side bars + for bar_side, suffix in zip([-1.0, 1.0], ["-", "+"]): + name = f"handle{i}_{suffix}" + g_list.append(name) + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=( + bar_side * self.handle_width / 2, + handle_side + * (self.body_half_size[1] + self.handle_length / 2), + handle_z, + ), + geom_quats=(1, 0, 0, 0), + geom_sizes=side_bar_size, + geom_names=name, + geom_rgbas=None if self.use_texture else rgba, + geom_materials=f"handle{i}_mat" if self.use_texture else None, + geom_frictions=(self.handle_friction, 0.005, 0.0001), + density=self.density, + ) + # Add relevant site + handle_site = self.get_site_attrib_template() + handle_name = f"handle{i}" + handle_site.update( + { + "name": handle_name, + "pos": array_to_string( + handle_center - handle_side * np.array([0, 0.005, 0]) + ), + "size": "0.005", + "rgba": rgba, + } + ) + site_attrs.append(handle_site) + # Add to important sites + self._important_sites[f"handle{i}"] = self.naming_prefix + handle_name + + # Add pot body site + pot_site = self.get_site_attrib_template() + center_name = "center" + pot_site.update( + { + "name": center_name, + "size": "0.005", + } + ) + site_attrs.append(pot_site) + # Add to important sites + self._important_sites["center"] = self.naming_prefix + center_name + + # Add back in base args and site args + obj_args.update(base_args) + obj_args["sites"] = site_attrs # All sites are part of main (top) body + + # Return this dict + return obj_args + + @property + def handle_distance(self): + + """ + Calculates how far apart the handles are + + Returns: + float: handle distance + """ + return self.body_half_size[1] * 2 + self.handle_length * 2 + + @property + def handle0_geoms(self): + """ + Returns: + list of str: geom names corresponding to handle0 (green handle) + """ + return self.correct_naming(self._handle0_geoms) + + @property + def handle1_geoms(self): + """ + Returns: + list of str: geom names corresponding to handle1 (blue handle) + """ + return self.correct_naming(self._handle1_geoms) + + @property + def handle_geoms(self): + """ + Returns: + list of str: geom names corresponding to both handles + """ + return self.handle0_geoms + self.handle1_geoms + + @property + def important_sites(self): + """ + Returns: + dict: In addition to any default sites for this object, also provides the following entries + + :`'handle0'`: Name of handle0 location site + :`'handle1'`: Name of handle1 location site + """ + # Get dict from super call and add to it + dic = super().important_sites + dic.update(self._important_sites) + return dic + + @property + def bottom_offset(self): + return np.array([0, 0, -1 * self.body_half_size[2]]) + + @property + def top_offset(self): + return np.array([0, 0, self.body_half_size[2]]) + + @property + def horizontal_radius(self): + return np.sqrt(2) * (max(self.body_half_size) + self.handle_length) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/ring_tripod.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/ring_tripod.py new file mode 100644 index 0000000000000000000000000000000000000000..11c9079b752d02c7f4ba3f9dd9fc9dbb7cbf33ef --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite/ring_tripod.py @@ -0,0 +1,200 @@ +import numpy as np + +from robosuite.models.objects import CompositeObject +from robosuite.utils.mjcf_utils import add_to_dict +from robosuite.utils.mjcf_utils import CustomMaterial +import robosuite.utils.transform_utils as T + + +class RingTripodObject(CompositeObject): + """ + Generates a tripod base with a small ring for threading a needle through it (used in Threading task) + + Args: + name (str): Name of this RingTripod object + """ + + def __init__( + self, + name, + ): + + ### TODO: make this object more general (with more args and configuration options) later ### + + # Set object attributes + self._name = name + self.tripod_mat_name = "lightwood_mat" + + # Other private attributes + self._important_sites = {} + + # Create dictionary of values to create geoms for composite object and run super init + super().__init__(**self._get_geom_attrs()) + + # Define materials we want to use for this object + tex_attrib = { + "type": "cube", + } + mat_attrib = { + "texrepeat": "1 1", + "specular": "0.4", + "shininess": "0.1", + } + tripod_mat = CustomMaterial( + texture="WoodLight", + tex_name="lightwood", + mat_name="lightwood_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + self.append_material(tripod_mat) + + def _get_geom_attrs(self): + """ + Creates geom elements that will be passed to superclass CompositeObject constructor + + Returns: + dict: args to be used by CompositeObject to generate geoms + """ + # Initialize dict of obj args that we'll pass to the CompositeObject constructor + total_size = (0.05, 0.05, 0.1) + base_args = { + "total_size": total_size, + "name": self.name, + "locations_relative_to_center": False, + "obj_types": "all", + "density": 100.0, + # NOTE: this lower value of solref allows the thin hole wall to avoid penetration through it + "solref": (0.02, 1.0), + "solimp": (0.9, 0.95, 0.001), + } + obj_args = {} + + # pattern for threading ring + unit_size = [0.005, 0.002, 0.002] + pattern = np.ones((6, 1, 6)) + for i in range(1, 5): + pattern[i][0][1:5] = np.zeros(4) + ring_size = [ + unit_size[0] * pattern.shape[1], + unit_size[1] * pattern.shape[2], + unit_size[2] * pattern.shape[0], + ] + self.ring_size = np.array(ring_size) + + # ring offset for where the ring is located relative to the (0, 0, 0) corner + ring_offset = [ + total_size[0] - ring_size[0], + total_size[1] - ring_size[1], + 2.0 * (total_size[2] - ring_size[2]), + ] + + # RING-GEOMS: use the pattern to instantiate geoms corresponding to the threading ring + nz, nx, ny = pattern.shape + self.num_ring_geoms = 0 + for k in range(nz): + for i in range(nx): + for j in range(ny): + if pattern[k, i, j] > 0: + add_to_dict( + dic=obj_args, + geom_types="box", + # needle geom needs to be offset from boundary in (x, z) + geom_locations=( + (i * 2.0 * unit_size[0]) + ring_offset[0], + (j * 2.0 * unit_size[1]) + ring_offset[1], + (k * 2.0 * unit_size[2]) + ring_offset[2], + ), + geom_quats=(1, 0, 0, 0), + geom_sizes=tuple(unit_size), + geom_names="ring_{}".format(self.num_ring_geoms), + geom_rgbas=None, + geom_materials=self.tripod_mat_name, + # make the ring low friction to ensure easy insertion + geom_frictions=(0.3, 5e-3, 1e-4), + ) + self.num_ring_geoms += 1 + + # TRIPOD-GEOMS: legs of the tripod + tripod_capsule_r = 0.01 + tripod_capsule_h = 0.03 + tripod_geom_locations = [ + (0.0, 0.0, 0.0), + (0.0, 2.0 * total_size[1] - 2.0 * tripod_capsule_r, 0.0), + ( + 2.0 * total_size[0] - 2.0 * tripod_capsule_r, + total_size[1] - tripod_capsule_r, + 0.0, + ), + ] + # rotate the legs to resemble a tripod + tripod_center = np.array([total_size[0], total_size[1], 0.0]) + xy_offset = np.array([tripod_capsule_r, tripod_capsule_r, 0.0]) + rotation_angle = -np.pi / 6.0 # 30 degrees + tripod_geom_quats = [] + for i in range(3): + capsule_loc = np.array(tripod_geom_locations[i]) + xy_offset + capsule_loc[2] = 0.0 # only care about location in x-y plane + vec_to_center = tripod_center - capsule_loc + vec_to_center = vec_to_center / np.linalg.norm(vec_to_center) + # cross-product with z unit vector to get vector to rotate about + rot_vec = np.cross(vec_to_center, np.array([0.0, 0.0, 1.0])) + rot_quat = T.mat2quat( + T.rotation_matrix(angle=rotation_angle, direction=rot_vec) + ) + tripod_geom_quats.append(T.convert_quat(rot_quat, to="wxyz")) + + for i in range(3): + add_to_dict( + dic=obj_args, + geom_types="capsule", + geom_locations=tripod_geom_locations[i], + geom_quats=tripod_geom_quats[i], + geom_sizes=(tripod_capsule_r, tripod_capsule_h), + geom_names="tripod_{}".format(i), + geom_rgbas=None, + geom_materials=self.tripod_mat_name, + geom_frictions=None, + ) + + # POST-GEOMS: mounted base + post + base_thickness = 0.005 + post_size = 0.005 + post_geom_sizes = [ + (total_size[0], total_size[1], base_thickness), + ( + post_size, + post_size, + total_size[2] + - ring_size[2] + - base_thickness + - tripod_capsule_r + - tripod_capsule_h, + ), + ] + post_geom_locations = [ + (0.0, 0.0, 2.0 * (tripod_capsule_r + tripod_capsule_h)), + ( + total_size[0] - post_size, + total_size[1] - post_size, + 2.0 * (tripod_capsule_r + tripod_capsule_h + base_thickness), + ), + ] + for i in range(2): + add_to_dict( + dic=obj_args, + geom_types="box", + geom_locations=post_geom_locations[i], + geom_quats=(1, 0, 0, 0), + geom_sizes=post_geom_sizes[i], + geom_names="post_{}".format(i), + geom_rgbas=None, + geom_materials=self.tripod_mat_name, + geom_frictions=None, + ) + + # Add back in base args and site args + obj_args.update(base_args) + + # Return this dict + return obj_args diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/__init__.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..dcea55930782409ac0c9dc2ba09a1b4432fd5e58 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/__init__.py @@ -0,0 +1,8 @@ +from .cup import CupObject +from .coffee_machine import CoffeeMachineObject +from .stacked_cylinder import StackedCylinderObject +from .inverse_stacked_cylinder import InverseStackedCylinderObject +from .stacked_box import StackedBoxObject +from .sliding_box import SlidingBoxObject +from .bin_with_handles import BinWithHandles +from .spray_bottle import SprayBottleObject diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/bin_with_handles.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/bin_with_handles.py new file mode 100644 index 0000000000000000000000000000000000000000..ef35b5e9f2f0a3e1615572596b399f9c1d6c6cdd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/bin_with_handles.py @@ -0,0 +1,162 @@ +from robosuite.models.objects import CompositeBodyObject, BoxObject, Bin +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class BinWithHandles(CompositeBodyObject): + """ + Bin with simple square handles on each side. + """ + + def __init__( + self, + name, + bin_size, + bin_wall_thickness, + bin_transparent_walls, + bin_upside_down, + center_handle_size, + adjacent_handle_size, + joints="default", + rgba=(0.2, 0.1, 0.0, 1.0), + material=None, + density=1000.0, + friction=None, + ): + + # Object properties + + # FULL size of bin + self.bin_size = list(bin_size) + self.bin_wall_thickness = bin_wall_thickness + self.bin_transparent_walls = bin_transparent_walls + self.bin_upside_down = bin_upside_down + + # half-sizes of box geom used for center part of handle (which you grab) + self.center_handle_size = list(center_handle_size) + + # half-sizes of box geoms used for adjacent parts of handle (not grabbed) + self.adjacent_handle_size = list(adjacent_handle_size) + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # bin + self.bin = Bin( + name="bin", + bin_size=self.bin_size, + wall_thickness=self.bin_wall_thickness, + transparent_walls=self.bin_transparent_walls, + rgba=rgba, + material=material, + density=density, + friction=friction, + upside_down=bin_upside_down, + ) + objects.append(self.bin) + object_locations.append([0.0, 0.0, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # handles on each side + + left_handle_1_loc = [ + 0.0, + -( + self.bin_size[1] / 2.0 + + 2.0 * self.adjacent_handle_size[1] + + self.center_handle_size[1] + ), + 0.0, + ] + left_handle_1_size = self.center_handle_size + + left_handle_2_loc = [ + (self.center_handle_size[0] - self.adjacent_handle_size[0]), + -(self.bin_size[1] / 2.0 + self.adjacent_handle_size[1]), + 0.0, + ] + left_handle_2_size = self.adjacent_handle_size + + left_handle_3_loc = [ + -(self.center_handle_size[0] - self.adjacent_handle_size[0]), + -(self.bin_size[1] / 2.0 + self.adjacent_handle_size[1]), + 0.0, + ] + left_handle_3_size = self.adjacent_handle_size + + right_handle_1_loc = [ + 0.0, + ( + self.bin_size[1] / 2.0 + + 2.0 * self.adjacent_handle_size[1] + + self.center_handle_size[1] + ), + 0.0, + ] + right_handle_1_size = self.center_handle_size + + right_handle_2_loc = [ + (self.center_handle_size[0] - self.adjacent_handle_size[0]), + (self.bin_size[1] / 2.0 + self.adjacent_handle_size[1]), + 0.0, + ] + right_handle_2_size = self.adjacent_handle_size + + right_handle_3_loc = [ + -(self.center_handle_size[0] - self.adjacent_handle_size[0]), + (self.bin_size[1] / 2.0 + self.adjacent_handle_size[1]), + 0.0, + ] + right_handle_3_size = self.adjacent_handle_size + + handle_locs = [ + left_handle_1_loc, + left_handle_2_loc, + left_handle_3_loc, + right_handle_1_loc, + right_handle_2_loc, + right_handle_3_loc, + ] + handle_sizes = [ + left_handle_1_size, + left_handle_2_size, + left_handle_3_size, + right_handle_1_size, + right_handle_2_size, + right_handle_3_size, + ] + handle_ind = 1 + for b_loc, b_size in zip(handle_locs, handle_sizes): + this_handle = BoxObject( + name="handle_{}".format(handle_ind), + size=b_size, + rgba=rgba, + material=material, + density=density, + friction=friction, + joints=None, + ) + objects.append(this_handle) + object_locations.append(b_loc) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + handle_ind += 1 + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + # total_size=body_total_size, + # locations_relative_to_corner=True, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/coffee_machine.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/coffee_machine.py new file mode 100644 index 0000000000000000000000000000000000000000..a2f73d0373f5595e7cdfe96342b8f44bc646b905 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/coffee_machine.py @@ -0,0 +1,246 @@ +from robosuite.models.objects import CompositeBodyObject, BoxObject +from robocasa.models.objects.composite_body.cup import ( + CupObject, +) +from robocasa.models.objects.xml_objects import ( + CoffeeMachineBodyObject, + CoffeeMachineLidObject, + CoffeeMachineBaseObject, +) +import numpy as np + +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class CoffeeMachineObject(CompositeBodyObject): + """ + Coffee machine object with a lid fixed on a hinge joint. + """ + + def __init__( + self, + name, + add_cup=True, + pod_holder_friction=None, + joints="default", + density=1000.0, + ): + + # pieces of the coffee machine + body = CoffeeMachineBodyObject(name="body") + body_size = body.get_bounding_box_half_size() + body_location = [0.0, 0.0, 0.0] + + lid = CoffeeMachineLidObject(name="lid") + lid_size = self.lid_size = lid.get_bounding_box_half_size() + # add tolerance to allow lid to open fully + lid_location = [ + body_size[0] - lid_size[0], + 2.0 * body_size[1] + 0.01, + 2.0 * (body_size[2] - lid_size[2]) + 0.005, + ] + + # add in hinge joint to lid + hinge_pos = [0.0, -lid_size[1], 0.0] + hinge_joint = dict( + type="hinge", + axis="1 0 0", + pos=array_to_string(hinge_pos), + limited="true", + range="{} {}".format(0, 2.0 * np.pi / 3.0), + damping="0.005", + ) + body_joints = dict( + lid_main=[hinge_joint] + ) # note: "main" gets appended to body name + lid = CoffeeMachineLidObject(name="lid") + + base = CoffeeMachineBaseObject(name="base") + base_size = base.get_bounding_box_half_size() + base_location = [body_size[0] - base_size[0], 2.0 * body_size[1], 0.0] + + pod_holder_holder = BoxObject( + name="pod_holder_holder", + size=[ + 0.01, + # tolerance for having the lid stick out a little from the holder + 0.9 * (lid_size[1] - lid_size[0]), + 0.005, + ], + rgba=[0.839, 0.839, 0.839, 1], # silver + joints=None, + ) + pod_holder_holder_size = pod_holder_holder.get_bounding_box_half_size() + pod_holder_holder_location = [ + body_size[0] - pod_holder_holder_size[0], + 2.0 * body_size[1], + # put right underneath lid + 2.0 * (body_size[2] - lid_size[2] - pod_holder_holder_size[2]), + ] + + pod_holder = CupObject( + name="pod_holder", + outer_cup_radius=lid_size[0], + inner_cup_radius=0.028, + cup_height=0.028, + cup_ngeoms=64, # 8, + cup_base_height=0.005, + cup_base_offset=0.002, + add_handle=False, + rgba=[1, 0, 0, 1], + density=density, + joints=None, + friction=pod_holder_friction, + ) + pod_holder_size = self.pod_holder_size = pod_holder.get_bounding_box_half_size() + # pod_holder_size = self.pod_holder_size = np.array([0.0295, 0.0295, 0.028 ]) + pod_holder_location = [ + body_size[0] - pod_holder_size[0], + 2.0 * (body_size[1] + pod_holder_holder_size[1]), + # put right underneath lid + 2.0 * (body_size[2] - lid_size[2] - pod_holder_size[2]), + ] + + total_size = [ + body_size[0], + body_size[1] + base_size[1], + body_size[2], + ] + + objects = [ + body, + lid, + base, + pod_holder_holder, + pod_holder, + ] + + object_locations = [ + body_location, + lid_location, + base_location, + pod_holder_holder_location, + pod_holder_location, + ] + + object_quats = [ + [0.0, 0.0, 0.0, 1.0], # z-rotate body and base by 180 + [1.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0], + [1.0, 0.0, 0.0, 0.0], + [1.0, 0.0, 0.0, 0.0], + ] + + # add a rigidly mounted cup to the base + self.add_cup = add_cup + if self.add_cup: + cup = CupObject( + name="cupppp", + outer_cup_radius=0.03, + inner_cup_radius=0.025, + cup_height=0.025, + cup_ngeoms=64, # 8, + cup_base_height=0.005, + cup_base_offset=0.005, + add_handle=True, + handle_outer_radius=0.015, + handle_inner_radius=0.010, + handle_thickness=0.003, + handle_ngeoms=64, + rgba=[0.839, 0.839, 0.839, 1], + density=1000.0, + joints=None, + ) + cup_total_size = cup.get_bounding_box_half_size() + # cup_total_size = np.array([0.03 , 0.045, 0.025]) + objects.append(cup) + object_locations.append( + [ + body_size[0] - cup_total_size[0], + 2.0 * (body_size[1] + pod_holder_holder_size[1]) + + pod_holder_size[1] + - cup_total_size[1], + 2.0 * base_size[2], + ] + ) + rot_angle = -np.pi / 2.0 + object_quats.append([np.cos(rot_angle / 2), 0, 0, np.sin(rot_angle / 2)]) + + object_parents = [None] * len(objects) + + """ + Variables to compare: + + objects + [, + , + , + , + , + ] + + object_locations + [[0.0, 0.0, 0.0], + [0.056999999999999995, 0.21100000000000002, 0.20700000000000002], + [0.04449999999999999, 0.201, 0.0], + [0.0765, 0.201, 0.192], + [0.056999999999999995, 0.22710000000000002, 0.14600000000000002], + [0.056499999999999995, 0.21160000000000007, 0.01]] + + object_quats + [[0.0, 0.0, 0.0, 1.0], + [1.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 1.0], + [1.0, 0.0, 0.0, 0.0], + [1.0, 0.0, 0.0, 0.0], + [0.7071067811865476, 0, 0, -0.7071067811865475]] + + body_size + array([0.0865, 0.1005, 0.1105]) + + lid_size + array([0.0295, 0.044 , 0.0095]) + + lid_location + [0.056999999999999995, 0.21100000000000002, 0.20700000000000002] + + base_size + array([0.042, 0.05 , 0.005]) + + base_location + [0.04449999999999999, 0.201, 0.0] + + pod_holder_holder_size + array([0.01 , 0.01305, 0.005 ]) + + pod_holder_holder_location + [0.0765, 0.201, 0.192] + + pod_holder_size + array([0.0295, 0.0295, 0.028 ]) + + pod_holder_location + [0.056999999999999995, 0.22710000000000002, 0.14600000000000002] + + total_size + [0.0865, 0.15050000000000002, 0.1105] + + cup.total_size + array([0.03 , 0.045, 0.025]) + """ + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + body_joints=body_joints, # make sure hinge joint is added + joints=joints, + # joints="default", # coffee machine can move + # joints=None, # coffee machine does not move + total_size=total_size, + locations_relative_to_corner=True, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/cup.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/cup.py new file mode 100644 index 0000000000000000000000000000000000000000..ba7bdda3e22f5048f2ce21fff3bea3c6386cfbf9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/cup.py @@ -0,0 +1,187 @@ +from robosuite.models.objects import ( + CompositeBodyObject, + BoxObject, + CylinderObject, + HollowCylinderObject, +) +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class CupObject(CompositeBodyObject): + """ + Cup object with optional handle. + """ + + def __init__( + self, + name, + outer_cup_radius=0.0425, + inner_cup_radius=0.03, + cup_height=0.05, + cup_ngeoms=8, + cup_base_height=0.01, + cup_base_offset=0.005, + add_handle=False, + handle_outer_radius=0.03, + handle_inner_radius=0.015, + handle_thickness=0.005, + handle_ngeoms=8, + joints="default", + rgba=None, + material=None, + density=100.0, + friction=None, + ): + + # Object properties + + # radius of the inner cup hole and entire cup + self.r1 = inner_cup_radius + self.r2 = outer_cup_radius + + # number of geoms used to approximate the cylindrical shell + self.n = cup_ngeoms + + # cup half-height + self.cup_height = cup_height + + # cup base args + self.cup_base_height = cup_base_height + self.cup_base_offset = cup_base_offset + + # handle args + self.add_handle = add_handle + self.handle_outer_radius = handle_outer_radius + self.handle_inner_radius = handle_inner_radius + self.handle_thickness = handle_thickness + self.handle_ngeoms = handle_ngeoms + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # cup body + self.cup_body = HollowCylinderObject( + name="cup_body", + outer_radius=self.r2, + inner_radius=self.r1, + height=self.cup_height, + ngeoms=self.n, + rgba=rgba, + material=material, + density=density, + friction=friction, + ) + objects.append(self.cup_body) + object_locations.append([0.0, 0.0, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # cup base + self.cup_base = CylinderObject( + name="cup_base", + size=[self.cup_body.int_r, self.cup_base_height], + rgba=rgba, + material=material, + density=density, + solref=[0.02, 1.0], + solimp=[0.998, 0.998, 0.001], + joints=None, + ) + objects.append(self.cup_base) + object_locations.append( + [0.0, 0.0, -self.cup_height + self.cup_base_height + self.cup_base_offset] + ) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + if self.add_handle: + # cup handle is a hollow half-cylinder + self.cup_handle = HollowCylinderObject( + name="cup_handle", + outer_radius=self.handle_outer_radius, + inner_radius=self.handle_inner_radius, + height=self.handle_thickness, + ngeoms=self.handle_ngeoms, + rgba=rgba, + material=material, + density=density, + make_half=True, + friction=friction, + ) + # translate handle to right side of cup body, and rotate by +90 degrees about y-axis + # to orient the handle geoms on the cup body + objects.append(self.cup_handle) + object_locations.append( + [0.0, (self.cup_body.r2 + self.cup_handle.unit_box_width), 0.0] + ) + object_quats.append( + T.convert_quat( + T.mat2quat( + T.rotation_matrix(angle=np.pi / 2.0, direction=[0.0, 1.0, 0.0])[ + :3, :3 + ] + ), + to="wxyz", + ) + ) + object_parents.append(None) + + # total size of cup + body_total_size = [self.r2, self.r2, self.cup_height] + if self.add_handle: + body_total_size[1] += self.handle_outer_radius + + """ + To match on cup 1: + + objects + [, + ] + + body_total_size + [0.0295, 0.0295, 0.028] + + object_locations + [[0.0, 0.0, 0.0], [0.0, 0.0, -0.020999999999999998]] + + object_quats + [[1.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0]] + + + To match on cup 2: + + objects + [, + , + ] + + body_total_size + [0.03, 0.045, 0.025] + + object_locations + [[0.0, 0.0, 0.0], [0.0, 0.0, -0.015], [0.0, 0.03073601511491127, 0.0]] + + object_quats + [[1.0, 0.0, 0.0, 0.0], + [1.0, 0.0, 0.0, 0.0], + array([ 0.70710677, -0. , 0.70710677, -0. ], dtype=float32)] + """ + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + total_size=body_total_size, + # locations_relative_to_corner=True, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/inverse_stacked_cylinder.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/inverse_stacked_cylinder.py new file mode 100644 index 0000000000000000000000000000000000000000..8cf95041d00a480ab01aa51800fc503fc6206e05 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/inverse_stacked_cylinder.py @@ -0,0 +1,141 @@ +from robosuite.models.objects import ( + CompositeBodyObject, + BoxObject, + CylinderObject, + HollowCylinderObject, +) +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class InverseStackedCylinderObject(CompositeBodyObject): + """ + Inverse of stacked cylinder object, where the top piece is a hollow cylinder object + and the bottom piece is a cylinder object. Optionally add a square base for stability. + """ + + def __init__( + self, + name, + radius_1, + radius_2, + height_1, + height_2, + ngeoms=64, + joints="default", + rgba=None, + material=None, + density=100.0, + friction=None, + square_base_width=None, + square_base_height=None, + ): + + # Object properties + + # radius of first (bottom) cylinder and inner radius of second (top) hollow cylinder + self.r1 = radius_1 + self.r2 = radius_2 + + # half-height of first (bottom) cylinder and second (top) hollow cylinder + self.h1 = height_1 + self.h2 = height_2 + + # num geoms to approximate the hollow cylinder + self.ngeoms = ngeoms + + # whether to add square base + self.add_square_base = (square_base_width is not None) and ( + square_base_height is not None + ) + + # half-width and half-height for square base + self.square_base_width = square_base_width + self.square_base_height = square_base_height + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # NOTE: we will place the object frame at the vertical center of the two stacked cylinders + z_center = (self.h1 + self.h2) / 2.0 + c1_offset = self.h1 - z_center + c2_offset = 2.0 * self.h1 + self.h2 - z_center + + # first (bottom) cylinder + self.cylinder_1 = CylinderObject( + name="cylinder_1", + size=[self.r1, self.h1], + rgba=rgba, + material=material, + density=density, + friction=friction, + solref=[0.02, 1.0], + # solimp=[0.998, 0.998, 0.001], + solimp=[0.9, 0.95, 0.001], + joints=None, + ) + objects.append(self.cylinder_1) + object_locations.append([0.0, 0.0, c1_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # second (top) hollow cylinder + self.cylinder_2 = HollowCylinderObject( + name="cylinder_2", + outer_radius=self.r1, # match radius of first cylinder + inner_radius=self.r2, + height=self.h2, + ngeoms=self.ngeoms, + rgba=rgba, + material=material, + density=density, + friction=friction, + # TODO: maybe tune solimp and try (0.998, 0.998, 0.001) + solref=[0.02, 1.0], + solimp=[0.9, 0.95, 0.001], + # solimp=(0.998, 0.998, 0.001), + ) + objects.append(self.cylinder_2) + object_locations.append([0.0, 0.0, c2_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # # total size of object + # max_r = max(self.r1, self.r2) + # body_total_size = [max_r, max_r, self.h1 + self.h2] + + if self.add_square_base: + # add square base underneath bottom cylinder + s1_offset = c1_offset - (self.square_base_height + self.h1) + self.square_base = BoxObject( + name="square_base", + size=[ + self.square_base_width, + self.square_base_width, + self.square_base_height, + ], + rgba=rgba, + material=material, + ) + objects.append(self.square_base) + object_locations.append([0.0, 0.0, s1_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + # total_size=body_total_size, + # locations_relative_to_corner=True, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/lightbulb.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/lightbulb.py new file mode 100644 index 0000000000000000000000000000000000000000..43ce8056200d0ac8ab73943c7b1b66ce1db44cf5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/lightbulb.py @@ -0,0 +1,155 @@ +from robosuite.models.objects import ( + CompositeBodyObject, + BoxObject, + CylinderObject, + BallObject, +) +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string, new_site +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class BallObjectWithSite(BallObject): + """ + A ball object with a inner site (used for the bulb). + """ + + def _get_object_subtree(self): + # tree = super()._get_object_subtree() + tree = self._get_object_subtree_(ob_type="sphere") + site_element_attr = self.get_site_attrib_template() + + site_element_attr["pos"] = "0 0 0.1" + site_element_attr["name"] = "center_site" + site_element_attr["size"] = "{} {} {}".format( + 2.0 * self.size[0], 2.0 * self.size[0], 2.0 * self.size[0] + ) + site_element_attr["rgba"] = "1.0 0.0 0.0 1.0" + site_element_attr["group"] = "1" + # site_element_attr["rgba"] = "1.0 0.976 0.839 0.9" + # site_element_attr["rgba"] = "1.0 0.976 0.839 0.0" + tree.append(new_site(**site_element_attr)) + return tree + + +class LightbulbObject(CompositeBodyObject): + """ + A simple lightbulb constructed out of a base of alternating radius cylinders + and a sphere on top. + """ + + def __init__( + self, + name, + radius_low, + radius_high, + cylinder_height, + num_cylinders, + sphere_radius, + joints="default", + density=100.0, + friction=None, + ): + + # Object properties + + # radii of alternating cylinders for base + self.radius_low = radius_low + self.radius_high = radius_high + + # half-height of each cylinder + self.cylinder_height = cylinder_height + + # number of cylinders for base + self.num_cylinders = num_cylinders + + # radius of sphere at top + self.sphere_radius = sphere_radius + + # toggle between translucent and yellow + self.translucent_rgba = (1.0, 1.0, 1.0, 0.3) + self.yellow_rgba = (1.0, 0.976, 0.839, 0.7) + # self.yellow_rgba = (0.0, 0.0, 0.0, 0.0) + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # NOTE: we will place the object frame at the vertical center of all the stacked objects + self.z_center = ( + (2.0 * self.cylinder_height) * self.num_cylinders + 2.0 * self.sphere_radius + ) / 2.0 + + metal = CustomMaterial( + texture="Metal", + tex_name="metal", + mat_name="MatMetal", + tex_attrib={"type": "cube"}, + mat_attrib={"specular": "1", "shininess": "0.3", "rgba": "0.9 0.9 0.9 1"}, + ) + + # we will define all objects relative to the bottom of the object, and then subtract the z_center value + for cylinder_ind in range(self.num_cylinders): + r = self.radius_low if ((cylinder_ind % 2) == 0) else self.radius_high + cyl_obj = CylinderObject( + name="cylinder_{}".format(cylinder_ind), + size=[r, self.cylinder_height], + rgba=None, + material=metal, + density=density, + friction=friction, + solref=[0.02, 1.0], + solimp=[0.9, 0.95, 0.001], + joints=None, + ) + objects.append(cyl_obj) + z_cyl = (2.0 * cylinder_ind + 1) * self.cylinder_height + object_locations.append([0.0, 0.0, z_cyl]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # then add translucent sphere at top + self.bulb = BallObject( + name="bulb", + size=[self.sphere_radius], + density=density, + friction=friction, + rgba=self.translucent_rgba, + material=None, + joints=None, + ) + objects.append(self.bulb) + z_bulb = object_locations[-1][2] + self.cylinder_height + self.sphere_radius + object_locations.append([0.0, 0.0, z_bulb]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # do frame conversion from bottom of object to z_center + object_locations = [ + [loc[0], loc[1], loc[2] - self.z_center] for loc in object_locations + ] + + # add site that can be toggled to turn lightbulb on + sites = [ + dict( + name="bulb_on", + pos=array_to_string(object_locations[-1]), + size="{}".format(0.95 * self.sphere_radius), + rgba=array_to_string(self.yellow_rgba), + ) + ] + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + sites=sites, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/sliding_box.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/sliding_box.py new file mode 100644 index 0000000000000000000000000000000000000000..0e6542b615457918a9ab869b62f54eb1923db5d5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/sliding_box.py @@ -0,0 +1,132 @@ +import numpy as np + +from robosuite.models.objects import BoxObject, CompositeBodyObject, CylinderObject +from robosuite.utils.mjcf_utils import BLUE, RED, CustomMaterial, array_to_string + + +class SlidingBoxObject(CompositeBodyObject): + """ + An example object that demonstrates the CompositeBodyObject functionality. This object consists of two cube bodies + joined together by a slide joint allowing one box to slide on top of the other. + + Args: + name (str): Name of this object + + box1_size (3-array): (L, W, H) half-sizes for the first box + + box2_size (3-array): (L, W, H) half-sizes for the second box + + use_texture (bool): set True if using wood textures for the blocks + """ + + def __init__( + self, + name, + box1_size=(0.1, 0.1, 0.02), + box2_size=(0.02, 0.02, 0.02), + use_texture=True, + ): + # Set box sizes + self.box1_size = np.array(box1_size) + self.box2_size = np.array(box2_size) + + # Set box densities + self.box1_density = 10000.0 + self.box2_density = 100.0 + + # Set texture attributes + self.use_texture = use_texture + self.box1_material = None + self.box2_material = None + self.box1_rgba = RED + self.box2_rgba = BLUE + + # Define materials we want to use for this object + if self.use_texture: + # Remove RGBAs + self.box1_rgba = None + self.box2_rgba = None + + # Set materials for each box + tex_attrib = { + "type": "cube", + } + mat_attrib = { + "texrepeat": "3 3", + "specular": "0.4", + "shininess": "0.1", + } + self.box1_material = CustomMaterial( + texture="WoodRed", + tex_name="box1_tex", + mat_name="box1_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + self.box2_material = CustomMaterial( + texture="WoodBlue", + tex_name="box2_tex", + mat_name="box2_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + + # Create objects + objects = [] + for i, (size, mat, rgba, density) in enumerate( + zip( + (self.box1_size, self.box2_size), + (self.box1_material, self.box2_material), + (self.box1_rgba, self.box2_rgba), + (self.box1_density, self.box2_density), + ) + ): + objects.append( + BoxObject( + name=f"box{i + 1}", + size=size, + rgba=rgba, + material=mat, + ) + ) + + # Define slide joint + rel_joint_pos = [0, 0, 0] # at second box + joint_lim = self.box1_size[1] - self.box2_size[1] + slide_joint = { + "name": "box_slide", + "type": "slide", + "axis": "0 1 0", # y-axis slide + "pos": array_to_string(rel_joint_pos), + "springref": "0", + "springdamper": "0.1 1.0", # mass-spring system with 0.1 time constant, 1.0 damping ratio + "limited": "true", + "range": "{} {}".format(-joint_lim, joint_lim), + } + + # Define positions -- second box should lie on top of first box + positions = [ + np.zeros(3), # First box is centered at top-level body anyways + np.array([0, 0, self.box1_size[2] + self.box2_size[2]]), + ] + + quats = [ + None, # Default quaternion for box 1 + None, # Default quaternion for box 2 + ] + + # Define parents -- which body each is aligned to + parents = [ + None, # box 1 attached to top-level body + objects[0].root_body, # box 2 attached to box 1 + ] + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=positions, + object_quats=quats, + object_parents=parents, + body_joints={objects[1].root_body: [slide_joint]}, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/socket.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/socket.py new file mode 100644 index 0000000000000000000000000000000000000000..21dadbe7af0d0cf9e9d2a52dfc7d56a9beea3ac0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/socket.py @@ -0,0 +1,339 @@ +from robosuite.models.objects import CompositeBodyObject, BoxObject, CylinderObject +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial +from .stacked_cylinder import StackedCylinderObject + + +class SocketObject(CompositeBodyObject): + """ + Box geom connected to series of geoms with ball joints (wire) and connected to + cylinder representing plug. + """ + + def __init__( + self, + name, + joints="default", + rgba=None, + material=None, + density=100.0, + friction=None, + socket_base_size=(0.02, 0.02, 0.03), + wire_box_geom_size=(0.02, 0.005, 0.005), + wire_box_geom_rgba=(0.0, 0.0, 0.0, 1.0), + num_box_geoms_up=6, + num_box_geoms_left=2, + num_box_geoms_down=9, + merge_box_geoms=False, + merge_size=1, + cylinder_args=None, + ): + + # Object properties + + # box geom used for socket base + self.socket_base_size = socket_base_size + + # box geoms used for wire + self.wire_box_geom_size = wire_box_geom_size + self.wire_box_geom_rgba = wire_box_geom_rgba + + # wire parameters - number of geoms to use for up, left, and down portions + self.num_box_geoms_up = num_box_geoms_up + self.num_box_geoms_left = num_box_geoms_left + self.num_box_geoms_down = num_box_geoms_down + + # if true, merge the box geoms along each direction of the wire into a single box geom + self.merge_box_geoms = merge_box_geoms + + # number of box geoms to use for each merged size (set to higher than 1 to merge the geoms into more + # than one box geom) + self.merge_size = merge_size + + if cylinder_args is None: + # default cylinder args + cylinder_args = dict( + # bottom cylinder radius and half-height + radius_1=0.03, + height_1=0.075, + # top cylinder radius and half-height + radius_2=0.02, + height_2=0.025, + rgba=[0.839, 0.839, 0.839, 1], + density=1000.0, + # add square base + square_base_width=0.03, + square_base_height=0.005, + ) + self.cylinder_args = dict(cylinder_args) + self.cylinder_args["joints"] = None + + # materials + box_geom_material = CustomMaterial( + texture="Metal", + tex_name="metal", + mat_name="MatMetal", + tex_attrib={"type": "cube"}, + mat_attrib={"specular": "1", "shininess": "0.3", "rgba": "0.9 0.9 0.9 1"}, + ) + socket_material = CustomMaterial( + texture="WoodLight", + tex_name="lightwood", + mat_name="lightwood_mat", + tex_attrib={"type": "cube"}, + mat_attrib={"texrepeat": "1 1", "specular": "0.4", "shininess": "0.1"}, + ) + + # params for ball joints used + + # + ball_joint_spec = { + "type": "ball", + "pos": "{} 0 0".format(self.wire_box_geom_size[0]), + "springref": "0", + "springdamper": "0.1 1.0", # mass-spring system with 0.1 time constant, 1.0 damping ratio + "limited": "true", + "range": "0 {}".format(np.pi / 4), + } + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + object_joints = dict() + + # NOTE: For absolute object locations (objects not defined relative to parent) we will use the socket base frame + # as a frame of reference, and add an offset from the center of the object (approximated via full width) + # to it. + + # get an approximate x-y bounding box below, and place the center there, and define offset relative to stove base center + approx_full_width = self.num_box_geoms_left * ( + 2.0 * self.wire_box_geom_size[0] + ) + (2.0 * self.socket_base_size[1]) + approx_full_height = (self.num_box_geoms_down + 2) * ( + 2.0 * self.wire_box_geom_size[0] + ) + + base_x_off = ( + self.socket_base_size[0] + + (self.num_box_geoms_up) * (2.0 * self.wire_box_geom_size[0]) + ) - (approx_full_height / 2.0) + base_y_off = ( + self.num_box_geoms_left * self.wire_box_geom_size[0] + ) + self.socket_base_size[1] + + # base of socket + self.socket_base = BoxObject( + name="stove_base", + size=list(self.socket_base_size), + rgba=rgba, + material=socket_material, + joints=None, + ) + objects.append(self.socket_base) + object_locations.append([base_x_off, base_y_off, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # chain above base + chain_ind = 0 + up_chain_size = list(self.wire_box_geom_size) + num_geoms_iter = self.num_box_geoms_up - 1 + if self.merge_box_geoms: + # only one big geom instead of chain of geoms + up_chain_size[0] *= self.num_box_geoms_up + up_chain_size[0] /= self.merge_size + # number of additional geoms to add + num_geoms_iter = self.merge_size - 1 + chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(up_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + objects.append(chain_obj) + object_locations.append( + [ + base_x_off - (self.socket_base_size[0] + up_chain_size[0]), + base_y_off, + 0.0, + ] + ) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + if self.merge_box_geoms: + # add ball joint and make sure to place it at the edge of the geom + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "{} 0 0".format(up_chain_size[0]) + object_joints[chain_obj.root_body] = [ball_joint] + + for i in range(num_geoms_iter): + chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(up_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(chain_obj) + object_locations.append([-2.0 * up_chain_size[0], 0.0, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + # add ball joint and make sure to place it at the edge of the geom + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "{} 0 0".format(up_chain_size[0]) + object_joints[chain_obj.root_body] = [ball_joint] + + # add chain in left direction + rot_quat = T.convert_quat( + T.axisangle2quat(np.array([0.0, 0.0, 1.0]) * (np.pi / 2.0)), to="wxyz" + ) + left_chain_size = list(self.wire_box_geom_size) + num_geoms_iter = self.num_box_geoms_left - 1 + if self.merge_box_geoms: + # only one big geom instead of chain of geoms + left_chain_size[0] *= self.num_box_geoms_left + # HACK: merge entire left chain since this side is small + left_merge_size = 1 + left_chain_size[0] /= left_merge_size + # number of additional geoms to add + num_geoms_iter = left_merge_size - 1 + chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(left_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(chain_obj) + object_locations.append([-up_chain_size[0], -left_chain_size[0], 0.0]) + object_quats.append(rot_quat) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "{} 0 0".format(left_chain_size[0]) + object_joints[chain_obj.root_body] = [ball_joint] + + for i in range(num_geoms_iter): + chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(left_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(chain_obj) + object_locations.append([-2.0 * left_chain_size[0], 0.0, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "{} 0 0".format(left_chain_size[0]) + object_joints[chain_obj.root_body] = [ball_joint] + + # add chain in downward direction + rot_quat = T.convert_quat( + T.axisangle2quat(np.array([0.0, 0.0, 1.0]) * (np.pi / 2.0)), to="wxyz" + ) + down_chain_size = list(self.wire_box_geom_size) + num_geoms_iter = self.num_box_geoms_down - 1 + if self.merge_box_geoms: + # only one big geom instead of chain of geoms + down_chain_size[0] *= self.num_box_geoms_down + down_chain_size[0] /= self.merge_size + # number of additional geoms to add + num_geoms_iter = self.merge_size - 1 + chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(down_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(chain_obj) + object_locations.append([-left_chain_size[0], -down_chain_size[0], 0.0]) + object_quats.append(rot_quat) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "{} 0 0".format(down_chain_size[0]) + object_joints[chain_obj.root_body] = [ball_joint] + + for i in range(num_geoms_iter): + chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(down_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(chain_obj) + object_locations.append([-2.0 * down_chain_size[0], 0.0, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "{} 0 0".format(down_chain_size[0]) + object_joints[chain_obj.root_body] = [ball_joint] + + # add cylinder object + self.cylinder_obj = StackedCylinderObject( + name="cylinder_obj", + **self.cylinder_args, + ) + + x_off = -(down_chain_size[0] + self.cylinder_obj.square_base_width) + y_off = 0.0 + z_off = ((self.cylinder_obj.h1 + self.cylinder_obj.h2) / 2.0) - down_chain_size[ + 2 + ] + parent = objects[-1].root_body + objects.append(self.cylinder_obj) + object_locations.append([x_off, y_off, z_off]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + # # add debug site to see object center + # sites = [ + # dict( + # name="TMP", + # pos=array_to_string([0., 0., 0.]), + # size="{}".format(0.1), + # rgba=array_to_string([1., 0., 0., 1.]), + # ) + # ] + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + body_joints=object_joints, + # sites=sites, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/spray_bottle.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/spray_bottle.py new file mode 100644 index 0000000000000000000000000000000000000000..56537ffdeb3fec3cfb7402b2a7f6ff32f7fd5d4d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/spray_bottle.py @@ -0,0 +1,213 @@ +import numpy as np + +from robosuite.models.objects import ( + BoxObject, + CompositeBodyObject, + CylinderObject, + ConeObject, +) +from robosuite.utils.mjcf_utils import BLUE, RED, CustomMaterial, array_to_string + + +class SprayBottleObject(CompositeBodyObject): + """ + A spray bottle object where the trigger is modeled via a slide joint. + """ + + def __init__( + self, + name, + base_cylinder_radius, + base_cylinder_height, + cone_outer_radius, + cone_inner_radius, + cone_height, + cone_ngeoms, + neck_height, + top_length, + top_thickness, + trigger_height, + trigger_width, + trigger_length, + joints="default", + rgba=None, + material=None, + density=100.0, + friction=None, + square_base_width=None, + square_base_height=None, + ): + # Sizes + self.base_cylinder_radius = base_cylinder_radius + self.base_cylinder_height = base_cylinder_height + self.cone_outer_radius = cone_outer_radius + self.cone_inner_radius = cone_inner_radius + self.cone_height = cone_height + self.cone_ngeoms = cone_ngeoms + self.neck_height = neck_height + self.top_length = top_length + self.top_thickness = top_thickness + self.trigger_height = trigger_height + self.trigger_width = trigger_width + self.trigger_length = trigger_length + + # whether to add square base + self.add_square_base = (square_base_width is not None) and ( + square_base_height is not None + ) + + # half-width and half-height for square base + self.square_base_width = square_base_width + self.square_base_height = square_base_height + + assert ( + self.top_length > self.cone_inner_radius + ), "top needs to stick out past neck" + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # base cylinder + self.base_cylinder = CylinderObject( + name="base_cylinder", + size=[self.base_cylinder_radius, self.base_cylinder_height], + rgba=rgba, + material=material, + density=density, + friction=friction, + solref=[0.02, 1.0], + # solimp=[0.998, 0.998, 0.001], + solimp=[0.9, 0.95, 0.001], + joints=None, + ) + objects.append(self.base_cylinder) + object_locations.append([0.0, 0.0, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # cone that is part of neck + # z_cone = self.base_cylinder_height # cone frame is bottom center of cone + z_cone = self.base_cylinder_height + (self.cone_height / 2.0) + self.neck_cone = ConeObject( + name="neck_cone", + outer_radius=self.cone_outer_radius, + inner_radius=self.cone_inner_radius, + height=self.cone_height, # full height, not half-height + ngeoms=self.cone_ngeoms, + use_box=False, + rgba=rgba, + material=material, + density=density, + solref=(0.02, 1.0), + # solimp=[0.998, 0.998, 0.001], + solimp=(0.9, 0.95, 0.001), + friction=friction, + ) + objects.append(self.neck_cone) + object_locations.append([0.0, 0.0, z_cone]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # cylinder that is part of neck + z_cyl = self.base_cylinder_height + self.cone_height + self.neck_height + self.neck_cylinder = CylinderObject( + name="neck_cylinder", + size=[self.cone_inner_radius, self.neck_height], # match cone radius + rgba=rgba, + material=material, + density=density, + friction=friction, + solref=[0.02, 1.0], + # solimp=[0.998, 0.998, 0.001], + solimp=[0.9, 0.95, 0.001], + joints=None, + ) + objects.append(self.neck_cylinder) + object_locations.append([0.0, 0.0, z_cyl]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # top box object + box_x_off = -(self.top_length - self.cone_inner_radius) + box_z_off = z_cyl + self.neck_height + self.top_thickness + self.top_box = BoxObject( + name="top_box", + size=[self.top_length, self.cone_inner_radius, self.top_thickness], + density=density, + friction=friction, + rgba=rgba, + material=material, + joints=None, + ) + objects.append(self.top_box) + object_locations.append([box_x_off, 0.0, box_z_off]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # trigger object, which is defined relative to top box object + trigger_x_off = -( + 0.5 * self.top_length + ) # place halfway along length of top object + trigger_z_off = -(self.top_thickness + self.trigger_height) + self.trigger = BoxObject( + name="trigger", + size=[self.trigger_length, self.trigger_width, self.trigger_height], + density=density, + friction=friction, + rgba=rgba, + material=material, + joints=None, + ) + objects.append(self.trigger) + object_locations.append([trigger_x_off, 0.0, trigger_z_off]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(objects[-2].root_body) # NOTE: relative to top box object + + # define slide joint for trigger + rel_joint_pos = [0, 0, 0] # at trigger + joint_lim_min = 0.0 + joint_lim_max = ( + self.top_length + ) # trigger was shifted to left by 0.5 * top_length, so allow it to go to right by top_length + slide_joint = { + "name": "trigger_slide", + "type": "slide", + "axis": "1 0 0", # x-axis slide + "pos": array_to_string(rel_joint_pos), + "springref": "0", + "springdamper": "0.1 1.0", # mass-spring system with 0.1 time constant, 1.0 damping ratio + "limited": "true", + "range": "{} {}".format(joint_lim_min, joint_lim_max), + } + + if self.add_square_base: + # add square base underneath bottom cylinder + s1_offset = -(self.square_base_height + self.base_cylinder_height) + self.square_base = BoxObject( + name="square_base", + size=[ + self.square_base_width, + self.square_base_width, + self.square_base_height, + ], + rgba=rgba, + material=material, + ) + objects.append(self.square_base) + object_locations.append([0.0, 0.0, s1_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + body_joints={objects[-1].root_body: [slide_joint]}, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stacked_box.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stacked_box.py new file mode 100644 index 0000000000000000000000000000000000000000..c2c7991c3a6056531e7758586df1f6a5538e3d45 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stacked_box.py @@ -0,0 +1,111 @@ +from robosuite.models.objects import CompositeBodyObject, BoxObject, CylinderObject, Bin +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class StackedBoxObject(CompositeBodyObject): + """ + Two boxes - one stacked on top of the other. + """ + + def __init__( + self, + name, + box_1_size, + box_2_size, + joints="default", + box_1_rgba=None, + box_2_rgba=None, + box_1_material=None, + box_2_material=None, + density=100.0, + friction=None, + make_box_2_transparent=False, + ): + + # Object properties + + # half-sizes of first (bottom) box + self.box_1_size = list(box_1_size) + + # half-sizes of second (top) box + self.box_2_size = list(box_2_size) + + # maybe make box 2 have transparent top and bottom walls + self.make_box_2_transparent = make_box_2_transparent + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # NOTE: we will place the object frame at the vertical center of the two stacked boxes + z_center = (self.box_1_size[2] + self.box_2_size[2]) / 2.0 + b1_offset = self.box_1_size[2] - z_center + b2_offset = 2.0 * self.box_1_size[2] + self.box_2_size[2] - z_center + + # first (bottom) box + self.box_1 = BoxObject( + name="box_1", + size=self.box_1_size, + rgba=box_1_rgba, + material=box_1_material, + density=density, + friction=friction, + joints=None, + ) + objects.append(self.box_1) + object_locations.append([0.0, 0.0, b1_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # second (top) box + if self.make_box_2_transparent: + self.box_2 = Bin( + name="box_2", + bin_size=( + 2.0 * self.box_2_size[0], + 2.0 * self.box_2_size[1], + 2.0 * self.box_2_size[2], + ), + wall_thickness=0.01, + transparent_walls=False, + friction=friction, + density=density, + use_texture=True, + rgba=box_2_rgba, + material=box_2_material, + upside_down=False, + add_second_base=True, + transparent_base=True, + ) + else: + self.box_2 = BoxObject( + name="box_2", + size=self.box_2_size, + rgba=box_2_rgba, + material=box_2_material, + density=density, + friction=friction, + joints=None, + ) + objects.append(self.box_2) + object_locations.append([0.0, 0.0, b2_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + # total_size=body_total_size, + # locations_relative_to_corner=True, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stacked_cylinder.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stacked_cylinder.py new file mode 100644 index 0000000000000000000000000000000000000000..047bc46f39fb8b1bdc9bb01ebf872b9be6f929e5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stacked_cylinder.py @@ -0,0 +1,129 @@ +from robosuite.models.objects import CompositeBodyObject, BoxObject, CylinderObject +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial + + +class StackedCylinderObject(CompositeBodyObject): + """ + Two cylinders - one stacked on top of the other. + Optionally add a square base for stability. + """ + + def __init__( + self, + name, + radius_1, + radius_2, + height_1, + height_2, + joints="default", + rgba=None, + material=None, + density=100.0, + friction=None, + square_base_width=None, + square_base_height=None, + ): + + # Object properties + + # radius of first (bottom) cylinder and second (top) cylinder + self.r1 = radius_1 + self.r2 = radius_2 + + # half-height of first (bottom) cylinder and second (top) cylinder + self.h1 = height_1 + self.h2 = height_2 + + # whether to add square base + self.add_square_base = (square_base_width is not None) and ( + square_base_height is not None + ) + + # half-width and half-height for square base + self.square_base_width = square_base_width + self.square_base_height = square_base_height + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + + # NOTE: we will place the object frame at the vertical center of the two stacked cylinders + z_center = (self.h1 + self.h2) / 2.0 + c1_offset = self.h1 - z_center + c2_offset = 2.0 * self.h1 + self.h2 - z_center + + # first (bottom) cylinder + self.cylinder_1 = CylinderObject( + name="cylinder_1", + size=[self.r1, self.h1], + rgba=rgba, + material=material, + density=density, + friction=friction, + solref=[0.02, 1.0], + solimp=[0.9, 0.95, 0.001], + # solimp=[0.998, 0.998, 0.001], + joints=None, + ) + objects.append(self.cylinder_1) + object_locations.append([0.0, 0.0, c1_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # second (top) cylinder + self.cylinder_2 = CylinderObject( + name="cylinder_2", + size=[self.r2, self.h2], + rgba=rgba, + material=material, + density=density, + friction=friction, + solref=[0.02, 1.0], + # solimp=[0.998, 0.998, 0.001], + solimp=[0.9, 0.95, 0.001], + joints=None, + ) + objects.append(self.cylinder_2) + object_locations.append([0.0, 0.0, c2_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # # total size of object + # max_r = max(self.r1, self.r2) + # body_total_size = [max_r, max_r, self.h1 + self.h2] + + if self.add_square_base: + # add square base underneath bottom cylinder + s1_offset = c1_offset - (self.square_base_height + self.h1) + self.square_base = BoxObject( + name="square_base", + size=[ + self.square_base_width, + self.square_base_width, + self.square_base_height, + ], + rgba=rgba, + material=material, + ) + objects.append(self.square_base) + object_locations.append([0.0, 0.0, s1_offset]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + # total_size=body_total_size, + # locations_relative_to_corner=True, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stove_plug.py b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stove_plug.py new file mode 100644 index 0000000000000000000000000000000000000000..088d7be31aa4d1a76602e25a01e9e5e002f4ea64 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa-gr1-tabletop-tasks/robocasa/models/objects/composite_body/stove_plug.py @@ -0,0 +1,400 @@ +from robosuite.models.objects import CompositeBodyObject, BoxObject, CylinderObject +import numpy as np + +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import array_to_string +from robosuite.utils.mjcf_utils import RED, BLUE, CustomMaterial +from .inverse_stacked_cylinder import InverseStackedCylinderObject +from .lightbulb import LightbulbObject + +import robosuite_task_zoo +from robosuite_task_zoo.models.kitchen import StoveObject + + +class StoveObjectNew(StoveObject): + """ + Override some offsets for placement sampler. + """ + + @property + def bottom_offset(self): + # unused since we directly hardcode z + return np.array([0, 0, -0.02]) + + @property + def top_offset(self): + # unused since we directly hardcode z + return np.array([0, 0, 0.02]) + + @property + def horizontal_radius(self): + return 0.1 + + +class StovePlugObject(CompositeBodyObject): + """ + Stove on wooden block with chain (plug) connected. Optionally replace the stove + with a lightbulb if @lightbulb_args is provided. + """ + + def __init__( + self, + name, + joints="default", + rgba=None, + material=None, + density=100.0, + friction=None, + stove_base_size=(0.12, 0.12, 0.01), + stove_z_half_size=0.025, + wire_box_geom_size=(0.005, 0.02, 0.005), + wire_box_geom_rgba=(0.0, 0.0, 0.0, 1.0), + num_box_geoms_left=5, + num_box_geoms_vert=8, + num_box_geoms_right=8, + merge_box_geoms=False, + merge_size=1, + cylinder_args=None, + lightbulb_args=None, + ): + + # Object properties + + # half sizes for stove base box object + # self.stove_base_size = (0.1, 0.1, 0.02) + self.stove_base_size = stove_base_size + self.stove_z_half_size = stove_z_half_size # note: estimated approximately + + # box geoms used for wire + self.wire_box_geom_size = wire_box_geom_size + self.wire_box_geom_rgba = wire_box_geom_rgba + + # wire parameters - number of geoms to use for left, down, and right portions + self.num_box_geoms_left = num_box_geoms_left + self.num_box_geoms_vert = num_box_geoms_vert + self.num_box_geoms_right = num_box_geoms_right + + # if true, merge the box geoms along each direction of the wire into a single box geom + self.merge_box_geoms = merge_box_geoms + + # number of box geoms to use for each merged size (set to higher than 1 to merge the geoms into more + # than one box geom) + self.merge_size = merge_size + + if cylinder_args is None: + # default cylinder args + cylinder_args = dict( + # bottom cylinder radius and half-height + radius_1=0.03, + height_1=0.01, + # top hollow cylinder inner radius and half-height + radius_2=0.025, + height_2=0.025, + # NOTE: reduce to 8 geoms if desired + ngeoms=64, + rgba=[0.839, 0.839, 0.839, 1], + density=1000.0, + # add square base + square_base_width=0.03, + square_base_height=0.005, + ) + self.cylinder_args = dict(cylinder_args) + self.cylinder_args["joints"] = None + + self.use_lightbulb = lightbulb_args is not None + if self.use_lightbulb: + self.lightbulb_args = dict(lightbulb_args) + self.lightbulb_args["joints"] = None + + # materials + box_geom_material = CustomMaterial( + texture="Metal", + tex_name="metal", + mat_name="MatMetal", + tex_attrib={"type": "cube"}, + mat_attrib={"specular": "1", "shininess": "0.3", "rgba": "0.9 0.9 0.9 1"}, + ) + stove_base_material = CustomMaterial( + texture="WoodLight", + tex_name="lightwood", + mat_name="lightwood_mat", + tex_attrib={"type": "cube"}, + mat_attrib={"texrepeat": "1 1", "specular": "0.4", "shininess": "0.1"}, + ) + + # params for ball joints used + + # + ball_joint_spec = { + "type": "ball", + "pos": "0 {} 0".format(self.wire_box_geom_size[1]), + "springref": "0", + "springdamper": "0.1 1.0", # mass-spring system with 0.1 time constant, 1.0 damping ratio + "limited": "true", + "range": "0 {}".format(np.pi / 4), + } + + # Create objects + objects = [] + object_locations = [] + object_quats = [] + object_parents = [] + object_joints = dict() + + # NOTE: For absolute object locations (objects not defined relative to parent) we will use the stove base frame + # as a frame of reference, and add an offset from the center of the object (approximated via full width) + # to it. + + # get an approximate x-y bounding box below, and place the center there, and define offset relative to stove base cente + approx_full_width = self.num_box_geoms_left * ( + 2.0 * self.wire_box_geom_size[1] + ) + (2.0 * self.stove_base_size[1]) + approx_full_height = (self.num_box_geoms_vert + 2) * ( + 2.0 * self.wire_box_geom_size[1] + ) + + stove_base_x_off = -(approx_full_height / 2.0) + self.stove_base_size[0] + stove_base_y_off = (approx_full_width / 2.0) - self.stove_base_size[1] + + # base of stove + self.stove_base = BoxObject( + name="stove_base", + size=list(self.stove_base_size), + rgba=rgba, + material=stove_base_material, + joints=None, + ) + objects.append(self.stove_base) + object_locations.append([stove_base_x_off, stove_base_y_off, 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + if self.use_lightbulb: + # lightbulb + self.lightbulb = LightbulbObject( + name="lightbulb", + **self.lightbulb_args, + ) + objects.append(self.lightbulb) + object_locations.append( + [ + stove_base_x_off, + stove_base_y_off, + (self.stove_base_size[2] + self.lightbulb.z_center), + ] + ) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + else: + # stove + self.stove = StoveObjectNew( + name="new_stove", + joints=None, + ) + objects.append(self.stove) + object_locations.append( + [ + stove_base_x_off, + stove_base_y_off, + (self.stove_base_size[2] + self.stove_z_half_size), + ] + ) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + + # chain to the left of stove base + chain_ind = 0 + left_chain_size = list(self.wire_box_geom_size) + num_geoms_iter = self.num_box_geoms_left - 1 + if self.merge_box_geoms: + # only one big geom instead of chain of geoms + left_chain_size[1] *= self.num_box_geoms_left + left_chain_size[1] /= self.merge_size + # number of additional geoms to add + num_geoms_iter = self.merge_size - 1 + left_chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(left_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + objects.append(left_chain_obj) + object_locations.append( + [ + stove_base_x_off - 0.75 * self.stove_base_size[0], + stove_base_y_off - (self.stove_base_size[1] + left_chain_size[1]), + 0.0, + ] + ) + # object_locations.append([0., -(self.stove_base_size[1] + left_chain_size[1]), 0.]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(None) + if self.merge_box_geoms: + # add ball joint and make sure to place it at the edge of the geom + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "0 {} 0".format(left_chain_size[1]) + object_joints[left_chain_obj.root_body] = [ball_joint] + for i in range(num_geoms_iter): + left_chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(left_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(left_chain_obj) + object_locations.append([0.0, -2.0 * left_chain_size[1], 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + # add ball joint and make sure to place it at the edge of the geom + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "0 {} 0".format(left_chain_size[1]) + object_joints[left_chain_obj.root_body] = [ball_joint] + + # add chain in downward direction + rot_quat = T.convert_quat( + T.axisangle2quat(np.array([0.0, 0.0, 1.0]) * (np.pi / 2.0)), to="wxyz" + ) + vert_chain_size = list(self.wire_box_geom_size) + num_geoms_iter = self.num_box_geoms_vert - 1 + if self.merge_box_geoms: + # only one big geom instead of chain of geoms + vert_chain_size[1] *= self.num_box_geoms_vert + vert_chain_size[1] /= self.merge_size + # number of additional geoms to add + num_geoms_iter = self.merge_size - 1 + vert_chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(vert_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(vert_chain_obj) + object_locations.append([vert_chain_size[1], -left_chain_size[1], 0.0]) + object_quats.append(rot_quat) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "0 {} 0".format(vert_chain_size[1]) + object_joints[vert_chain_obj.root_body] = [ball_joint] + + for i in range(num_geoms_iter): + vert_chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(vert_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(vert_chain_obj) + object_locations.append([0.0, -2.0 * vert_chain_size[1], 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "0 {} 0".format(vert_chain_size[1]) + object_joints[vert_chain_obj.root_body] = [ball_joint] + + # add chain in rightward direction + rot_quat = T.convert_quat( + T.axisangle2quat(np.array([0.0, 0.0, 1.0]) * (np.pi / 2.0)), to="wxyz" + ) + right_chain_size = list(self.wire_box_geom_size) + num_geoms_iter = self.num_box_geoms_right - 1 + if self.merge_box_geoms: + # only one big geom instead of chain of geoms + right_chain_size[1] *= self.num_box_geoms_right + right_chain_size[1] /= self.merge_size + # number of additional geoms to add + num_geoms_iter = self.merge_size - 1 + right_chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(right_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(right_chain_obj) + object_locations.append([right_chain_size[1], -vert_chain_size[1], 0.0]) + object_quats.append(rot_quat) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "0 {} 0".format(right_chain_size[1]) + object_joints[right_chain_obj.root_body] = [ball_joint] + + for i in range(num_geoms_iter): + right_chain_obj = BoxObject( + name="chain_{}".format(chain_ind), + size=list(right_chain_size), + rgba=list(self.wire_box_geom_rgba), + material=box_geom_material, + joints=None, + ) + chain_ind += 1 + parent = objects[-1].root_body + objects.append(right_chain_obj) + object_locations.append([0.0, -2.0 * right_chain_size[1], 0.0]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + ball_joint = dict(ball_joint_spec) + ball_joint["name"] = "ball_joint_{}".format(chain_ind) + ball_joint["pos"] = "0 {} 0".format(right_chain_size[1]) + object_joints[right_chain_obj.root_body] = [ball_joint] + + # add cylinder object + self.cylinder_obj = InverseStackedCylinderObject( + name="cylinder_obj", + **self.cylinder_args, + ) + + x_off = 0.0 + y_off = -(right_chain_size[1] + self.cylinder_obj.square_base_width) + z_off = ( + (self.cylinder_obj.h1 + self.cylinder_obj.h2) / 2.0 + ) - right_chain_size[2] + parent = objects[-1].root_body + objects.append(self.cylinder_obj) + object_locations.append([x_off, y_off, z_off]) + object_quats.append([1.0, 0.0, 0.0, 0.0]) + object_parents.append(parent) + + # # add debug site to see object center + # sites = [ + # dict( + # name="TMP", + # pos=array_to_string([0., 0., 0.]), + # size="{}".format(0.1), + # rgba=array_to_string([1., 0., 0., 1.]), + # ) + # ] + + # Run super init + super().__init__( + name=name, + objects=objects, + object_locations=object_locations, + object_quats=object_quats, + object_parents=object_parents, + joints=joints, + body_joints=object_joints, + # sites=sites, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/.gitignore b/Isaac-GR00T/external_dependencies/robocasa/docs/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3c1f3b58410f315566363bbfdb04fa588494303a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/.gitignore @@ -0,0 +1,2 @@ +_build +api diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/Makefile b/Isaac-GR00T/external_dependencies/robocasa/docs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..fc04a82d4fe8aed28227dcfe64b2ac835bfecaf7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/Makefile @@ -0,0 +1,24 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +apidoc: + @sphinx-apidoc -T --force ../robocasa -o api + + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/conf.py b/Isaac-GR00T/external_dependencies/robocasa/docs/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..ffe7ae58ed5a20308f99860c65a82067a24074b3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/conf.py @@ -0,0 +1,156 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +import os +import sys + +sys.path.insert(0, os.path.abspath(".")) + +# import pydata_sphinx_theme +import robocasa + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.napoleon", + "sphinx_markdown_tables", + "sphinx.ext.mathjax", + "sphinx.ext.githubpages", + "sphinx.ext.autodoc", + "recommonmark", # use Sphinx-1.4 or newer + "nbsphinx", +] + + +# Sphinx-apidoc variables +apidoc_module_dir = "../robocasa" +apidoc_output_dir = "reference" + + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# source_parsers = { +# '.md': CommonMarkParser, +# } + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +source_suffix = [".rst", ".md", ".ipynb"] + +# The master toctree document. +master_doc = "index" + +# General information about the project. +project = "RoboCasa" +copyright = "the RoboCasa core team, 2024" +author = "the RoboCasa core team" + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = (".").join(robocasa.__version__.split(".")[:-1]) +# The full version, including alpha/beta/rc tags. +release = (".").join(robocasa.__version__.split(".")[:-1]) + + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = "en" + + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects htmlstatic_path and html_extra_path. +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = "sphinx" + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "sphinx_book_theme" +html_logo = "robocasa_logo.svg" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +htmlstatic_path = ["static"] + +# html_context = { +# 'css_files': [ +# 'static/theme_overrides.css', # override wide tables in RTD theme +# ], +# } + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = "robocasadoc" + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, "robocasa.tex", "RoboCasa Documentation", author, "manual"), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [(master_doc, "robocasa", "RoboCasa Documentation", [author], 1)] diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/images/layouts.png b/Isaac-GR00T/external_dependencies/robocasa/docs/images/layouts.png new file mode 100644 index 0000000000000000000000000000000000000000..ca907828d4f5ad98c76af9675ddc14cc9ceb6536 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/images/layouts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75b4e630608f36f82ec99dfd850538c5eb77ec17cb8da477b69218a1383d3582 +size 2966715 diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/images/robocasa-banner.jpg b/Isaac-GR00T/external_dependencies/robocasa/docs/images/robocasa-banner.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aee1b89b99d1f65f1f6452f790684c2394a13e10 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/images/robocasa-banner.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:910a659b222c7ec92963b2a656ae23e9fd55332037b472bee7fd62d68eaf55af +size 1448004 diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/images/styles.png b/Isaac-GR00T/external_dependencies/robocasa/docs/images/styles.png new file mode 100644 index 0000000000000000000000000000000000000000..a7104dae025156c766d26efe83841dbe4ebb4095 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/images/styles.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d96fa843982905bc6546ca79323ebdefb2faeed4674a8d9b17c549b435980a95 +size 1465961 diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/index.rst b/Isaac-GR00T/external_dependencies/robocasa/docs/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..035a3f21226f5401af3432aee4ce455ef9757bcc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/index.rst @@ -0,0 +1,54 @@ +.. RoboCasa documentation master file, created by + sphinx-quickstart on Tue Jun 18 15:47:35 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to RoboCasa's documentation! +==================================== + +.. toctree:: + :maxdepth: 1 + :caption: Introduction + + introduction/overview + introduction/installation + introduction/quick_start + introduction/codebase_overview + +.. toctree:: + :maxdepth: 1 + :caption: Use Cases + + use_cases/basic_usage + use_cases/downloading_datasets + use_cases/using_datasets + use_cases/collecting_human_demos + use_cases/creating_datasets + use_cases/mimicgen + use_cases/policy_learning + +.. toctree:: + :maxdepth: 1 + :caption: Tasks, Scenes, and Assets + + tasks_scenes_assets/atomic_tasks + tasks_scenes_assets/composite_tasks + tasks_scenes_assets/kitchen_scenes + tasks_scenes_assets/objects + +.. toctree:: + :maxdepth: 4 + :caption: Source API + + api/robocasa + + + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/basic_usage.md b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/basic_usage.md new file mode 100644 index 0000000000000000000000000000000000000000..bb7eb0b3c3fe125b16446da1a4327b9f996724ea --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/basic_usage.md @@ -0,0 +1,32 @@ +## Basic Usage + +The following script shows how to create evaluation environments and to run random rollouts: + +``` +from robocasa.environments import ALL_KITCHEN_ENVIRONMENTS +from robocasa.utils.dataset_registry import SINGLE_STAGE_TASK_DATASETS, MULTI_STAGE_TASK_DATASETS +from robocasa.utils.dataset_registry import get_ds_path +from robocasa.utils.env_utils import create_env, run_random_rollouts + +import numpy as np + +""" +Select a random task (that comes with an accompanying dataset) to run rollouts for. +Alternatively, sample *any* kitchen task in RoboCasa by replacing the following line with +env_name = np.random.choice(list(ALL_KITCHEN_ENVIRONMENTS)) +""" +env_name = np.random.choice( + list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS) +) + +# seed environment as needed. set seed=None to run unseeded +env = create_env(env_name=env_name, seed=0) + +# run rollouts with random actions and save video +info = run_random_rollouts( + env, num_rollouts=3, num_steps=100, video_path="/tmp/test.mp4" +) +print(info) +``` + +Separately we provide tools to run policy rollouts within robomimic. See the [policy learning page](../use_cases/policy_learning.html) for additional details. \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/codebase_overview.md b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/codebase_overview.md new file mode 100644 index 0000000000000000000000000000000000000000..19415c2778b3d61fc8f4a60bc356fc3ddd136c4f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/codebase_overview.md @@ -0,0 +1,23 @@ +# Codebase Overview + +Here is an outline of prominent components of the codebase: +- `robocasa/demos/`: interactive scripts to explore tasks and environments (see [quick start](../introduction/quick_start.html) section for details) +- `robocasa/environments/kitchen/`: all implementations for kitchen tasks + - `kitchen.py`: base class from which all kitchen tasks extend from + - `single_stage/`: implementations of all single-stage (aka "atomic") tasks + - `multi_stage/`: implementations of all multi-stage (aka “composite”) tasks +- `robocasa/scripts/`: utility scripts + - `download_kitchen_assets.py`: downloads all assets. called automatically during setup in setup.sh + - `download_datasets.py`: downloads datasets (see datasets section for details) + - `collect_demos.py`: collect demonstration trajectories for any task and environment +- `robocasa/utils/`: utilities + - `dataset_registry.py`: registry of all datasets (see [using datasets](../use_cases/using_datasets.html) for more details) +- `robocasa/models/`: assets and implementations for objects, fixtures, and scenes + - `objects/kitchen_objects.py`: registry for all object categories and groups + - `assets/objects/`: raw assets for all objects + - `fixtures/`: implementations of all fixture classes + - `assets/fixtures/`: raw assets for all environment fixtures + - `assets/fixtures/fixture_registry/`: registry for all fixture assets + - `scenes/`: implementations for constructing kitchen scenes + - `scene_registry.py`: registry of all kitchen scenes, including layouts and styles + - `assets/scenes/`: blueprints for kitchen scenes, including layouts and styles \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/getting_started.md b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/getting_started.md new file mode 100644 index 0000000000000000000000000000000000000000..ac3d9906b804db95e5ad52f6cd407619822cfb3c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/getting_started.md @@ -0,0 +1,50 @@ +# Quick Start + +
+

Attention Mac users!

+ +For these scripts, Mac users need to prepend the "python" command with "mj": `mjpython ...` +
+ +------- +### Explore kitchen layouts and styles +Explore kitchen layouts (G-shaped, U-shaped, etc) and kitchen styles (mediterranean, industrial, etc): +``` +python -m robocasa.demos.demo_kitchen_scenes +``` + +------- +### Play back sample demonstrations of tasks +Select a task and the script will render a human collected demonstration from our [datasets](../use_cases/datasets.html). Rendering can either be on-screen or off-screen as a video: +``` +python -m robocasa.demos.demo_tasks +``` + +
+

Off-screen rendering

+ +You can render videos of the demos off-screen by adding the `--render_offscreen` flag. Mac users will need to run the command as `python` instead of `mjpython`. + +
+ +------- +### Explore library of 2500+ objects +View and interact with both human-designed and AI-generated objects. Can also specify the path to a custom mjcf file. If no mjcf path specified, the script will show a random object: +``` +python -m robocasa.demos.demo_objects +``` +Note: by default this demo shows objaverse objects. To view AI-generated objects, add the flag `--obj_types aigen`. + +------- +### Teleoperate the robot +Control the robot directly, either through a keyboard controller or spacemouse. This script renders the robot semi-translucent in order to minimize occlusions and enable better visibility. Can specify environment, layout, and style via arguments to the script. Collected demonstrations will not be saved +``` +python -m robocasa.demos.demo_teleop +``` +Note: If using spacemouse: you may need to modify the product ID to your appropriate model, setting `SPACEMOUSE_PRODUCT_ID` in `robocasa/macros_private.py`. + +## Other useful sections + - [Overview of Datasets](../use_cases/datasets.html) + - [Overview of Atomic Tasks](../tasks_scenes_assets/atomic_tasks.html) + - [Overview of Composite Tasks](../tasks_scenes_assets/composite_tasks.html) + - [Training Policies on Datasets](../use_cases/policy_learning.html) \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/installation.md b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/installation.md new file mode 100644 index 0000000000000000000000000000000000000000..f98aea5f9f7cbf5dc2a7683252daf7a3cd015e21 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/installation.md @@ -0,0 +1,46 @@ + +# Installation + +RoboCasa works across all major computing platforms. The easiest way to set up is through the [Anaconda](https://www.anaconda.com/) package management system. Follow the instructions below to install: +1. Set up conda environment: + + ```sh + conda create -c conda-forge -n robocasa python=3.10 + ``` +2. Activate conda environment: + ```sh + conda activate robocasa + ``` +3. Clone and setup robosuite dependency: + +
+

Important!

+ The latest version of RoboCasa uses the master branch of robosuite. If you wish to use the previous version of RoboCasa (v0.1), please use the robocasa_v0.1 branch on robosuite. +
+ + ```sh + git clone https://github.com/ARISE-Initiative/robosuite + cd robosuite + pip install -e . + ``` +4. Clone and setup this repo: + + ```sh + cd .. + git clone https://github.com/robocasa/robocasa + cd robocasa + pip install -e . + ``` +
+

Installation troubleshooting

+ + If you encounter issues with installing the numpy or numba dependencies, please try installing through conda instead: `conda install -c numba numba=0.56.4 -y` + +
+ +5. Install the package and download assets: + ```sh + python robocasa/scripts/download_kitchen_assets.py # Caution: Assets to be downloaded are around 5GB. + python robocasa/scripts/setup_macros.py # Set up system variables. + ``` + diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/overview.md b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/overview.md new file mode 100644 index 0000000000000000000000000000000000000000..b730299863008e0b40b281db1899c35b3c6c150d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/overview.md @@ -0,0 +1,26 @@ + +# Overview + +**RoboCasa** is a large-scale simulation framework for training generally capable robots to perform everyday tasks. Four pillars underlie RoboCasa: +- **Diverse assets**, including 120 kitchen scenes and over 2,500 3D objects, created with the aid of generative AI tools +- **Cross-embodiment support** for mobile manipulators and humanoid robots +- **Diverse tasks** created with the guidance of large language models +- **High-quality human demonstrations** in addition to **massive robot datasets** created with automated trajectory tools + +

+ +

+ +This documentation guide contains information about installation, getting started, and additional use cases such as accessing datasets, policy learning, and API docs. + +### Citation + +```bibtex +@inproceedings{robocasa2024, + title={RoboCasa: Large-Scale Simulation of Everyday Tasks for Generalist Robots}, + author={Soroush Nasiriany and Abhiram Maddukuri and Lance Zhang and Adeet Parikh and Aaron Lo and Abhishek Joshi and Ajay Mandlekar and Yuke Zhu}, + booktitle={Robotics: Science and Systems (RSS)}, + year={2024} +} +``` + diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/quick_start.md b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/quick_start.md new file mode 100644 index 0000000000000000000000000000000000000000..d5bdf1565f197dc3f0a08c9368acda3a9fb0f63b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/introduction/quick_start.md @@ -0,0 +1,52 @@ +# Quick Start + +
+

Attention Mac users!

+ +For these scripts, Mac users need to prepend the "python" command with "mj": `mjpython ...` +
+ +------- +### Explore kitchen layouts and styles +Explore kitchen layouts (G-shaped, U-shaped, etc) and kitchen styles (mediterranean, industrial, etc): +``` +python -m robocasa.demos.demo_kitchen_scenes +``` + +------- +### Play back sample demonstrations of tasks +Select a task and the script will render a human collected demonstration from our [datasets](../use_cases/datasets.html). Rendering can either be on-screen or off-screen as a video: +``` +python -m robocasa.demos.demo_tasks +``` + +
+

Off-screen rendering

+ +You can render videos of the demos off-screen by adding the `--render_offscreen` flag. Mac users will need to run the command as `python` instead of `mjpython`. + +
+ +------- +### Explore library of 2500+ objects +View and interact with both human-designed and AI-generated objects. Can also specify the path to a custom mjcf file. If no mjcf path specified, the script will show a random object: +``` +python -m robocasa.demos.demo_objects +``` +Note: by default this demo shows objaverse objects. To view AI-generated objects, add the flag `--obj_types aigen`. + +------- +### Teleoperate the robot +Control the robot directly, either through a keyboard controller or spacemouse. This script renders the robot semi-translucent in order to minimize occlusions and enable better visibility. Can specify environment, layout, and style via arguments to the script. Collected demonstrations will not be saved +``` +python -m robocasa.demos.demo_teleop +``` +Note: If using spacemouse: you may need to modify the product ID to your appropriate model, setting `SPACEMOUSE_PRODUCT_ID` in `robocasa/macros_private.py`. + +## Other useful sections + - [Basic Usage](../use_cases/basic_usage.html) + - [Downloading Datasets](../use_cases/downloading_datasets.html) + - [Using Datasets](../use_cases/using_datasets.html) + - [Overview of Atomic Tasks](../tasks_scenes_assets/atomic_tasks.html) + - [Overview of Composite Tasks](../tasks_scenes_assets/composite_tasks.html) + - [Training Policies on Datasets](../use_cases/policy_learning.html) \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/make.bat b/Isaac-GR00T/external_dependencies/robocasa/docs/make.bat new file mode 100644 index 0000000000000000000000000000000000000000..747ffb7b3033659bdd2d1e6eae41ecb00358a45e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/requirements-docs.txt b/Isaac-GR00T/external_dependencies/robocasa/docs/requirements-docs.txt new file mode 100644 index 0000000000000000000000000000000000000000..49c7a1fa52266074dc3d0414f028502253acb4e4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/requirements-docs.txt @@ -0,0 +1,59 @@ +alabaster==0.7.16 +attrs==23.2.0 +Babel==2.15.0 +beautifulsoup4==4.12.3 +bleach==6.1.0 +certifi==2024.6.2 +charset-normalizer==3.3.2 +commonmark==0.9.1 +defusedxml==0.7.1 +docutils==0.17.1 +fastjsonschema==2.20.0 +idna==3.7 +imagesize==1.4.1 +importlib_metadata==7.2.1 +Jinja2==3.1.4 +jsonschema==4.22.0 +jsonschema-specifications==2023.12.1 +jupyter_client==8.6.2 +jupyter_core==5.7.2 +jupyterlab_pygments==0.3.0 +Markdown==3.6 +MarkupSafe==2.1.5 +mistune==3.0.2 +nbclient==0.10.0 +nbconvert==7.16.4 +nbformat==5.10.4 +nbsphinx==0.9.3 +packaging==24.1 +pandocfilters==1.5.1 +platformdirs==4.2.2 +pydata-sphinx-theme==0.8.1 +Pygments==2.18.0 +python-dateutil==2.9.0.post0 +PyYAML==6.0.1 +pyzmq==26.0.3 +recommonmark==0.7.1 +referencing==0.35.1 +requests==2.32.3 +rpds-py==0.18.1 +six==1.16.0 +snowballstemmer==2.2.0 +soupsieve==2.5 +Sphinx==4.1.0 +sphinx-book-theme==0.3.0 +sphinx-markdown-tables==0.0.17 +sphinx-rtd-theme==1.3.0 +sphinxcontrib-applehelp==1.0.1 +sphinxcontrib-devhelp==1.0.1 +sphinxcontrib-htmlhelp==2.0.0 +sphinxcontrib-jquery==4.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.1 +sphinxcontrib-serializinghtml==1.0.0 +tinycss2==1.3.0 +tornado==6.4.1 +traitlets==5.14.3 +urllib3==2.2.2 +webencodings==0.5.1 +zipp==3.19.2 diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/robocasa_logo.svg b/Isaac-GR00T/external_dependencies/robocasa/docs/robocasa_logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..7286ead2aae3e77655270fb38be835ba042f75bf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/robocasa_logo.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/atomic_tasks.md b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/atomic_tasks.md new file mode 100644 index 0000000000000000000000000000000000000000..e0dd4752d37ae92bb94d5ce91d5b3d36649ee96e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/atomic_tasks.md @@ -0,0 +1,75 @@ +## Atomic Tasks + +The current release includes 25 atomic tasks for systematically training policies across eight foundational skill families. The breakdown of these tasks across skill families is as follows: + +### Pick and place + +| Task | Description | Class File | +|:------------------------------|:----------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------| +| `PickPlaceCounterToCabinet` | Pick an object from the counter and place it inside the cabinet. The cabinet is already open. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceCabinetToCounter` | Pick an object from the cabinet and place it on the counter. The cabinet is already open. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceCounterToSink` | Pick an object from the counter and place it in the sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceSinkToCounter` | Pick an object from the sink and place it on the counter area next to the sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceCounterToMicrowave` | Pick an object from the counter and place it inside the microwave. The microwave door is already open. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceMicrowaveToCounter` | Pick an object from inside the microwave and place it on the counter. The microwave door is already open. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceCounterToStove` | Pick an object from the counter and place it in a pan or pot on the stove. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | +| `PickPlaceStoveToCounter` | Pick an object from the stove (via a pot or pan) and place it on (the plate on) the counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_pnp.py) | + + +### Opening and closing doors + +| Task | Description | Class File | +|:------------------|:-----------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------| +| `OpenSingleDoor` | Open a microwave door or a cabinet with a single door. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_doors.py) | +| `CloseSingleDoor` | Close a microwave door or a cabinet with a single door. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_doors.py) | +| `OpenDoubleDoor` | Open a cabinet with two opposite-facing doors. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_doors.py) | +| `CloseDoubleDoor` | Close a cabinet with two opposite-facing doors. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_doors.py) | + + +### Opening and closing drawers + +| Task | Description | Class File | +|:--------------|:-----------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------| +| `OpenDrawer` | Open a drawer. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_drawer.py) | +| `CloseDrawer` | Close a drawer. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_drawer.py) | + + +### Turning levers + +| Task | Description | Class File | +|:--------------------|:-----------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------| +| `TurnOnSinkFaucet` | Turn on the sink faucet to begin the flow of water. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_sink.py) | +| `TurnOffSinkFaucet` | Turn off the sink faucet to begin the flow of water. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_sink.py) | +| `TurnSinkSpout` | Turn the sink spout. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_sink.py) | + + +### Twisting knobs + +| Task | Description | Class File | +|:---------------|:-----------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------| +| `TurnOnStove` | Turn on a specified stove burner by twisting the respective stove knob. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_stove.py) | +| `TurnOffStove` | Turn off a specified stove burner by twisting the respective stove knob. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_stove.py) | + + +### Insertion + +| Task | Description | Class File | +|:-----------------|:-----------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------| +| `CoffeeSetupMug` | Pick the mug from the counter and insert it onto the coffee machine mug holder area. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_coffee.py) | +| `CoffeeServeMug` | Remove the mug from the coffee machine mug holder and place it on the counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_coffee.py) | + + +### Pressing buttons + +| Task | Description | Class File | +|:--------------------|:-----------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------| +| `CoffeePressButton` | Press the button on the coffee machine to pour coffee into the mug. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_coffee.py) | +| `TurnOnMicrowave` | Turn on the microwave by pressing the start button. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_microwave.py) | +| `TurnOffMicrowave` | Turn off the microwave by pressing the stop button. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_microwave.py) | + + +### Navigation + +| Task | Description | Class File | +|:------------------|:-----------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------| +| `NavigateKitchen` | Navigate to a specified appliance in the kitchen. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/single_stage/kitchen_navigate.py) | \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/composite_tasks.md b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/composite_tasks.md new file mode 100644 index 0000000000000000000000000000000000000000..5beb3755b42c64c5eb1254b7d28cd5ed040fde43 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/composite_tasks.md @@ -0,0 +1,207 @@ +## Composite Tasks + + +### Baking + +| Task | Description | Class File | +|:----------------------------|:--------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------| +| `PastryDisplay` | Place the pastries on the plates. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/baking/pastry_display.py) | +| `OrganizeBakingIngredients` | Place the eggs and milk next to the bowl. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/baking/organize_baking_ingredients.py) | +| `CupcakeCleanup` | Move the fresh-baked cupcake off the tray onto the counter, and place the bowl used for mixing into the sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/baking/cupcake_cleanup.py) | + + +### Boiling + +| Task | Description | Class File | +|:--------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------| +| `FillKettle` | Open the cabinet, pick the kettle from the cabinet, and place it in the sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/boiling/fill_kettle.py) | +| `HeatMultipleWater` | Pick the kettle from the cab and place it on a stove burner. Then pick the pot from the counter and place on another stove burner. Finally, turn both burners on. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/boiling/heat_multiple_water.py) | +| `VeggieBoil` | Pick up the pot and place it in the sink. Then turn on the sink faucet and let the pot fill up with water. Then turn the sink faucet off and move the pot to the stove. Lastly, turn on the stove and place the food in the pot for boiling. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/boiling/veggie_boil.py) | + + +### Brewing + +| Task | Description | Class File | +|:----------------|:------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------| +| `KettleBoiling` | Pick the kettle from the counter and place it on a stove burner. Then turn the burner on. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/brewing/kettle_boiling.py) | +| `ArrangeTea` | Pick the kettle from the counter and place it on the tray. Then pick the mug from the cabinet and place it on the tray. Then close the cabinet doors. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/brewing/arrange_tea.py) | +| `PrepareCoffee` | Pick the mug from the cabinet, place it under the coffee machine dispenser, and press the start button. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/brewing/prepare_coffee.py) | + + +### Chopping food + +| Task | Description | Class File | +|:--------------------------|:-----------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------| +| `ArrangeVegetables` | Pick the vegetables from the sink and place them on the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/chopping_food/arrange_vegetables.py) | +| `OrganizeVegetables` | Place the vegetables on separate cutting boards. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/chopping_food/organize_vegetables.py) | +| `BreadSetupSlicing` | Place all breads on the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/chopping_food/bread_setup_slicing.py) | +| `ClearingTheCuttingBoard` | Clear the non-vegetable object off the cutting board and place the vegetables onto it. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/chopping_food/clearing_the_cutting_board.py) | +| `MeatTransfer` | Retrieve the container from the cabinet, then place the raw meat into the container to avoid contamination. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/chopping_food/meat_transfer.py) | + + +### Clearing table + +| Task | Description | Class File | +|:------------------------------|:---------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------| +| `CondimentCollection` | Pick the condiments from the counter and place them in the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/condiment_collection.py) | +| `DessertAssembly` | Pick up the container with dessert and place it on the tray. Pick up the cupcake and place it on the tray. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/dessert_assembly.py) | +| `ClearingCleaningReceptacles` | Pick the receptacles and place them in the sink. Then turn on the water. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/clearing_cleaning_receptacles.py) | +| `CandleCleanup` | Pick the decorations from the dining table and place them in the open cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/candle_cleanup.py) | +| `FoodCleanup` | Pick the food items from the counter and place them in the cabinet. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/food_cleanup.py) | +| `DrinkwareConsolidation` | Pick the drinks from the island and place them in the open cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/drinkware_consolidation.py) | +| `BowlAndCup` | Place the cup inside the bowl on the island and move the bowl to any counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/clearing_table/bowl_and_cup.py) | + + +### Defrosting food + +| Task | Description | Class File | +|:--------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------| +| `ThawInSink` | Pick the object from the counter and place it in the sink. Then turn on the sink faucet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/defrosting_food/thaw_in_sink.py) | +| `MicrowaveThawing` | Pick the food from the counter and place it in the microwave. Then turn on the microwave. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/defrosting_food/microwave_thawing.py) | +| `QuickThaw` | Frozen meat rests on a plate on the counter. Retrieve the meat and place it in a pot on a burner. Then turn the burner on. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/defrosting_food/quick_thaw.py) | +| `DefrostByCategory` | There is a mixed pile of frozen fruits and vegetables on the counter. Locate all the frozen vegetables and place the items in a bowl on the counter. Take all the frozen fruits and defrost them in a running sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/defrosting_food/defrost_by_category.py) | + + +### Frying + +| Task | Description | Class File | +|:-----------------------|:----------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------| +| `SetupFrying` | Pick the pan from the cabinet and place it on the stove. Then turn on the stove burner for the pan. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/frying/setup_frying.py) | +| `FryingPanAdjustment` | Pick and place the pan from the current burner to another burner and turn the burner on. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/frying/frying_pan_adjustment.py) | +| `MealPrepStaging` | Place both pans onto different burners. Then place the vegetable and the meat on different pans. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/frying/meal_prep_staging.py) | +| `AssembleCookingArray` | Move the meat onto the pan on the stove. Then move the condiment and vegetable from the cabinet to the counter where the plate is. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/frying/assemble_cooking_array.py) | +| `SearingMeat` | Grab the pan from the cabinet and place it on the burner on the stove. Then place the meat on the stove and turn the burner on. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/frying/searing_meat.py) | + + +### Making toast + +| Task | Description | Class File | +|:------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------| +| `PrepareToast` | Pick the bread, place it on the cutting board, pick the jam, place it on the counter, and close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/making_toast/prepare_toast.py) | +| `SweetSavoryToastSetup` | Pick the avocado and bread from the counter and place them on the plate. Then pick the jam from the cabinet and place it next to the plate. Lastly, close the cabinet door. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/making_toast/sweet_savory_toast_setup.py) | +| `CheesyBread` | Pick up the wedge of cheese and place it on the slice of bread to prepare a simple cheese on bread dish. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/making_toast/cheesy_bread.py) | +| `BreadSelection` | From the different types of pastries on the counter, select a croissant and place it on the cutting board. Then retrieve a jar of jam from the cabinet and place it alongside the croissant on the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/making_toast/bread_selection.py) | + + +### Meat preparation + +| Task | Description | Class File | +|:---------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------| +| `PrepMarinatingMeat` | Pick the meat from its container and place it on the cutting board. Then pick the condiment from the cabinet and place it next to the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_marinating_meat.py) | +| `PrepForTenderizing` | Retrieve a rolling pin from the cabinet and place it next to the meat on the cutting board to prepare for tenderizing. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_for_tenderizing.py) | + + +### Mixing and blending + +| Task | Description | Class File | +|:----------------|:--------------------------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------| +| `SetupJuicing` | Open the cabinet, pick all fruits from the cabinet and place them on the counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/mixing_and_blending/setup_juicing.py) | +| `ColorfulSalsa` | Place the avocado, onion, tomato and bell pepper on the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/mixing_and_blending/colorful_salsa.py) | +| `SpicyMarinade` | Open the cabinet. Place the bowl and condiment on the counter. Then place the lime and garlic on the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/mixing_and_blending/spicy_marinade.py) | + + +### Reheating food + +| Task | Description | Class File | +|:-------------------|:---------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `HeatMug` | Pick the mug from the cabinet and place it inside the microwave. Then close the microwave. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/reheating_food/heat_mug.py) | +| `SimmeringSauce` | Place the pan on the burner on the stove. Then place the tomato and the onion in the pan and turn on the burner. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/reheating_food/simmering_sauce.py) | +| `WaffleReheat` | Open the microwave, place the bowl with waffle inside the microwave, then close the microwave door and turn it on. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/reheating_food/waffle_reheat.py) | +| `WarmCroissant` | Pick the croissant and place it on the pan. Then turn on the stove to warm the croissant. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/reheating_food/warm_croissant.py) | +| `MakeLoadedPotato` | Retrieve the reheated potato from the microwave, then place it on the cutting board along with cheese and a bottle of condiment. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/reheating_food/make_loaded_potato.py) | + + +### Restocking supplies + +| Task | Description | Class File | +|:-------------------------|:-------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------| +| `RestockPantry` | Pick the cans from the counter and place them in their designated side in the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_pantry.py) | +| `StockingBreakfastFoods` | Pick the packaged foods from the counter and place them in the cabinets closest to them. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/restocking_supplies/stocking_breakfast_foods.py) | +| `RestockBowls` | Open the cabinet. Pick the bowls from the counter and place them in the cabinet directly in front. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_bowls.py) | +| `BeverageSorting` | Sort all alcoholic drinks to one cabinet, and non-alcoholic drinks to the other. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/restocking_supplies/beverage_sorting.py) | + + +### Sanitize surface + +| Task | Description | Class File | +|:---------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------| +| `PushUtensilsToSink` | Push the utensils into the sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/sanitize_surface/push_utensils_to_sink.py) | +| `PrepForSanitizing` | Pick the cleaning supplies from the cabinet and place them on the counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/sanitize_surface/prep_for_sanitizing.py) | +| `CleanMicrowave` | Open the microwave. Then pick the sponge from the counter and place it in the microwave. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/sanitize_surface/clean_microwave.py) | +| `CountertopCleanup` | Pick the fruit and vegetable from the counter and place them in the cabinet. Then open the drawer and pick the cleaner and sponge from the drawer and place them on the counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/sanitize_surface/countertop_cleanup.py) | + + +### Serving food + +| Task | Description | Class File | +|:---------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------| +| `WineServingPrep` | Open the cabinet directly in front. Then move the alcohol and the cup to the counter with the decoration on it. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/serving_food/wine_serving_prep.py) | +| `ServeSteak` | Pick up the pan with the steak in it and place it on the dining table. Then place the steak on the plate. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/serving_food/serve_steak.py) | +| `PlaceFoodInBowls` | Pick both bowls and place them on the counter. Then pick the food and place it in one bowl and pick the other food and place it in the other bowl. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/serving_food/place_food_in_bowls.py) | +| `DessertUpgrade` | Move the dessert items from the plate to the tray. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/serving_food/dessert_upgrade.py) | +| `PrepareSoupServing` | Open the cabinet and move the ladle to the pot. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/serving_food/prepare_soup_serving.py) | +| `PanTransfer` | Pick up the pan and dump the vegetables in it onto the plate. Then return the pan to the stove. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/serving_food/pan_transfer.py) | + + +### Setting the table + +| Task | Description | Class File | +|:-----------------------|:----------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------| +| `DateNight` | Pick up the decoration and the alcohol in the cabinet and move them to the dining counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/setting_the_table/date_night.py) | +| `ArrangeBreadBasket` | Open the cabinet, pick up the bread from the cabinet and place it in the bowl. Then move the bowl to the dining counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/setting_the_table/arrange_bread_basket.py) | +| `SeasoningSpiceSetup` | Move the condiments from the cabinet to the dining counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/setting_the_table/seasoning_spice_setup.py) | +| `SetBowlsForSoup` | Move the bowls from the cabinet to the plates on the dining table. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/setting_the_table/set_bowls_for_soup.py) | +| `BeverageOrganization` | Move the drinks to the dining counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/setting_the_table/beverage_organization.py) | +| `SizeSorting` | Stack the cups/bowls from largest to smallest. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/setting_the_table/size_sorting.py) | + + +### Snack preparation + +| Task | Description | Class File | +|:--------------------|:----------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------| +| `CerealAndBowl` | Open the cabinet. Pick the cereal and bowl from the cabinet and place them on the counter. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/snack_preparation/cereal_and_bowl.py) | +| `BreadAndCheese` | Place the bread and cheese on the cutting board. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/snack_preparation/bread_and_cheese.py) | +| `YogurtDelightPrep` | Place the yogurt and fruit onto the counter. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/snack_preparation/yogurt_delight_prep.py) | +| `MakeFruitBowl` | Open the cabinet. Pick the fruits from the cabinet and place them into the bowl. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/snack_preparation/make_fruit_bowl.py) | +| `VeggieDipPrep` | Place the two vegetables and a bowl onto the tray for setting up a vegetable dip station. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/snack_preparation/veggie_dip_prep.py) | + + +### Steaming food + +| Task | Description | Class File | +|:--------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------| +| `SteamInMicrowave` | Pick the vegetable from the sink and place it in the bowl. Then pick the bowl and place it in the microwave. Then close the microwave door and press the start button. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/steaming_food/steam_in_microwave.py) | +| `MultistepSteaming` | Turn on the sink faucet. Then move the vegetable from the counter to the sink. Turn of the sink. Move the vegetable from the sink to the pot next to the stove. Finally, move the pot to the appropriate burner. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/steaming_food/multistep_steaming.py) | +| `SteamVegetables` | Place vegetables into the pot based on the amount of time it would take to steam each, e.g. potatoes and carrots would take the longest. Then turn off the burner beneath the pot. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/steaming_food/steam_vegetables.py) | + + +### Tidying cabinets and drawers + +| Task | Description | Class File | +|:---------------------------|:----------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `OrganizeCleaningSupplies` | Open the cabinet. Pick the cleaner and place it next to the sink. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/organize_cleaning_supplies.py) | +| `DrawerUtensilSort` | Open the left drawer and push the utensils inside it. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/drawer_utensil_sort.py) | +| `PantryMishap` | Place the vegetable on the counter and the canned food in the drawer. Close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/pantry_mishap.py) | +| `ShakerShuffle` | Pick and place the shaker into the drawer. Then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/shaker_shuffle.py) | +| `SnackSorting` | Place the bar in the bowl and close the drawer. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/snack_sorting.py) | + + +### Washing dishes + +| Task | Description | Class File | +|:-------------------|:------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------| +| `StackBowlsInSink` | Stack the bowls in the sink. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_dishes/stack_bowls.py) | +| `PreSoakPan` | Pick the pan and sponge and place them into the sink. Then turn on the water. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_dishes/pre_soak_pan.py) | +| `SortingCleanup` | Pick the mug and place it in the sink. Pick the bowl and place it in the cabinet and then close the cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_dishes/sorting_cleanup.py) | +| `DryDrinkware` | A wet mug is on the counter and needs to be dried. Pick it up and place it upside down in the open cabinet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_drinkware.py) | +| `DryDishes` | Pick the cup and bowl from the sink and place them on the counter for drying. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_dishes.py) | + + +### Washing fruits and vegetables + +| Task | Description | Class File | +|:----------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------| +| `PrewashFoodAssembly` | Pick the fruit/vegetable from the cabinet and place it in the bowl. Then pick the bowl and place it in the sink. Then turn on the sink facuet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/prewash_food_assembly.py) | +| `ClearClutter` | Pick up the fruits and vegetables and place them in the sink. Turn on the sink faucet to wash them. Then turn the sink off and put them in the tray. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/clear_clutter.py) | +| `DrainVeggies` | Dump the vegetable from the pot into the sink. Then turn on the water and wash the vegetable. Then turn off the water and put the vegetable back in the pot. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/drain_veggies.py) | +| `AfterwashSorting` | Pick the foods of the same kind from the sink and place them in one bowl. Place the other food in the other bowl. Then turn off the sink faucet. | [Source](https://github.com/robocasa/robocasa/blob/main/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/afterwash_sorting.py) | \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/kitchen_scenes.md b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/kitchen_scenes.md new file mode 100644 index 0000000000000000000000000000000000000000..ce20b15fb39ca469d4a61e4b9c9d025656df2243 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/kitchen_scenes.md @@ -0,0 +1,28 @@ +# Kitchen Scenes + +RoboCasa offers a large array of kitchen scenes with fully interactive cabinets, drawers, and appliances. +We model 10 layouts ranging from basic designs found in apartments to more elaborate designs found in high-end homes. Each layout can be configured to take on one of 12 unique styles, resulting in 120 kitchen scenes. See the breakdown of layouts and styles as follows. + +Environments can be initialized with specific layouts and styles via integer enums defined [here](https://github.com/robocasa/robocasa/blob/main/robocasa/models/scenes/scene_registry.py). For example: +``` +from robocasa.utils.env_utils import create_env +from robocasa.models.scenes.scene_registry import LayoutType, StyleType + +env = create_env( + env_name="PnPCounterToCab", + layout_ids=[LayoutType.ONE_WALL_SMALL, LayoutType.L_SHAPED_LARGE, LayoutType.WRAPAROUND], + style_ids=[StyleType.COASTAL, StyleType.FARMHOUSE, StyleType.RUSTIC], +) +``` + +## Layouts + +Layouts are configured by setting the arrangment of fixtures (cabinets, microwaves, counters, etc.) in a yaml file [**[Source]**](https://github.com/robocasa/robocasa/tree/main/robocasa/models/assets/scenes/kitchen_layouts). + +![Kitchen Layouts](../images/layouts.png) + +## Styles + +Styles are configured by setting relevant textures and fixture attributes (cabinet handle types, door types, coffee machine types, etc) in a yaml file [**[Source]**](https://github.com/robocasa/robocasa/tree/main/robocasa/models/assets/scenes/kitchen_styles). + +![Kitchen Styles](../images/styles.png) diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/object_categories.md b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/object_categories.md new file mode 100644 index 0000000000000000000000000000000000000000..f9e5221b743234d58600f16e4d9f514fdedda0be --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/object_categories.md @@ -0,0 +1,159 @@ +## Object Categories + +RoboCasa offers over 2,500 objects across over 150 object categories. Some are sourced from [Objaverse 1.0](https://objaverse.allenai.org/objaverse-1.0), while the remianing majority are AI generated from [Luma.ai](https://luma.ai/). See the breakdown of object categories as follows: + +| Category | Groups | Objaverse Instances | AI Generated Instances | +|:--------------------|:-------------------------------|----------------------:|-------------------------:| +| liquor | drink, alcohol | 12 | 10 | +| apple | fruit | 22 | 10 | +| avocado | vegetable | 7 | 11 | +| bagel | bread_food | 9 | 10 | +| bagged_food | packaged_food | 9 | 9 | +| baguette | bread_food | 6 | 18 | +| banana | fruit | 23 | 10 | +| bar | packaged_food | 10 | 7 | +| bar_soap | cleaner | 4 | 8 | +| beer | drink, alcohol | 17 | 9 | +| bell_pepper | vegetable | 4 | 7 | +| bottled_drink | drink | 5 | 14 | +| bottled_water | drink | 14 | 15 | +| bowl | receptacle, stackable | 20 | 4 | +| boxed_drink | drink | 7 | 15 | +| boxed_food | packaged_food | 10 | 6 | +| bread | bread_food | 20 | 12 | +| broccoli | vegetable | 3 | 15 | +| cake | sweets | 10 | 7 | +| can | drink | 14 | 7 | +| candle | decoration | 15 | 10 | +| canned_food | packaged_food | 16 | 7 | +| carrot | vegetable | 7 | 9 | +| cereal | packaged_food | 14 | 9 | +| cheese | dairy | 9 | 13 | +| chips | packaged_food | 16 | 7 | +| chocolate | sweets | 15 | 8 | +| coffee_cup | drink | 18 | 6 | +| condiment_bottle | condiment | 3 | 10 | +| corn | vegetable | 4 | 8 | +| croissant | pastry | 10 | 7 | +| cucumber | vegetable | 6 | 12 | +| cup | receptacle, stackable | 4 | 18 | +| cupcake | sweets | 16 | 15 | +| cutting_board | receptacle | 12 | 11 | +| donut | sweets, pastry | 16 | 8 | +| egg | dairy | 13 | 15 | +| eggplant | vegetable | 5 | 7 | +| fish | meat | 12 | 8 | +| fork | utensil | 12 | 10 | +| garlic | vegetable | 5 | 13 | +| hot_dog | cooked_food | 7 | 11 | +| jam | packaged_food | 7 | 19 | +| jug | receptacle | 9 | 8 | +| ketchup | condiment | 10 | 10 | +| kettle_electric | receptacle | 9 | 6 | +| kettle_non_electric | receptacle | 18 | 7 | +| kiwi | fruit | 7 | 11 | +| knife | utensil | 27 | 11 | +| ladle | utensil | 5 | 9 | +| lemon | vegetable | 18 | 12 | +| lime | vegetable | 4 | 9 | +| mango | fruit | 15 | 8 | +| milk | dairy, drink | 8 | 9 | +| mug | receptacle, stackable | 18 | 10 | +| mushroom | vegetable | 16 | 9 | +| onion | vegetable | 10 | 7 | +| orange | fruit | 12 | 7 | +| pan | receptacle | 20 | 3 | +| pot | receptacle | 3 | 1 | +| peach | fruit | 7 | 11 | +| pear | fruit | 16 | 14 | +| plate | receptacle | 18 | 7 | +| potato | vegetable | 19 | 14 | +| rolling_pin | tool | 6 | 7 | +| scissors | tool | 11 | 7 | +| shaker | condiment | 4 | 7 | +| soap_dispenser | cleaner | 6 | 11 | +| spatula | utensil | 14 | 11 | +| sponge | cleaner | 8 | 10 | +| spoon | utensil | 24 | 8 | +| spray | cleaner | 3 | 13 | +| squash | vegetable | 9 | 7 | +| steak | meat | 11 | 10 | +| sweet_potato | vegetable | 3 | 12 | +| tangerine | fruit | 7 | 13 | +| teapot | receptacle | 11 | 7 | +| tomato | vegetable | 8 | 9 | +| tray | receptacle | 11 | 11 | +| waffle | sweets | 4 | 7 | +| water_bottle | drink | 22 | 7 | +| wine | drink, alcohol | 12 | 7 | +| yogurt | dairy, packaged_food | 3 | 7 | +| dates | fruit | 0 | 13 | +| lemonade | drink | 0 | 6 | +| walnut | none | 0 | 8 | +| cheese_grater | tool | 0 | 9 | +| syrup_bottle | condiment | 0 | 13 | +| scallops | meat | 0 | 16 | +| candy | sweets | 0 | 11 | +| whisk | utensil | 0 | 9 | +| pitcher | receptacle | 0 | 13 | +| ice_cream | sweets | 0 | 13 | +| cherry | fruit | 0 | 12 | +| peanut_butter | packaged_food | 0 | 13 | +| thermos | drink | 0 | 13 | +| ham | meat | 0 | 9 | +| dumpling | meat, cooked_food | 0 | 22 | +| cabbage | vegetable | 0 | 17 | +| lettuce | vegetable | 0 | 9 | +| tongs | tool | 0 | 7 | +| ginger | vegetable | 0 | 7 | +| ice_cube_tray | receptacle | 0 | 9 | +| shrimp | meat | 0 | 9 | +| cantaloupe | fruit | 0 | 14 | +| honey_bottle | packaged_food | 0 | 16 | +| grapes | fruit | 0 | 14 | +| spaghetti_box | packaged_food | 0 | 11 | +| chili_pepper | vegetable | 0 | 8 | +| celery | vegetable | 0 | 9 | +| burrito | cooked_food | 0 | 12 | +| olive_oil_bottle | packaged_food | 0 | 15 | +| kebabs | cooked_food | 0 | 15 | +| bottle_opener | tool | 0 | 16 | +| chicken_breast | meat | 0 | 12 | +| jello_cup | packaged_food | 0 | 9 | +| lobster | meat | 0 | 11 | +| brussel_sprout | vegetable | 0 | 14 | +| sushi | meat | 0 | 13 | +| baking_sheet | receptacle | 0 | 8 | +| wine_glass | receptacle | 0 | 7 | +| asparagus | vegetable | 0 | 13 | +| lamb_chop | meat | 0 | 8 | +| pickle | vegetable | 0 | 7 | +| bacon | meat | 0 | 11 | +| canola_oil | packaged_food | 0 | 14 | +| strawberry | fruit | 0 | 10 | +| watermelon | fruit | 0 | 12 | +| pizza_cutter | tool | 0 | 9 | +| pomegranate | fruit | 0 | 7 | +| apricot | fruit | 0 | 9 | +| beet | vegetable | 0 | 11 | +| radish | vegetable | 0 | 10 | +| salsa | packaged_food | 0 | 13 | +| artichoke | vegetable | 0 | 10 | +| scone | pastry, bread_food | 0 | 12 | +| hamburger | cooked_food | 0 | 16 | +| raspberry | fruit | 0 | 8 | +| tacos | cooked_food | 0 | 8 | +| vinegar | packaged_food, condiment | 0 | 11 | +| zucchini | vegetable | 0 | 11 | +| pork_loin | meat | 0 | 15 | +| pork_chop | meat | 0 | 16 | +| sausage | meat | 0 | 16 | +| coconut | fruit | 0 | 15 | +| cauliflower | vegetable | 0 | 10 | +| lollipop | sweets | 0 | 9 | +| salami | meat | 0 | 13 | +| butter_stick | dairy | 0 | 13 | +| can_opener | tool | 0 | 6 | +| tofu | none | 0 | 17 | +| pineapple | fruit | 0 | 8 | +| skewers | meat, cooked_food | 0 | 6 | \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/objects.md b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/objects.md new file mode 100644 index 0000000000000000000000000000000000000000..2ccba1130bd6d43a56bf7b3face2b5fea29eab91 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/tasks_scenes_assets/objects.md @@ -0,0 +1,159 @@ +## Objects + +RoboCasa offers over 2,500 objects across over 150 object categories. Some are sourced from [Objaverse 1.0](https://objaverse.allenai.org/objaverse-1.0), while the remianing majority are AI generated from [Luma.ai](https://luma.ai/). See the breakdown of object categories as follows: + +| Category | Groups | Objaverse Instances | AI Generated Instances | +|:--------------------|:-------------------------------|----------------------:|-------------------------:| +| liquor | drink, alcohol | 12 | 10 | +| apple | fruit | 22 | 10 | +| avocado | vegetable | 7 | 11 | +| bagel | bread_food | 9 | 10 | +| bagged_food | packaged_food | 9 | 9 | +| baguette | bread_food | 6 | 18 | +| banana | fruit | 23 | 10 | +| bar | packaged_food | 10 | 7 | +| bar_soap | cleaner | 4 | 8 | +| beer | drink, alcohol | 17 | 9 | +| bell_pepper | vegetable | 4 | 7 | +| bottled_drink | drink | 5 | 14 | +| bottled_water | drink | 14 | 15 | +| bowl | receptacle, stackable | 20 | 4 | +| boxed_drink | drink | 7 | 15 | +| boxed_food | packaged_food | 10 | 6 | +| bread | bread_food | 20 | 12 | +| broccoli | vegetable | 3 | 15 | +| cake | sweets | 10 | 7 | +| can | drink | 14 | 7 | +| candle | decoration | 15 | 10 | +| canned_food | packaged_food | 16 | 7 | +| carrot | vegetable | 7 | 9 | +| cereal | packaged_food | 14 | 9 | +| cheese | dairy | 9 | 13 | +| chips | packaged_food | 16 | 7 | +| chocolate | sweets | 15 | 8 | +| coffee_cup | drink | 18 | 6 | +| condiment_bottle | condiment | 3 | 10 | +| corn | vegetable | 4 | 8 | +| croissant | pastry | 10 | 7 | +| cucumber | vegetable | 6 | 12 | +| cup | receptacle, stackable | 4 | 18 | +| cupcake | sweets | 16 | 15 | +| cutting_board | receptacle | 12 | 11 | +| donut | sweets, pastry | 16 | 8 | +| egg | dairy | 13 | 15 | +| eggplant | vegetable | 5 | 7 | +| fish | meat | 12 | 8 | +| fork | utensil | 12 | 10 | +| garlic | vegetable | 5 | 13 | +| hot_dog | cooked_food | 7 | 11 | +| jam | packaged_food | 7 | 19 | +| jug | receptacle | 9 | 8 | +| ketchup | condiment | 10 | 10 | +| kettle_electric | receptacle | 9 | 6 | +| kettle_non_electric | receptacle | 18 | 7 | +| kiwi | fruit | 7 | 11 | +| knife | utensil | 27 | 11 | +| ladle | utensil | 5 | 9 | +| lemon | vegetable | 18 | 12 | +| lime | vegetable | 4 | 9 | +| mango | fruit | 15 | 8 | +| milk | dairy, drink | 8 | 9 | +| mug | receptacle, stackable | 18 | 10 | +| mushroom | vegetable | 16 | 9 | +| onion | vegetable | 10 | 7 | +| orange | fruit | 12 | 7 | +| pan | receptacle | 20 | 3 | +| pot | receptacle | 3 | 1 | +| peach | fruit | 7 | 11 | +| pear | fruit | 16 | 14 | +| plate | receptacle | 18 | 7 | +| potato | vegetable | 19 | 14 | +| rolling_pin | tool | 6 | 7 | +| scissors | tool | 11 | 7 | +| shaker | condiment | 4 | 7 | +| soap_dispenser | cleaner | 6 | 11 | +| spatula | utensil | 14 | 11 | +| sponge | cleaner | 8 | 10 | +| spoon | utensil | 24 | 8 | +| spray | cleaner | 3 | 13 | +| squash | vegetable | 9 | 7 | +| steak | meat | 11 | 10 | +| sweet_potato | vegetable | 3 | 12 | +| tangerine | fruit | 7 | 13 | +| teapot | receptacle | 11 | 7 | +| tomato | vegetable | 8 | 9 | +| tray | receptacle | 11 | 11 | +| waffle | sweets | 4 | 7 | +| water_bottle | drink | 22 | 7 | +| wine | drink, alcohol | 12 | 7 | +| yogurt | dairy, packaged_food | 3 | 7 | +| dates | fruit | 0 | 13 | +| lemonade | drink | 0 | 6 | +| walnut | none | 0 | 8 | +| cheese_grater | tool | 0 | 9 | +| syrup_bottle | condiment | 0 | 13 | +| scallops | meat | 0 | 16 | +| candy | sweets | 0 | 11 | +| whisk | utensil | 0 | 9 | +| pitcher | receptacle | 0 | 13 | +| ice_cream | sweets | 0 | 13 | +| cherry | fruit | 0 | 12 | +| peanut_butter | packaged_food | 0 | 13 | +| thermos | drink | 0 | 13 | +| ham | meat | 0 | 9 | +| dumpling | meat, cooked_food | 0 | 22 | +| cabbage | vegetable | 0 | 17 | +| lettuce | vegetable | 0 | 9 | +| tongs | tool | 0 | 7 | +| ginger | vegetable | 0 | 7 | +| ice_cube_tray | receptacle | 0 | 9 | +| shrimp | meat | 0 | 9 | +| cantaloupe | fruit | 0 | 14 | +| honey_bottle | packaged_food | 0 | 16 | +| grapes | fruit | 0 | 14 | +| spaghetti_box | packaged_food | 0 | 11 | +| chili_pepper | vegetable | 0 | 8 | +| celery | vegetable | 0 | 9 | +| burrito | cooked_food | 0 | 12 | +| olive_oil_bottle | packaged_food | 0 | 15 | +| kebabs | cooked_food | 0 | 15 | +| bottle_opener | tool | 0 | 16 | +| chicken_breast | meat | 0 | 12 | +| jello_cup | packaged_food | 0 | 9 | +| lobster | meat | 0 | 11 | +| brussel_sprout | vegetable | 0 | 14 | +| sushi | meat | 0 | 13 | +| baking_sheet | receptacle | 0 | 8 | +| wine_glass | receptacle | 0 | 7 | +| asparagus | vegetable | 0 | 13 | +| lamb_chop | meat | 0 | 8 | +| pickle | vegetable | 0 | 7 | +| bacon | meat | 0 | 11 | +| canola_oil | packaged_food | 0 | 14 | +| strawberry | fruit | 0 | 10 | +| watermelon | fruit | 0 | 12 | +| pizza_cutter | tool | 0 | 9 | +| pomegranate | fruit | 0 | 7 | +| apricot | fruit | 0 | 9 | +| beet | vegetable | 0 | 11 | +| radish | vegetable | 0 | 10 | +| salsa | packaged_food | 0 | 13 | +| artichoke | vegetable | 0 | 10 | +| scone | pastry, bread_food | 0 | 12 | +| hamburger | cooked_food | 0 | 16 | +| raspberry | fruit | 0 | 8 | +| tacos | cooked_food | 0 | 8 | +| vinegar | packaged_food, condiment | 0 | 11 | +| zucchini | vegetable | 0 | 11 | +| pork_loin | meat | 0 | 15 | +| pork_chop | meat | 0 | 16 | +| sausage | meat | 0 | 16 | +| coconut | fruit | 0 | 15 | +| cauliflower | vegetable | 0 | 10 | +| lollipop | sweets | 0 | 9 | +| salami | meat | 0 | 13 | +| butter_stick | dairy | 0 | 13 | +| can_opener | tool | 0 | 6 | +| tofu | none | 0 | 17 | +| pineapple | fruit | 0 | 8 | +| skewers | meat, cooked_food | 0 | 6 | \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/basic_usage.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/basic_usage.md new file mode 100644 index 0000000000000000000000000000000000000000..3ec44b05ec01a5cca0c7f90565c9d34b2f667dc1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/basic_usage.md @@ -0,0 +1,60 @@ +## Basic Usage + +### Gym interface +We provide a gym-like interface to run rollouts: +
+

Attention Mac users!

+Mac users who wish to run this example need to prepend the “python” command with “mj”: mjpython +
+ +```py +from robocasa.environments import ALL_KITCHEN_ENVIRONMENTS +from robocasa.utils.env_utils import create_env, run_random_rollouts +import numpy as np + +# choose random task +env_name = np.random.choice(list(ALL_KITCHEN_ENVIRONMENTS)) + +env = create_env( + env_name=env_name, + render_onscreen=True, + seed=0, # set seed=None to run unseeded +) + +# reset the environment +env.reset() + +# get task language +lang = env.get_ep_meta()["lang"] +print("Instruction:", lang) + +for i in range(500): + action = np.random.randn(*env.action_spec[0].shape) * 0.1 + obs, reward, done, info = env.step(action) # take action in the environment + env.render() # render on display +``` + +### Offscreen rollouts +You can also run rollouts and save videos: +```py +from robocasa.environments import ALL_KITCHEN_ENVIRONMENTS +from robocasa.utils.env_utils import create_env, run_random_rollouts +import numpy as np + +# choose random task +env_name = np.random.choice(list(ALL_KITCHEN_ENVIRONMENTS)) + +env = create_env( + env_name=env_name, + render_onscreen=False, + seed=0, # set seed=None to run unseeded +) + +# run rollouts with random actions and save video +info = run_random_rollouts( + env, num_rollouts=3, num_steps=100, video_path="/tmp/test.mp4" +) +print(info) +``` + +Separately we provide tools to run policy rollouts within robomimic. See the [policy learning page](../use_cases/policy_learning.html) for additional details. \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/creating_datasets.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/creating_datasets.md new file mode 100644 index 0000000000000000000000000000000000000000..7a534fb6d7a0f005b558f02e42ed4863b5760267 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/creating_datasets.md @@ -0,0 +1,44 @@ +# Creating Datasets + +## Collecting human demonstrations +You can use the collect_demos.py script to collect demonstrations: +``` +python robocasa/scripts/collect_demos.py --env +``` + +
+

Attention Mac users

+ +Mac users must prepend this script with `mj`, ie. `mjpython` + +
+ +You can either control the robot with a [spacemouse](https://3dconnexion.com/us/product/spacemouse-compact/) (`--device spacemouse`) or the keyboard (`--device keyboard`). A spacemouse is recommended. + +This will save a raw dataset. Follow the steps in the next section to extract image observations for this dataset. + +## Extracting observations +To extract observations from an existing dataset, you can run: +``` +OMP_NUM_THREADS=1 MPI_NUM_THREADS=1 MKL_NUM_THREADS=1 OPENBLAS_NUM_THREADS=1 python robocasa/scripts/dataset_states_to_obs.py --dataset +``` +This script will generate a new dataset with the suffix `_im128.hdf5` in the same directory as `--dataset`. + +
+

Image resolution

+ +You can override the default image resolution by setting the flags `--camera_height` and `--camera_width`. + +
+ +
+

Visual randomization

+ +You can add the flag `--generative_textures` to render images with AI-generated environment textures, and `--randomize_cameras` to randomize camera viewpoints for rendering. + +
+ +
+

Warning!

+This observation extraction script may drop a few demonstrations due to subprocesses failing. To minimize this issue you can run the script with the flag --num_procs 1 +
\ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/downloading_datasets.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/downloading_datasets.md new file mode 100644 index 0000000000000000000000000000000000000000..139a993a1640d3a167cc1035d0471fe2f3c8f46c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/downloading_datasets.md @@ -0,0 +1,30 @@ +# Downloading Datasets + +RoboCasa comes with a large selection of demonstrations to faciliate training agents. We provide: +- **human demonstrations**: across all 25 atomic tasks and a subset of composite tasks, with 50 demonstrations per task. +- **machine-generated demonstrations** from [MimicGen](https://mimicgen.github.io/): across 24 atomic tasks, with 3000 demonstrations per task. + +
+

Dataset storage location

+ +By default, all datasets are stored under `datasets/` in the root robocasa directory. You can change the location for datasets by setting `DATASET_BASE_PATH` in `robocasa/macros_private.py`. + +
+ +Here are a few ways to download the datasets: +``` +# downloads all human datasets with images +python -m robocasa.scripts.download_datasets --ds_types human_im + +# lite download: download human datasets without images +python -m robocasa.scripts.download_datasets --ds_types human_raw + +# downloads all MimicGen datasets with images +python -m robocasa.scripts.download_datasets --ds_types mg_im +``` + +Additionally you can specify the following optional arguments: +``` +--tasks : downloads datasets for specific tasks, eg, --tasks PnPCounterToCab ArrangeVegetables +--overwrite: overwrites existing datasets +``` diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/evaluation.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/evaluation.md new file mode 100644 index 0000000000000000000000000000000000000000..26fdd9f025729afb9a3d7f71c55d227671adec81 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/evaluation.md @@ -0,0 +1,30 @@ +# Evaluation + +## Running Rollouts +The following script shows how to create evaluation environments and to run random rollouts: +``` +from robocasa.environments import ALL_KITCHEN_ENVIRONMENTS +from robocasa.utils.dataset_registry import SINGLE_STAGE_TASK_DATASETS, MULTI_STAGE_TASK_DATASETS +from robocasa.utils.dataset_registry import get_ds_path +from robocasa.utils.eval_utils import create_eval_env, run_random_rollouts + +import numpy as np + +""" +Select a random task (that comes with an accompanying dataset) to run rollouts for. +Alternatively, sample *any* kitchen task in RoboCasa by replacing the following line with +env_name = np.random.choice(list(ALL_KITCHEN_ENVIRONMENTS)) +""" +env_name = np.random.choice( + list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS) +) + +# seed environment as needed. set seed=None to run unseeded +env = create_eval_env(env_name=env_name, seed=0) +info = run_random_rollouts( + env, num_rollouts=3, num_steps=100, video_path="/tmp/test.mp4" +) +print(info) +``` + +Separately we provide tools to run policy rollouts within robomimic. See the [policy learning page](../use_cases/policy_learning.html) for additional details. \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/mimicgen.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/mimicgen.md new file mode 100644 index 0000000000000000000000000000000000000000..7a7bd97f333042824a1cdf10b5222e052408d288 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/mimicgen.md @@ -0,0 +1,39 @@ +## Generating Data with MimicGen + +Given a modest number of source demonstrations, we offer the ability to syntehsize new trajectories with [MimicGen](https://mimicgen.github.io/). + +### Installation +1. Clone and setup MimicGen under the `experimental/robocasa` branch: + + ```sh + git clone https://github.com/NVlabs/mimicgen -b experimental/robocasa + cd mimicgen + pip install -e . + ``` + +2. Setup the robomimic dependency: + ```sh + cd .. + git clone https://github.com/ARISE-Initiative/robomimic -b robocasa + cd robomimic + pip install -e . + ``` + +### Generate data for existing tasks +We have set up MimicGen for 24/25 existing atomic tasks. Generating demonstration datasets for these tasks is a 3 step process, which we illustrate for the `PnPCounterToSink` task: + +(Note: these commands assume that datasets are stored under `~/robocasa/datasets`) + +1. Extract subtask meta data: + ```sh + python mimicgen/scripts/prepare_src_dataset.py --dataset ~/robocasa/datasets/v0.1/single_stage/kitchen_pnp/PnPCounterToSink/2024-04-25/demo.hdf5 + ``` +2. Generate demonstartions: + ```sh + python mimicgen/scripts/generate_dataset.py --config mimicgen/exps/templates/robocasa/single_stage/kitchen_pnp/PnPCounterToSink.json + ``` +3. Extract image observations. + You can then extract image datasets following the dataset extraction tutorial on [this guide](../use_cases/creating_datasets.html). + +### Set up MimicGen for new tasks +Please follow the official MimicGen documentation [tutorial page](https://mimicgen.github.io/docs/tutorials/datagen_custom.html). diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/policy_learning.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/policy_learning.md new file mode 100644 index 0000000000000000000000000000000000000000..4d9b43dfbacbfdc15e3b11a4980b10749c4eaf6d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/policy_learning.md @@ -0,0 +1,57 @@ +# Policy Learning + +Our [policy learning code](https://github.com/ARISE-Initiative/robomimic/tree/robocasa) provides official support for training and evaluating polices. This repo is a branch of robomimic, with modifications to train on RoboCasa datasets. + +------- +## Installation +After installing the RoboCasa codebase, follow the instructions below: +``` +git clone https://github.com/ARISE-Initiative/robomimic -b robocasa +cd robomimic +pip install -e . +``` + +------- +## Training +There are a number of algorithms to choose from. We offer official support for BC-Transformer. Users can also adapt the code to run Diffusion Policy, ACT, etc. + +Before training, download datasets, see instructions [here](https://github.com/robocasa/robocasa?tab=readme-ov-file#datasets). + +Each algorithm has its own config generator script. For example for BC-Transformer policy run: +``` +python robomimic/scripts/config_gen/bc_xfmr_gen.py --name +``` +You can modify this file accordingly to train on datasets of your choice. + +
+

Debugging

+ +You can add --debug to generate small runs for debugging. + +
+ +Running this script will generate training run commands. You can use this script for generating a single run or multiple (for comparing settings and hyperparameter tuning). +After running this script you just need to run the command(s) outputted. + +Want to learn how to set your own config values and sweep them? Read this short [tutorial section](https://robomimic.github.io/docs/tutorials/hyperparam_scan.html#step-3-set-hyperparameter-values). + +### Loading model checkpoint weights +Want to intialize your model with weights from a previous model checkpoint? Set the checkpoint path under `experiment.ckpt_path` in the config. + +### Logging and viewing results +Read this short [tutorial page](https://robomimic.github.io/docs/tutorials/viewing_results.html). + +------- +## Evaluation +We provide a script for running evaluations on existing model checkpoints: +``` +python robomimic/scripts/config_gen/eval_ckpt.py --ckpt --name +``` +This will generate a command which you can subsequently run. + +
+

Debugging

+ +You can add --debug to generate small runs for debugging. + +
diff --git a/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/using_datasets.md b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/using_datasets.md new file mode 100644 index 0000000000000000000000000000000000000000..f6d18deac2cb207989ca4b093b20fa7128eeb828 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/docs/use_cases/using_datasets.md @@ -0,0 +1,65 @@ +## Using and Inspecting Datasets + +### Dataset registry +You can retrieve dataset paths from the [dataset registry](https://github.com/robocasa/robocasa/blob/main/robocasa/utils/dataset_registry.py) as follows: + +```py +from robocasa.utils.dataset_registry import SINGLE_STAGE_TASK_DATASETS, MULTI_STAGE_TASK_DATASETS +from robocasa.utils.dataset_registry import get_ds_path + +# iterate through all atomic and composite tasks +for task in list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS): + print(f"Datasets for {task}") + human_path, ds_meta = get_ds_path(task=task, ds_type="human_im", return_info=True) # human dataset path + horizon = ds_meta["horizon"] # get suggested for dataset + mg_path, ds_meta = get_ds_path(task=task, ds_type="mg_im", return_info=True) # MimicGen dataset path + print(f"Human ds: {human_path}") + print(f"MimicGen ds: {mg_path}") + print(f"Dataset horizon:", horizon) + print() +``` + +### Basic usage +Here is an example script to access dataset elements: +```py +import h5py +import json + +f = h5py.File(INSERT_DATASET_PATH) +demo = f["data"]["demo_5"] # access demo 5 +obs = demo["obs"] # obervations across all timesteps +left_img = obs["robot0_agentview_left_image"][:] # get left camera images in numpy format +ep_meta = json.loads(demo.attrs["ep_meta"]) # get meta data for episode +lang = ep_meta["lang"] # get language instruction for episode +f.close() +``` + +### Inspecting and visualizing datasets + +To get dataset meta data (filter keys, env args) and statistics (object, task language, scenes): +``` +python robocasa/scripts/get_dataset_info.py --dataset +``` + +To visualize a dataset and save a video: +``` +python robocasa/scripts/playback_dataset.py --n 10 --dataset +``` +This will save a video of 10 random demonstrations in the same path as the dataset. You can play the full dataset by removing the `--n` flag. + +### Dataset structure +RoboCasa datasets follow the convention of robomimic `.hdf5` files. Here is an overview of important elements of each dataset: + +`|__data`: env meta data and all demos
+` |__env_args` (attribute): meta data infromation about the dataset task
+` |__demo_`: data for demo n
+` |__model_file` (attribute): the xml string corresponding to the MJCF MuJoCo model
+` |__ep_meta` (attribute): episode meta data (task langage, scene info, object info, etc)
+` |__actions`: environment actions, ordered by time. Shape (N, A) where N is the
+` `length of the trajectory, and A is the action space dimension
+` |__action_dict`: dictionary that splits actions by fine-grained components,
+` `eg. position, rotation, gripper, etc
+` |__obs`: dictionary of observation keys, including images, proprioception, etc.
+` |__states`: flattened raw low-level MuJoCo states, ordered by time. Used to replay demos
+` `Not to be used for policy learning!
+`|__mask`: contains filter key meta data to split the dataset in different ways \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..92dc6f7141761c1871059729b594383f1f3d6b1f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/__init__.py @@ -0,0 +1,338 @@ +from robosuite.environments.base import make + +# Manipulation environments +from robocasa.environments.kitchen.kitchen import Kitchen, KitchenDemo +from robocasa.environments.kitchen.multi_stage.baking.cupcake_cleanup import ( + CupcakeCleanup, +) +from robocasa.environments.kitchen.multi_stage.baking.organize_baking_ingredients import ( + OrganizeBakingIngredients, +) +from robocasa.environments.kitchen.multi_stage.baking.pastry_display import ( + PastryDisplay, +) +from robocasa.environments.kitchen.multi_stage.boiling.fill_kettle import FillKettle +from robocasa.environments.kitchen.multi_stage.boiling.heat_multiple_water import ( + HeatMultipleWater, +) +from robocasa.environments.kitchen.multi_stage.boiling.veggie_boil import VeggieBoil +from robocasa.environments.kitchen.multi_stage.brewing.arrange_tea import ArrangeTea +from robocasa.environments.kitchen.multi_stage.brewing.kettle_boiling import ( + KettleBoiling, +) +from robocasa.environments.kitchen.multi_stage.brewing.prepare_coffee import ( + PrepareCoffee, +) +from robocasa.environments.kitchen.multi_stage.chopping_food.arrange_vegetables import ( + ArrangeVegetables, +) +from robocasa.environments.kitchen.multi_stage.chopping_food.bread_setup_slicing import ( + BreadSetupSlicing, +) +from robocasa.environments.kitchen.multi_stage.chopping_food.clearing_the_cutting_board import ( + ClearingTheCuttingBoard, +) +from robocasa.environments.kitchen.multi_stage.chopping_food.meat_transfer import ( + MeatTransfer, +) +from robocasa.environments.kitchen.multi_stage.chopping_food.organize_vegetables import ( + OrganizeVegetables, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.bowl_and_cup import ( + BowlAndCup, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.candle_cleanup import ( + CandleCleanup, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.clearing_cleaning_receptacles import ( + ClearingCleaningReceptacles, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.condiment_collection import ( + CondimentCollection, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.dessert_assembly import ( + DessertAssembly, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.drinkware_consolidation import ( + DrinkwareConsolidation, +) +from robocasa.environments.kitchen.multi_stage.clearing_table.food_cleanup import ( + FoodCleanup, +) +from robocasa.environments.kitchen.multi_stage.defrosting_food.defrost_by_category import ( + DefrostByCategory, +) +from robocasa.environments.kitchen.multi_stage.defrosting_food.microwave_thawing import ( + MicrowaveThawing, +) +from robocasa.environments.kitchen.multi_stage.defrosting_food.quick_thaw import ( + QuickThaw, +) +from robocasa.environments.kitchen.multi_stage.defrosting_food.thaw_in_sink import ( + ThawInSink, +) +from robocasa.environments.kitchen.multi_stage.frying.assemble_cooking_array import ( + AssembleCookingArray, +) +from robocasa.environments.kitchen.multi_stage.frying.frying_pan_adjustment import ( + FryingPanAdjustment, +) +from robocasa.environments.kitchen.multi_stage.frying.meal_prep_staging import ( + MealPrepStaging, +) +from robocasa.environments.kitchen.multi_stage.frying.searing_meat import SearingMeat +from robocasa.environments.kitchen.multi_stage.frying.setup_frying import SetupFrying +from robocasa.environments.kitchen.multi_stage.making_toast.bread_selection import ( + BreadSelection, +) +from robocasa.environments.kitchen.multi_stage.making_toast.cheesy_bread import ( + CheesyBread, +) +from robocasa.environments.kitchen.multi_stage.making_toast.prepare_toast import ( + PrepareToast, +) +from robocasa.environments.kitchen.multi_stage.making_toast.sweet_savory_toast_setup import ( + SweetSavoryToastSetup, +) +from robocasa.environments.kitchen.multi_stage.meat_preparation.prep_for_tenderizing import ( + PrepForTenderizing, +) +from robocasa.environments.kitchen.multi_stage.meat_preparation.prep_marinating_meat import ( + PrepMarinatingMeat, +) +from robocasa.environments.kitchen.multi_stage.mixing_and_blending.colorful_salsa import ( + ColorfulSalsa, +) +from robocasa.environments.kitchen.multi_stage.mixing_and_blending.setup_juicing import ( + SetupJuicing, +) +from robocasa.environments.kitchen.multi_stage.mixing_and_blending.spicy_marinade import ( + SpicyMarinade, +) +from robocasa.environments.kitchen.multi_stage.reheating_food.heat_mug import HeatMug +from robocasa.environments.kitchen.multi_stage.reheating_food.make_loaded_potato import ( + MakeLoadedPotato, +) +from robocasa.environments.kitchen.multi_stage.reheating_food.simmering_sauce import ( + SimmeringSauce, +) +from robocasa.environments.kitchen.multi_stage.reheating_food.waffle_reheat import ( + WaffleReheat, +) +from robocasa.environments.kitchen.multi_stage.reheating_food.warm_croissant import ( + WarmCroissant, +) +from robocasa.environments.kitchen.multi_stage.restocking_supplies.beverage_sorting import ( + BeverageSorting, +) +from robocasa.environments.kitchen.multi_stage.restocking_supplies.restock_bowls import ( + RestockBowls, +) +from robocasa.environments.kitchen.multi_stage.restocking_supplies.restock_pantry import ( + RestockPantry, +) +from robocasa.environments.kitchen.multi_stage.restocking_supplies.stocking_breakfast_foods import ( + StockingBreakfastFoods, +) +from robocasa.environments.kitchen.multi_stage.sanitize_surface.clean_microwave import ( + CleanMicrowave, +) +from robocasa.environments.kitchen.multi_stage.sanitize_surface.countertop_cleanup import ( + CountertopCleanup, +) +from robocasa.environments.kitchen.multi_stage.sanitize_surface.prep_for_sanitizing import ( + PrepForSanitizing, +) +from robocasa.environments.kitchen.multi_stage.sanitize_surface.push_utensils_to_sink import ( + PushUtensilsToSink, +) +from robocasa.environments.kitchen.multi_stage.serving_food.dessert_upgrade import ( + DessertUpgrade, +) +from robocasa.environments.kitchen.multi_stage.serving_food.pan_transfer import ( + PanTransfer, +) +from robocasa.environments.kitchen.multi_stage.serving_food.place_food_in_bowls import ( + PlaceFoodInBowls, +) +from robocasa.environments.kitchen.multi_stage.serving_food.prepare_soup_serving import ( + PrepareSoupServing, +) +from robocasa.environments.kitchen.multi_stage.serving_food.serve_steak import ( + ServeSteak, +) +from robocasa.environments.kitchen.multi_stage.serving_food.wine_serving_prep import ( + WineServingPrep, +) +from robocasa.environments.kitchen.multi_stage.setting_the_table.arrange_bread_basket import ( + ArrangeBreadBasket, +) +from robocasa.environments.kitchen.multi_stage.setting_the_table.beverage_organization import ( + BeverageOrganization, +) +from robocasa.environments.kitchen.multi_stage.setting_the_table.date_night import ( + DateNight, +) +from robocasa.environments.kitchen.multi_stage.setting_the_table.seasoning_spice_setup import ( + SeasoningSpiceSetup, +) +from robocasa.environments.kitchen.multi_stage.setting_the_table.set_bowls_for_soup import ( + SetBowlsForSoup, +) +from robocasa.environments.kitchen.multi_stage.setting_the_table.size_sorting import ( + SizeSorting, +) +from robocasa.environments.kitchen.multi_stage.snack_preparation.bread_and_cheese import ( + BreadAndCheese, +) +from robocasa.environments.kitchen.multi_stage.snack_preparation.cereal_and_bowl import ( + CerealAndBowl, +) +from robocasa.environments.kitchen.multi_stage.snack_preparation.make_fruit_bowl import ( + MakeFruitBowl, +) +from robocasa.environments.kitchen.multi_stage.snack_preparation.veggie_dip_prep import ( + VeggieDipPrep, +) +from robocasa.environments.kitchen.multi_stage.snack_preparation.yogurt_delight_prep import ( + YogurtDelightPrep, +) +from robocasa.environments.kitchen.multi_stage.steaming_food.multistep_steaming import ( + MultistepSteaming, +) +from robocasa.environments.kitchen.multi_stage.steaming_food.steam_in_microwave import ( + SteamInMicrowave, +) +from robocasa.environments.kitchen.multi_stage.steaming_food.steam_vegetables import ( + SteamVegetables, +) +from robocasa.environments.kitchen.multi_stage.tidying_cabinets_and_drawers.drawer_utensil_sort import ( + DrawerUtensilSort, +) +from robocasa.environments.kitchen.multi_stage.tidying_cabinets_and_drawers.organize_cleaning_supplies import ( + OrganizeCleaningSupplies, +) +from robocasa.environments.kitchen.multi_stage.tidying_cabinets_and_drawers.pantry_mishap import ( + PantryMishap, +) +from robocasa.environments.kitchen.multi_stage.tidying_cabinets_and_drawers.shaker_shuffle import ( + ShakerShuffle, +) +from robocasa.environments.kitchen.multi_stage.tidying_cabinets_and_drawers.snack_sorting import ( + SnackSorting, +) +from robocasa.environments.kitchen.multi_stage.washing_dishes.dry_dishes import ( + DryDishes, +) +from robocasa.environments.kitchen.multi_stage.washing_dishes.dry_drinkware import ( + DryDrinkware, +) +from robocasa.environments.kitchen.multi_stage.washing_dishes.pre_soak_pan import ( + PreSoakPan, +) +from robocasa.environments.kitchen.multi_stage.washing_dishes.sorting_cleanup import ( + SortingCleanup, +) +from robocasa.environments.kitchen.multi_stage.washing_dishes.stack_bowls import ( + StackBowlsInSink, +) +from robocasa.environments.kitchen.multi_stage.washing_fruits_and_vegetables.afterwash_sorting import ( + AfterwashSorting, +) +from robocasa.environments.kitchen.multi_stage.washing_fruits_and_vegetables.clear_clutter import ( + ClearClutter, +) +from robocasa.environments.kitchen.multi_stage.washing_fruits_and_vegetables.drain_veggies import ( + DrainVeggies, +) +from robocasa.environments.kitchen.multi_stage.washing_fruits_and_vegetables.prewash_food_assembly import ( + PrewashFoodAssembly, +) +from robocasa.environments.kitchen.single_stage.kitchen_coffee import ( + CoffeePressButton, + CoffeeServeMug, + CoffeeSetupMug, +) +from robocasa.environments.kitchen.single_stage.kitchen_doors import ( + CloseDoor, + CloseDoubleDoor, + CloseSingleDoor, + OpenDoor, + OpenDoubleDoor, + OpenSingleDoor, +) +from robocasa.environments.kitchen.single_stage.kitchen_drawer import ( + CloseDrawer, + OpenDrawer, +) +from robocasa.environments.kitchen.single_stage.kitchen_microwave import ( + TurnOffMicrowave, + TurnOnMicrowave, +) +from robocasa.environments.kitchen.single_stage.kitchen_navigate import NavigateKitchen +from robocasa.environments.kitchen.single_stage.kitchen_pnp import ( + PnPCabToCounter, + PnPCounterToCab, + PnPCounterToMicrowave, + PnPCounterToSink, + PnPMicrowaveToCounter, + PnPSinkToCounter, +) +from robocasa.environments.kitchen.single_stage.kitchen_sink import ( + TurnOffSinkFaucet, + TurnOnSinkFaucet, +) +from robocasa.environments.kitchen.single_stage.kitchen_stove import ( + TurnOffStove, + TurnOnStove, +) + +try: + import mimicgen +except ImportError: + print( + "WARNING: mimicgen environments not imported since mimicgen is not installed!" + ) + +from robocasa.environments import ALL_KITCHEN_ENVIRONMENTS + +# from robosuite.controllers import ALL_CONTROLLERS, load_controller_config +from robosuite.controllers import ALL_PART_CONTROLLERS, load_composite_controller_config +from robosuite.environments import ALL_ENVIRONMENTS +from robosuite.models.grippers import ALL_GRIPPERS +from robosuite.robots import ALL_ROBOTS + +import mujoco + +assert ( + mujoco.__version__ == "3.2.6" +), "MuJoCo version must be 3.2.6. Please run pip install mujoco==3.2.6" + +import numpy + +assert numpy.__version__ in [ + "1.23.2", + "1.23.3", + "1.23.5", + "1.26.4", +], "numpy version must be either 1.23.{2,3,5}. Please install one of these versions." + +import robosuite + +robosuite_version = [int(e) for e in robosuite.__version__.split(".")] +robosuite_check = True +if robosuite_version[0] < 1: + robosuite_check = False +if robosuite_version[0] == 1 and robosuite_version[1] < 5: + robosuite_check = False +assert ( + robosuite_check +), "robosuite version must be >=1.5.0. Please install the correct version" + +__version__ = "0.2.0" +__logo__ = """ + ; / ,--. + ["] ["] ,< |__**| + /[_]\ [~]\/ |// | + ] [ OOO /o|__| +""" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_kitchen_scenes.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_kitchen_scenes.py new file mode 100644 index 0000000000000000000000000000000000000000..5270a238fe58ff1c72e60ec625981647dd6662f8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_kitchen_scenes.py @@ -0,0 +1,169 @@ +import argparse +import json +import time +from collections import OrderedDict + +import numpy as np +import robosuite +from robosuite.controllers import load_composite_controller_config +from robosuite.wrappers import VisualizationWrapper +from termcolor import colored + +from robocasa.models.scenes.scene_registry import LayoutType, StyleType +from robocasa.scripts.collect_demos import collect_human_trajectory + + +def choose_option( + options, option_name, show_keys=False, default=None, default_message=None +): + """ + Prints out environment options, and returns the selected env_name choice + + Returns: + str: Chosen environment name + """ + # get the list of all tasks + + if default is None: + default = options[0] + + if default_message is None: + default_message = default + + # Select environment to run + print("{}s:".format(option_name.capitalize())) + + for i, (k, v) in enumerate(options.items()): + if show_keys: + print("[{}] {}: {}".format(i, k, v)) + else: + print("[{}] {}".format(i, v)) + print() + try: + s = input( + "Choose an option 0 to {}, or any other key for default ({}): ".format( + len(options) - 1, + default_message, + ) + ) + # parse input into a number within range + k = min(max(int(s), 0), len(options) - 1) + choice = list(options.keys())[k] + except: + if default is None: + choice = options[0] + else: + choice = default + print("Use {} by default.\n".format(choice)) + + # Return the chosen environment name + return choice + + +if __name__ == "__main__": + # Arguments + parser = argparse.ArgumentParser() + parser.add_argument("--task", type=str, default="PnPCounterToCab", help="task") + parser.add_argument("--layout", type=int, help="kitchen layout (choose number 0-9)") + parser.add_argument("--style", type=int, help="kitchen style (choose number 0-11)") + parser.add_argument("--robot", type=str, help="robot", default="PandaOmron") + args = parser.parse_args() + + raw_layouts = dict( + map(lambda item: (item.value, item.name.lower().capitalize()), LayoutType) + ) + layouts = OrderedDict() + for k in sorted(raw_layouts.keys()): + if k < -0: + continue + layouts[k] = raw_layouts[k] + + raw_styles = dict( + map(lambda item: (item.value, item.name.lower().capitalize()), StyleType) + ) + styles = OrderedDict() + for k in sorted(raw_styles.keys()): + if k < 0: + continue + styles[k] = raw_styles[k] + + # Create argument configuration + config = { + "env_name": args.task, + "robots": args.robot, + "controller_configs": load_composite_controller_config(robot=args.robot), + "translucent_robot": False, + } + + args.renderer = "mjviewer" + + print(colored("Initializing environment...", "yellow")) + + env = robosuite.make( + **config, + has_renderer=True, + has_offscreen_renderer=False, + render_camera=None, + ignore_done=True, + use_camera_obs=False, + control_freq=20, + renderer=args.renderer, + ) + + # Grab reference to controller config and convert it to json-encoded string + env_info = json.dumps(config) + + # initialize device + from robosuite.devices import Keyboard + + device = Keyboard(env=env, pos_sensitivity=4.0, rot_sensitivity=4.0) + + # collect demonstrations + while True: + if args.layout is None: + layout = choose_option( + layouts, "kitchen layout", default=-1, default_message="random layouts" + ) + else: + layout = args.layout + + if args.style is None: + style = choose_option( + styles, "kitchen style", default=-1, default_message="random styles" + ) + else: + style = args.style + + if layout == -1: + layout = np.random.choice(range(10)) + if style == -1: + style = np.random.choice(range(11)) + + env.layout_and_style_ids = [[layout, style]] + print( + colored( + f"Showing configuration:\n Layout: {layouts[layout]}\n Style: {styles[style]}", + "green", + ) + ) + print() + print( + colored( + "Spawning environment...\n(Press Q any time to view new configuration)", + "yellow", + ) + ) + + ep_directory, discard_traj = collect_human_trajectory( + env, + device, + "right", + "single-arm-opposed", + mirror_actions=True, + render=(args.renderer != "mjviewer"), + max_fr=30, + print_info=False, + ) + + print() + print() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_objects.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_objects.py new file mode 100644 index 0000000000000000000000000000000000000000..c749643d5f5aa388bcfc8d0eb43be1e91c72d694 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_objects.py @@ -0,0 +1,372 @@ +"""Visualize MJCF models. +""" + +import argparse +import os +import time +import xml.etree.ElementTree as ET + +import mujoco +import mujoco.viewer +import numpy as np +import robosuite +from pynput.keyboard import Controller, Key, Listener +from robosuite.devices import Device +from robosuite.utils.binding_utils import MjRenderContextOffscreen, MjSim +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import find_elements +from robosuite.utils.mjcf_utils import string_to_array as s2a +from termcolor import colored + +import robocasa +from robocasa.models.objects.kitchen_object_utils import sample_kitchen_object +from robocasa.scripts.download_kitchen_assets import ( + DOWNLOAD_ASSET_REGISTRY, + download_and_extract_zip, +) + + +def edit_model_xml(xml_str): + """ + This function edits the model xml with custom changes, including resolving relative paths, + applying changes retroactively to existing demonstration files, and other custom scripts. + Environment subclasses should modify this function to add environment-specific xml editing features. + Args: + xml_str (str): Mujoco sim demonstration XML file as string + Returns: + str: Edited xml file as string + """ + + path = os.path.split(robosuite.__file__)[0] + path_split = path.split("/") + + # replace mesh and texture file paths + tree = ET.fromstring(xml_str) + root = tree + asset = root.find("asset") + meshes = asset.findall("mesh") + textures = asset.findall("texture") + all_elements = meshes + textures + + for elem in all_elements: + old_path = elem.get("file") + if old_path is None: + continue + + old_path_split = old_path.split("/") + # maybe replace all paths to robosuite assets + check_lst = [ + loc for loc, val in enumerate(old_path_split) if val == "robosuite" + ] + if len(check_lst) > 0: + ind = max(check_lst) # last occurrence index + new_path_split = path_split + old_path_split[ind + 1 :] + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + return ET.tostring(root, encoding="utf8").decode("utf8") + + +def read_model( + filepath, + hide_sites=True, + show_bbox=False, + show_coll_geoms=False, +): + with open(filepath, "r") as file: + xml = file.read() + + xml = edit_model_xml(xml) + root = ET.fromstring(xml) + + # add white background + asset = find_elements(root, tags="asset") + skybox = ET.fromstring( + """""" + ) + asset.append(skybox) + + # add lighting + worldbody = find_elements(root, tags="worldbody") + light = ET.fromstring( + """""" + ) + worldbody.append(light) + + # make collision geoms (in)visible + geoms = find_elements(root, tags="geom", return_first=False) + for g in geoms: + if g.get("group", None) == "0": + if show_coll_geoms: + g.set("rgba", "1.0 0.0 0.0 0.5") + else: + g.set("rgba", "1.0 0.0 0.0 0.0") + + if show_bbox: + sites = {} + for site in find_elements(root, tags="site", return_first=False): + name = site.get("name", None) + if name is not None: + sites[name] = s2a(site.get("pos")) + + ext_bbox_center = None + ext_bbox_size = None + if "ext_p0" in sites: + ext_bbox_center = np.array( + [ + np.mean([sites["ext_p0"][0], sites["ext_px"][0]]), + np.mean([sites["ext_p0"][1], sites["ext_py"][1]]), + np.mean([sites["ext_p0"][2], sites["ext_pz"][2]]), + ] + ) + ext_bbox_size = np.array( + [ + sites["ext_px"][0] - sites["ext_p0"][0], + sites["ext_py"][1] - sites["ext_p0"][1], + sites["ext_pz"][2] - sites["ext_p0"][2], + ] + ) + elif "bottom_site" in sites: + ext_bbox_center = np.mean([sites["top_site"], sites["bottom_site"]], axis=0) + ext_bbox_size = ( + np.array( + [ + sites["horizontal_radius_site"][0], + sites["horizontal_radius_site"][1], + sites["top_site"][2] - ext_bbox_center[2], + ] + ) + * 2 + ) + + if (ext_bbox_center is not None) and (ext_bbox_size is not None): + ext_bbox_site = ET.fromstring( + """""".format( + pos=a2s(ext_bbox_center), + hsize=a2s(ext_bbox_size / 2), + ) + ) + worldbody.append(ext_bbox_site) + + if hide_sites: + # hide all sites + for site in find_elements(root, tags="site", return_first=False): + site.set("rgba", "0 0 0 0") + else: + for site in find_elements(root, tags="site", return_first=False): + rgba = s2a(site.get("rgba")) + # rgba[-1] = 1.0 + site.set("rgba", a2s(rgba)) + + info = {} + + # initialize model + xml = ET.tostring(root, encoding="unicode") + if filepath is not None: + os.chdir(os.path.dirname(filepath)) + t = time.time() + model = mujoco.MjModel.from_xml_string(xml) + sim = MjSim(model) + info["sim_load_time"] = time.time() - t + + return sim, info + + +def render_model( + sim, + cam_settings=None, +): + if cam_settings is None: + cam_settings = {} + + kill = False + + def key_callback(keycode): + if chr(keycode) == "q": + nonlocal kill + kill = not kill + + # mujoco.viewer.launch(sim.model._model, sim.data._data) + viewer = mujoco.viewer.launch_passive( + sim.model._model, + sim.data._data, + key_callback=key_callback, + show_right_ui=False, + ) + + # viewer.cam.lookat = cam_settings["lookat"] + # viewer.cam.azimuth = cam_settings["azimuth"] + viewer.cam.distance = cam_settings["distance"] + viewer.cam.elevation = cam_settings["elevation"] + + return viewer + + +class DemoKeyboard(Device): + """ + A minimalistic driver class for a Keyboard. + Args: + pos_sensitivity (float): Magnitude of input position command scaling + rot_sensitivity (float): Magnitude of scale input rotation commands scaling + """ + + def __init__(self): + self._reset_state = 0 + self._kill_state = 0 + + # make a thread to listen to keyboard and register our callback functions + self.listener = Listener(on_press=self.on_press, on_release=self.on_release) + + # start listening + self.listener.start() + + def start_control(self): + """ + Method that should be called externally before controller can + start receiving commands. + """ + self._reset_state = 0 + self._kill_state = 0 + + def get_controller_state(self): + """ + Grabs the current state of the keyboard. + Returns: + dict: A dictionary containing dpos, orn, unmodified orn, grasp, and reset + """ + + return dict( + reset=self._reset_state, + kill=self._kill_state, + ) + + def on_press(self, key): + """ + Key handler for key presses. + Args: + key (str): key that was pressed + """ + pass + + def on_release(self, key): + """ + Key handler for key releases. + Args: + key (str): key that was pressed + """ + + try: + # user-commanded quit + if key.char == "q": + self._kill_state = 1 + elif key.char == "n": + self._reset_state = 1 + + except AttributeError as e: + pass + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--mjcf", + type=str, + help="(optional) path to specific model xml file to visualize. skip to sample random models", + ) + parser.add_argument( + "--show_bbox", + action="store_true", + help="(optional) visualize exterior bounding box (based on ext_ sites)", + ) + parser.add_argument( + "--show_coll_geoms", + action="store_true", + help="(optional) whether to hide collision geoms (group 0)", + ) + parser.add_argument( + "--obj_types", + type=str, + nargs="+", + default=["objaverse"], + help="(optional) object types. choose among [objaverse, aigen]", + ) + args = parser.parse_args() + + cam_settings = { + "distance": 0.3, + "elevation": -30, + } + + device = DemoKeyboard() + + obj_registries = args.obj_types + + if "aigen" in obj_registries: + + aigen_objs_path = os.path.join( + robocasa.__path__[0], "models/assets/objects/aigen_objs" + ) + if os.path.exists(aigen_objs_path) is False: + download_config = DOWNLOAD_ASSET_REGISTRY["aigen_objs"] + download_config[ + "message" + ] = "Unable to find AI-generated objects locally. Downloading files." + download_config["prompt_before_download"] = True + download_and_extract_zip(**download_config) + print( + colored( + f"Ending script. Rerun script to use new AI-generated objects", + "yellow", + ) + ) + exit() + + while True: + if args.mjcf is not None: + filepath = args.mjcf + else: + mjcf_kwargs, sampled_object_info = sample_kitchen_object( + groups="all", + obj_registries=obj_registries, + ) + filepath = sampled_object_info["mjcf_path"] + cat = sampled_object_info["cat"].replace("_", " ") + aigen = "aigen_objs" in filepath + print() + print(colored(f"Category: {cat}", "green")) + print(colored(f"AI-Generated? {aigen}", "green")) + print(colored(f"Model path: {filepath}", "green")) + + sim, info = read_model( + filepath=filepath, + hide_sites=False, + show_bbox=args.show_bbox, + show_coll_geoms=args.show_coll_geoms, + ) + + if args.mjcf is None: + print() + print(colored("(Press N to view another object, Q to end demo)", "yellow")) + else: + print(colored("(Press Q to end demo)", "yellow")) + + device.start_control() + + viewer = render_model( + sim=sim, + cam_settings=cam_settings, + ) + + time.sleep(0.5) # add delay to prevent ghost windows from opening + + while viewer.is_running(): + if device.get_controller_state()["kill"]: + exit() + if device.get_controller_state()["reset"]: + break + + viewer.close() + del viewer + + if args.mjcf is not None: + break diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_tasks.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_tasks.py new file mode 100644 index 0000000000000000000000000000000000000000..37462bb0f8eb556b852c322e6d1d2680db910aef --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_tasks.py @@ -0,0 +1,153 @@ +import argparse +import json +import os +import time +from collections import OrderedDict + +import robosuite +from termcolor import colored + +import robocasa +from robocasa.scripts.download_datasets import download_datasets +from robocasa.scripts.download_kitchen_assets import download_and_extract_zip +from robocasa.scripts.playback_dataset import playback_dataset +from robocasa.utils.dataset_registry import get_ds_path +import os + + +def choose_option( + options, option_name, show_keys=False, default=None, default_message=None +): + """ + Prints out environment options, and returns the selected env_name choice + + Returns: + str: Chosen environment name + """ + # get the list of all tasks + + if default is None: + default = options[0] + + if default_message is None: + default_message = default + + # Select environment to run + print("{}s:".format(option_name.capitalize())) + + for i, (k, v) in enumerate(options.items()): + if show_keys: + print("[{}] {}: {}".format(i, k, v)) + else: + print("[{}] {}".format(i, v)) + print() + try: + s = input( + "Choose an option 0 to {}, or any other key for default ({}): ".format( + len(options) - 1, + default_message, + ) + ) + # parse input into a number within range + k = min(max(int(s), 0), len(options) - 1) + choice = list(options.keys())[k] + except: + if default is None: + choice = options[0] + else: + choice = default + print("Use {} by default.\n".format(choice)) + + # Return the chosen environment name + return choice + + +if __name__ == "__main__": + # Arguments + parser = argparse.ArgumentParser() + parser.add_argument( + "--task", type=str, help="task (must be task with demos collected already)" + ) + parser.add_argument( + "--render_offscreen", + action="store_true", + help="off-screen rendering", + ) + parser.add_argument( + "--video_path", + type=str, + default="/tmp/robocasa_demo_tasks", + help="path to video folder for offscreen rendering.", + ) + args = parser.parse_args() + + tasks = OrderedDict( + [ + ("PnPCounterToCab", "pick and place from counter to cabinet"), + ("PnPCounterToSink", "pick and place from counter to sink"), + ("PnPMicrowaveToCounter", "pick and place from microwave to counter"), + ("PnPStoveToCounter", "pick and place from stove to counter"), + ("OpenSingleDoor", "open cabinet or microwave door"), + ("CloseDrawer", "close drawer"), + ("TurnOnMicrowave", "turn on microwave"), + ("TurnOnSinkFaucet", "turn on sink faucet"), + ("TurnOnStove", "turn on stove"), + ("ArrangeVegetables", "arrange vegetables on a cutting board"), + ("MicrowaveThawing", "place frozen food in microwave for thawing"), + ("RestockPantry", "restock cans in pantry"), + ("PreSoakPan", "prepare pan for washing"), + ("PrepareCoffee", "make coffee"), + ] + ) + + video_num = -1 + while True: + if args.task is None: + task = choose_option( + tasks, "task", default="PnPCounterToCab", show_keys=True + ) + else: + task = args.task + video_num += 1 + + dataset = get_ds_path(task, ds_type="human_raw") + + if os.path.exists(dataset) is False: + # download dataset files + print( + colored( + "Unable to find dataset locally. Downloading...", color="yellow" + ) + ) + download_datasets(tasks=[task], ds_types=["human_raw"]) + + parser = argparse.Namespace() + parser.dataset = dataset + + if args.render_offscreen: + parser.render = True + if not os.path.exists(args.video_path): + os.makedirs(args.video_path) + parser.video_path = os.path.join(args.video_path, f"video_{video_num}.mp4") + else: + parser.render = False + parser.video_path = False + + parser.render = not args.render_offscreen + parser.use_actions = False + parser.use_abs_actions = False + parser.render_image_names = ["robot0_agentview_center"] + parser.use_obs = False + parser.n = 1 if args.task is None else None + parser.filter_key = None + parser.video_skip = 5 + parser.first = False + parser.verbose = True + parser.extend_states = True + parser.camera_height = 512 + parser.camera_width = 768 + + playback_dataset(parser) + if args.task is not None: + break + print() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_teleop.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_teleop.py new file mode 100644 index 0000000000000000000000000000000000000000..99a808006ae61783d60e78e9beb152529b34b7b4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/demos/demo_teleop.py @@ -0,0 +1,164 @@ +import argparse +import json +import time +from collections import OrderedDict + +import robosuite +from robosuite.controllers import load_composite_controller_config +from robosuite.wrappers import VisualizationWrapper +from termcolor import colored + +import robocasa.macros as macros +from robocasa.scripts.collect_demos import collect_human_trajectory + + +def choose_option( + options, option_name, show_keys=False, default=None, default_message=None +): + """ + Prints out environment options, and returns the selected env_name choice + + Returns: + str: Chosen environment name + """ + # get the list of all tasks + + if default is None: + default = options[0] + + if default_message is None: + default_message = default + + # Select environment to run + print("Here is a list of {}s:\n".format(option_name)) + + for i, (k, v) in enumerate(options.items()): + if show_keys: + print("[{}] {}: {}".format(i, k, v)) + else: + print("[{}] {}".format(i, v)) + print() + try: + s = input( + "Choose an option 0 to {}, or any other key for default ({}): ".format( + len(options) - 1, + default_message, + ) + ) + # parse input into a number within range + k = min(max(int(s), 0), len(options) - 1) + choice = list(options.keys())[k] + except: + if default is None: + choice = options[0] + else: + choice = default + print("Use {} by default.\n".format(choice)) + + # Return the chosen environment name + return choice + + +if __name__ == "__main__": + # Arguments + parser = argparse.ArgumentParser() + parser.add_argument("--task", type=str, help="task (choose among 100+ tasks)") + parser.add_argument("--layout", type=int, help="kitchen layout (choose number 0-9)") + parser.add_argument("--style", type=int, help="kitchen style (choose number 0-11)") + parser.add_argument( + "--device", type=str, default="keyboard", choices=["keyboard", "spacemouse"] + ) + parser.add_argument("--robot", type=str, help="robot") + args = parser.parse_args() + + tasks = OrderedDict( + [ + ("PnPCounterToCab", "pick and place from counter to cabinet"), + ("PnPCounterToSink", "pick and place from counter to sink"), + ("PnPMicrowaveToCounter", "pick and place from microwave to counter"), + ("PnPStoveToCounter", "pick and place from stove to counter"), + ("OpenSingleDoor", "open cabinet or microwave door"), + ("CloseDrawer", "close drawer"), + ("TurnOnMicrowave", "turn on microwave"), + ("TurnOnSinkFaucet", "turn on sink faucet"), + ("TurnOnStove", "turn on stove"), + ("ArrangeVegetables", "arrange vegetables on a cutting board"), + ("MicrowaveThawing", "place frozen food in microwave for thawing"), + ("RestockPantry", "restock cans in pantry"), + ("PreSoakPan", "prepare pan for washing"), + ("PrepareCoffee", "make coffee"), + ] + ) + + if args.task is None: + args.task = choose_option( + tasks, "task", default="PnPCounterToCab", show_keys=True + ) + robots = OrderedDict([(0, "PandaOmron"), (1, "GR1FloatingBody")]) + + if args.robot is None: + robot_choice = choose_option( + robots, "robot", default=0, default_message="PandaOmron" + ) + args.robot = robots[robot_choice] + + # Create argument configuration + config = { + "env_name": args.task, + "robots": args.robot, + "controller_configs": load_composite_controller_config(robot=args.robot), + "layout_ids": args.layout, + "style_ids": args.style, + "translucent_robot": True, + } + + args.renderer = "mjviewer" + + print(colored(f"Initializing environment...", "yellow")) + env = robosuite.make( + **config, + has_renderer=True, + has_offscreen_renderer=False, + render_camera="robot0_frontview", + ignore_done=True, + use_camera_obs=False, + control_freq=20, + renderer=args.renderer, + ) + + # Wrap this with visualization wrapper + env = VisualizationWrapper(env) + + # Grab reference to controller config and convert it to json-encoded string + env_info = json.dumps(config) + + # initialize device + if args.device == "keyboard": + from robosuite.devices import Keyboard + + device = Keyboard(env=env, pos_sensitivity=4.0, rot_sensitivity=4.0) + elif args.device == "spacemouse": + from robosuite.devices import SpaceMouse + + device = SpaceMouse( + env=env, + pos_sensitivity=4.0, + rot_sensitivity=4.0, + vendor_id=macros.SPACEMOUSE_VENDOR_ID, + product_id=macros.SPACEMOUSE_PRODUCT_ID, + ) + else: + raise ValueError + + # collect demonstrations + while True: + ep_directory, discard_traj = collect_human_trajectory( + env, + device, + "right", + "single-arm-opposed", + mirror_actions=True, + render=(args.renderer != "mjviewer"), + max_fr=30, + ) + print() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b150e36cc3457ca5cb0e727b8ce1778934b56585 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/__init__.py @@ -0,0 +1,3 @@ +from .kitchen.kitchen import REGISTERED_KITCHEN_ENVS + +ALL_KITCHEN_ENVIRONMENTS = REGISTERED_KITCHEN_ENVS.keys() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/kitchen.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/kitchen.py new file mode 100644 index 0000000000000000000000000000000000000000..51b3d15c7ce7be1c912fb112012502ef45840119 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/kitchen.py @@ -0,0 +1,1635 @@ +import os +import random +import xml.etree.ElementTree as ET +from copy import deepcopy + +import numpy as np +import robosuite.utils.transform_utils as T +from robosuite.environments.manipulation.manipulation_env import ManipulationEnv +from robosuite.models.tasks import ManipulationTask +from robosuite.utils.errors import RandomizationError +from robosuite.utils.mjcf_utils import ( + array_to_string, + find_elements, + xml_path_completion, +) +from robosuite.models.robots.robot_model import REGISTERED_ROBOTS +from robosuite.utils.observables import Observable, sensor +from robosuite.environments.base import EnvMeta +from scipy.spatial.transform import Rotation + +from robosuite.models.robots import PandaOmron + +import robocasa +import robocasa.macros as macros +import robocasa.utils.camera_utils as CamUtils +import robocasa.utils.object_utils as OU +import robocasa.models.scenes.scene_registry as SceneRegistry +from robocasa.models.scenes import KitchenArena +from robocasa.models.fixtures import * +from robocasa.models.objects.kitchen_object_utils import sample_kitchen_object +from robocasa.models.objects.objects import MJCFObject +from robocasa.utils.placement_samplers import ( + SequentialCompositeSampler, + UniformRandomSampler, +) +from robocasa.utils.texture_swap import ( + get_random_textures, + replace_cab_textures, + replace_counter_top_texture, + replace_floor_texture, + replace_wall_texture, +) +from robocasa.utils.config_utils import refactor_composite_controller_config + + +REGISTERED_KITCHEN_ENVS = {} + + +def register_kitchen_env(target_class): + REGISTERED_KITCHEN_ENVS[target_class.__name__] = target_class + + +class KitchenEnvMeta(EnvMeta): + """Metaclass for registering robocasa environments""" + + def __new__(meta, name, bases, class_dict): + cls = super().__new__(meta, name, bases, class_dict) + register_kitchen_env(cls) + return cls + + +_ROBOT_POS_OFFSETS: dict[str, list[float]] = { + "GR1FloatingBody": [0, 0, 0.97], + "GR1": [0, 0, 0.97], + "GR1FixedLowerBody": [0, 0, 0.97], + "G1FloatingBody": [0, -0.33, 0], + "G1": [0, -0.33, 0], + "G1FixedLowerBody": [0, -0.33, 0], + "GoogleRobot": [0, 0, 0], +} + + +class Kitchen(ManipulationEnv, metaclass=KitchenEnvMeta): + """ + Initialized a Base Kitchen environment. + + Args: + robots: Specification for specific robot arm(s) to be instantiated within this env + (e.g: "Sawyer" would generate one arm; ["Panda", "Panda", "Sawyer"] would generate three robot arms) + + env_configuration (str): Specifies how to position the robot(s) within the environment. Default is "default", + which should be interpreted accordingly by any subclasses. + + controller_configs (str or list of dict): If set, contains relevant controller parameters for creating a + custom controller. Else, uses the default controller for this specific task. Should either be single + dict if same controller is to be used for all robots or else it should be a list of the same length as + "robots" param + + base_types (None or str or list of str): type of base, used to instantiate base models from base factory. + Default is "default", which is the default base associated with the robot(s) the 'robots' specification. + None results in no base, and any other (valid) model overrides the default base. Should either be + single str if same base type is to be used for all robots or else it should be a list of the same + length as "robots" param + + gripper_types (None or str or list of str): type of gripper, used to instantiate + gripper models from gripper factory. Default is "default", which is the default grippers(s) associated + with the robot(s) the 'robots' specification. None removes the gripper, and any other (valid) model + overrides the default gripper. Should either be single str if same gripper type is to be used for all + robots or else it should be a list of the same length as "robots" param + + initialization_noise (dict or list of dict): Dict containing the initialization noise parameters. + The expected keys and corresponding value types are specified below: + + :`'magnitude'`: The scale factor of uni-variate random noise applied to each of a robot's given initial + joint positions. Setting this value to `None` or 0.0 results in no noise being applied. + If "gaussian" type of noise is applied then this magnitude scales the standard deviation applied, + If "uniform" type of noise is applied then this magnitude sets the bounds of the sampling range + :`'type'`: Type of noise to apply. Can either specify "gaussian" or "uniform" + + Should either be single dict if same noise value is to be used for all robots or else it should be a + list of the same length as "robots" param + + :Note: Specifying "default" will automatically use the default noise settings. + Specifying None will automatically create the required dict with "magnitude" set to 0.0. + + use_camera_obs (bool): if True, every observation includes rendered image(s) + + placement_initializer (ObjectPositionSampler): if provided, will be used to place objects on every reset, + else a UniformRandomSampler is used by default. + + has_renderer (bool): If true, render the simulation state in + a viewer instead of headless mode. + + has_offscreen_renderer (bool): True if using off-screen rendering + + render_camera (str): Name of camera to render if `has_renderer` is True. Setting this value to 'None' + will result in the default angle being applied, which is useful as it can be dragged / panned by + the user using the mouse + + render_collision_mesh (bool): True if rendering collision meshes in camera. False otherwise. + + render_visual_mesh (bool): True if rendering visual meshes in camera. False otherwise. + + render_gpu_device_id (int): corresponds to the GPU device id to use for offscreen rendering. + Defaults to -1, in which case the device will be inferred from environment variables + (GPUS or CUDA_VISIBLE_DEVICES). + + control_freq (float): how many control signals to receive in every second. This sets the abase of + simulation time that passes between every action input. + + horizon (int): Every episode lasts for exactly @horizon timesteps. + + ignore_done (bool): True if never terminating the environment (ignore @horizon). + + hard_reset (bool): If True, re-loads model, sim, and render object upon a reset call, else, + only calls sim.reset and resets all robosuite-internal variables + + camera_names (str or list of str): name of camera to be rendered. Should either be single str if + same name is to be used for all cameras' rendering or else it should be a list of cameras to render. + + :Note: At least one camera must be specified if @use_camera_obs is True. + + :Note: To render all robots' cameras of a certain type (e.g.: "robotview" or "eye_in_hand"), use the + convention "all-{name}" (e.g.: "all-robotview") to automatically render all camera images from each + robot's camera list). + + camera_heights (int or list of int): height of camera frame. Should either be single int if + same height is to be used for all cameras' frames or else it should be a list of the same length as + "camera names" param. + + camera_widths (int or list of int): width of camera frame. Should either be single int if + same width is to be used for all cameras' frames or else it should be a list of the same length as + "camera names" param. + + camera_depths (bool or list of bool): True if rendering RGB-D, and RGB otherwise. Should either be single + bool if same depth setting is to be used for all cameras or else it should be a list of the same length as + "camera names" param. + + renderer (str): Specifies which renderer to use. + + renderer_config (dict): dictionary for the renderer configurations + + init_robot_base_pos (str): name of the fixture to place the near. If None, will randomly select a fixture. + + seed (int): environment seed. Default is None, where environment is unseeded, ie. random + + layout_and_style_ids (list of list of int): list of layout and style ids to use for the kitchen. + + layout_ids ((list of) LayoutType or int): layout id(s) to use for the kitchen. -1 and None specify all layouts + -2 specifies layouts not involving islands/wall stacks, -3 specifies layouts involving islands/wall stacks, + -4 specifies layouts with dining areas. + + style_ids ((list of) StyleType or int): style id(s) to use for the kitchen. -1 and None specify all styles. + + generative_textures (str): if set to "100p", will use AI generated textures + + obj_registries (tuple of str): tuple containing the object registries to use for sampling objects. + can contain "objaverse" and/or "aigen" to sample objects from objaverse, AI generated, or both. + + obj_instance_split (str): string for specifying a custom set of object instances to use. "A" specifies + all but the last 3 object instances (or the first half - whichever is larger), "B" specifies the + rest, and None specifies all. + + use_distractors (bool): if True, will add distractor objects to the scene + + translucent_robot (bool): if True, will make the robot appear translucent during rendering + + randomize_cameras (bool): if True, will add gaussian noise to the position and rotation of the + wrist and agentview cameras + """ + + EXCLUDE_LAYOUTS = [] + + def __init__( + self, + robots, + env_configuration="default", + controller_configs=None, + gripper_types="default", + base_types="default", + initialization_noise="default", + use_camera_obs=True, + use_object_obs=True, # currently unused variable + reward_scale=1.0, # currently unused variable + reward_shaping=False, # currently unused variables + placement_initializer=None, + has_renderer=False, + has_offscreen_renderer=True, + render_camera="robot0_agentview_center", + render_collision_mesh=False, + render_visual_mesh=True, + render_gpu_device_id=-1, + control_freq=20, + horizon=1000, + ignore_done=True, + hard_reset=True, + camera_names="agentview", + camera_heights=256, + camera_widths=256, + camera_depths=False, + renderer="mjviewer", + renderer_config=None, + init_robot_base_pos=None, + seed=None, + layout_and_style_ids=None, + layout_ids=None, + style_ids=None, + scene_split=None, # unsued, for backwards compatibility + generative_textures=None, + obj_registries=("objaverse",), + obj_instance_split=None, + use_distractors=False, + translucent_robot=False, + randomize_cameras=False, + ): + self.init_robot_base_pos = init_robot_base_pos + + # object placement initializer + self.placement_initializer = placement_initializer + self.obj_registries = obj_registries + self.obj_instance_split = obj_instance_split + + if layout_and_style_ids is not None: + assert ( + layout_ids is None and style_ids is None + ), "layout_ids and style_ids must both be set to None if layout_and_style_ids is set" + self.layout_and_style_ids = layout_and_style_ids + else: + layout_ids = SceneRegistry.unpack_layout_ids(layout_ids) + style_ids = SceneRegistry.unpack_style_ids(style_ids) + self.layout_and_style_ids = [(l, s) for l in layout_ids for s in style_ids] + + # remove excluded layouts + self.layout_and_style_ids = [ + (int(l), int(s)) + for (l, s) in self.layout_and_style_ids + if l not in self.EXCLUDE_LAYOUTS + ] + + assert generative_textures in [None, False, "100p"] + self.generative_textures = generative_textures + + self.use_distractors = use_distractors + self.translucent_robot = translucent_robot + self.randomize_cameras = randomize_cameras + + if isinstance(robots, str): + robots = [robots] + + # backward compatibility: rename all robots that were previously called PandaMobile -> PandaOmron + for i in range(len(robots)): + if robots[i] == "PandaMobile": + robots[i] = "PandaOmron" + assert len(robots) == 1 + + # intialize cameras + self._cam_configs = CamUtils.get_robot_cam_configs(robots[0]) + + # set up currently unused variables (used in robosuite) + self.use_object_obs = use_object_obs + self.reward_scale = reward_scale + self.reward_shaping = reward_shaping + + if controller_configs is not None: + # detect if using stale controller configs (before robosuite v1.5.1) and update to new convention + arms = REGISTERED_ROBOTS[robots[0]].arms + controller_configs = refactor_composite_controller_config( + controller_configs, robots[0], arms + ) + if robots[0] == "PandaOmron": + if "composite_controller_specific_configs" not in controller_configs: + controller_configs["composite_controller_specific_configs"] = {} + controller_configs["composite_controller_specific_configs"][ + "body_part_ordering" + ] = ["right", "right_gripper", "base", "torso"] + + super().__init__( + robots=robots, + env_configuration=env_configuration, + controller_configs=controller_configs, + base_types=base_types, + gripper_types=gripper_types, + initialization_noise=initialization_noise, + use_camera_obs=use_camera_obs, + has_renderer=has_renderer, + has_offscreen_renderer=has_offscreen_renderer, + render_camera=render_camera, + render_collision_mesh=render_collision_mesh, + render_visual_mesh=render_visual_mesh, + render_gpu_device_id=render_gpu_device_id, + control_freq=control_freq, + lite_physics=True, + horizon=horizon, + ignore_done=ignore_done, + hard_reset=hard_reset, + camera_names=camera_names, + camera_heights=camera_heights, + camera_widths=camera_widths, + camera_depths=camera_depths, + renderer=renderer, + renderer_config=renderer_config, + seed=seed, + ) + + def _load_model(self): + """ + Loads an xml model, puts it in self.model + """ + super()._load_model() + + for robot in self.robots: + if isinstance(robot.robot_model, PandaOmron): + robot.init_qpos = ( + -0.01612974, + -1.03446714, + -0.02397936, + -2.27550888, + 0.03932365, + 1.51639493, + 0.69615947, + ) + robot.init_torso_qpos = np.array([0.0]) + + # determine sample layout and style + if "layout_id" in self._ep_meta and "style_id" in self._ep_meta: + self.layout_id = self._ep_meta["layout_id"] + self.style_id = self._ep_meta["style_id"] + else: + layout_id, style_id = self.rng.choice(self.layout_and_style_ids) + self.layout_id = int(layout_id) + self.style_id = int(style_id) + + if macros.VERBOSE: + print("layout: {}, style: {}".format(self.layout_id, self.style_id)) + + # to be set later inside edit_model_xml function + self._curr_gen_fixtures = self._ep_meta.get("gen_textures") + + # setup scene + self.mujoco_arena = KitchenArena( + layout_id=self.layout_id, + style_id=self.style_id, + rng=self.rng, + ) + # Arena always gets set to zero origin + self.mujoco_arena.set_origin([0, 0, 0]) + self.set_cameras() # setup cameras + + # setup rendering for this layout + if self.renderer == "mjviewer": + camera_config = CamUtils.LAYOUT_CAMS.get( + self.layout_id, CamUtils.DEFAULT_LAYOUT_CAM + ) + self.renderer_config = {"cam_config": camera_config} + + # setup fixtures + self.fixture_cfgs = self.mujoco_arena.get_fixture_cfgs() + self.fixtures = {cfg["name"]: cfg["model"] for cfg in self.fixture_cfgs} + + # setup scene, robots, objects + self.model = ManipulationTask( + mujoco_arena=self.mujoco_arena, + mujoco_robots=[robot.robot_model for robot in self.robots], + mujoco_objects=list(self.fixtures.values()), + ) + + # setup fixture locations + fxtr_placement_initializer = self._get_placement_initializer( + self.fixture_cfgs, z_offset=0.0 + ) + fxtr_placements = None + for i in range(10): + try: + fxtr_placements = fxtr_placement_initializer.sample() + except RandomizationError as e: + if macros.VERBOSE: + print("Ranomization error in initial placement. Try #{}".format(i)) + continue + break + if fxtr_placements is None: + if macros.VERBOSE: + print("Could not place fixtures. Trying again with self._load_model()") + self._load_model() + return + self.fxtr_placements = fxtr_placements + # Loop through all objects and reset their positions + for obj_pos, obj_quat, obj in fxtr_placements.values(): + assert isinstance(obj, Fixture) + obj.set_pos(obj_pos) + + # hacky code to set orientation + obj.set_euler(T.mat2euler(T.quat2mat(T.convert_quat(obj_quat, "xyzw")))) + + # setup internal references related to fixtures + self._setup_kitchen_references() + + # set robot position + if self.init_robot_base_pos is not None: + ref_fixture = self.get_fixture(self.init_robot_base_pos) + else: + fixtures = list(self.fixtures.values()) + valid_src_fixture_classes = [ + "CoffeeMachine", + "Toaster", + "Stove", + "Stovetop", + "SingleCabinet", + "HingeCabinet", + "OpenCabinet", + "Drawer", + "Microwave", + "Sink", + "Hood", + "Oven", + "Fridge", + "Dishwasher", + ] + while True: + ref_fixture = self.rng.choice(fixtures) + fxtr_class = type(ref_fixture).__name__ + if fxtr_class not in valid_src_fixture_classes: + continue + break + + robot_base_pos, robot_base_ori = self.compute_robot_base_placement_pose( + ref_fixture=ref_fixture + ) + robot_model = self.robots[0].robot_model + robot_model.set_base_xpos(robot_base_pos) + robot_model.set_base_ori(robot_base_ori) + + # create and place objects + self._create_objects() + + # setup object locations + self.placement_initializer = self._get_placement_initializer(self.object_cfgs) + object_placements = None + for i in range(1): + try: + object_placements = self.placement_initializer.sample( + placed_objects=self.fxtr_placements + ) + except RandomizationError as e: + if macros.VERBOSE: + print("Randomization error in initial placement. Try #{}".format(i)) + continue + break + if object_placements is None: + if macros.VERBOSE: + print("Could not place objects. Trying again with self._load_model()") + self._load_model() + return + self.object_placements = object_placements + + def _create_objects(self): + """ + Creates and places objects in the kitchen environment. + Helper function called by _create_objects() + """ + # add objects + self.objects = {} + if "object_cfgs" in self._ep_meta: + self.object_cfgs = self._ep_meta["object_cfgs"] + for obj_num, cfg in enumerate(self.object_cfgs): + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + model, info = self._create_obj(cfg) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + else: + self.object_cfgs = self._get_obj_cfgs() + addl_obj_cfgs = [] + for obj_num, cfg in enumerate(self.object_cfgs): + cfg["type"] = "object" + if "name" not in cfg: + cfg["name"] = "obj_{}".format(obj_num + 1) + model, info = self._create_obj(cfg) + cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + try_to_place_in = cfg["placement"].get("try_to_place_in", None) + + # place object in a container and add container as an object to the scene + if try_to_place_in and ( + "in_container" in cfg["info"]["groups_containing_sampled_obj"] + ): + container_cfg = { + "name": cfg["name"] + "_container", + "obj_groups": cfg["placement"].get("try_to_place_in"), + "placement": deepcopy(cfg["placement"]), + "type": "object", + } + + container_kwargs = cfg["placement"].get("container_kwargs", None) + if container_kwargs is not None: + for k, v in container_kwargs.items(): + container_cfg[k] = v + + # add in the new object to the model + addl_obj_cfgs.append(container_cfg) + model, info = self._create_obj(container_cfg) + container_cfg["info"] = info + self.objects[model.name] = model + self.model.merge_objects([model]) + + # modify object config to lie inside of container + cfg["placement"] = dict( + size=(0.01, 0.01), + ensure_object_boundary_in_range=False, + sample_args=dict( + reference=container_cfg["name"], + ), + ) + + # prepend the new object configs in + self.object_cfgs = addl_obj_cfgs + self.object_cfgs + + # # remove objects that didn't get created + # self.object_cfgs = [cfg for cfg in self.object_cfgs if "model" in cfg] + + def _create_obj(self, cfg): + """ + Helper function for creating objects. + Called by _create_objects() + """ + if "info" in cfg: + """ + if cfg has "info" key in it, that means it is storing meta data already + that indicates which object we should be using. + set the obj_groups to this path to do deterministic playback + """ + mjcf_path = cfg["info"]["mjcf_path"] + # replace with correct base path + new_base_path = os.path.join(robocasa.models.assets_root, "objects") + new_path = os.path.join(new_base_path, mjcf_path.split("/objects/")[-1]) + obj_groups = new_path + exclude_obj_groups = None + else: + obj_groups = cfg.get("obj_groups", "all") + exclude_obj_groups = cfg.get("exclude_obj_groups", None) + object_kwargs, object_info = self.sample_object( + obj_groups, + exclude_groups=exclude_obj_groups, + graspable=cfg.get("graspable", None), + washable=cfg.get("washable", None), + microwavable=cfg.get("microwavable", None), + cookable=cfg.get("cookable", None), + freezable=cfg.get("freezable", None), + max_size=cfg.get("max_size", (None, None, None)), + object_scale=cfg.get("object_scale", None), + ) + info = object_info + + object = MJCFObject(name=cfg["name"], **object_kwargs) + + return object, info + + def _setup_kitchen_references(self): + """ + setup fixtures (and their references). this function is called within load_model function for kitchens + """ + serialized_refs = self._ep_meta.get("fixture_refs", {}) + # unserialize refs + self.fixture_refs = { + k: self.get_fixture(v) for (k, v) in serialized_refs.items() + } + + def _reset_observables(self): + if self.hard_reset: + self._observables = self._setup_observables() + + def compute_robot_base_placement_pose(self, ref_fixture, offset=None): + """ + steps: + 1. find the nearest counter to this fixture + 2. compute offset relative to this counter + 3. transform offset to global coordinates + + Args: + ref_fixture (Fixture): reference fixture to place th robot near + + offset (list): offset to add to the base position + + """ + # step 1: find vase fixture closest to robot + base_fixture = None + + # get all base fixtures in the environment + base_fixtures = [ + fxtr + for fxtr in self.fixtures.values() + if isinstance(fxtr, Counter) + or isinstance(fxtr, Stove) + or isinstance(fxtr, Stovetop) + or isinstance(fxtr, HousingCabinet) + or isinstance(fxtr, Fridge) + ] + + for fxtr in base_fixtures: + # get bounds of fixture + point = ref_fixture.pos + if not OU.point_in_fixture(point=point, fixture=fxtr, only_2d=True): + continue + base_fixture = fxtr + break + + # set the base fixture as the ref fixture itself if cannot find fixture containing ref + if base_fixture is None: + base_fixture = ref_fixture + # assert base_fixture is not None + + # step 2: compute offset relative to this counter + base_to_ref, _ = OU.get_rel_transform(base_fixture, ref_fixture) + cntr_y = base_fixture.get_ext_sites(relative=True)[0][1] + base_to_edge = [ + base_to_ref[0], + cntr_y - 0.20, + 0, + ] + if offset is not None: + base_to_edge[0] += offset[0] + base_to_edge[1] += offset[1] + + if ( + isinstance(base_fixture, HousingCabinet) + or isinstance(base_fixture, Fridge) + or "stack" in base_fixture.name + ): + base_to_edge[1] -= 0.10 + + # apply robot-specific offset relative to the base fixture for x,y dims + robot_model = self.robots[0].robot_model + robot_class_name = robot_model.__class__.__name__ + if robot_class_name in _ROBOT_POS_OFFSETS: + for dimension in range(0, 2): + base_to_edge[dimension] += _ROBOT_POS_OFFSETS[robot_class_name][ + dimension + ] + + # step 3: transform offset to global coordinates + robot_base_pos = np.zeros(3) + robot_base_pos[0:2] = OU.get_pos_after_rel_offset(base_fixture, base_to_edge)[ + 0:2 + ] + # apply robot-specific absolutely for z dim + if robot_class_name in _ROBOT_POS_OFFSETS: + robot_base_pos[2] = _ROBOT_POS_OFFSETS[robot_class_name][2] + robot_base_ori = np.array([0, 0, base_fixture.rot + np.pi / 2]) + + return robot_base_pos, robot_base_ori + + def _get_placement_initializer(self, cfg_list, z_offset=0.01): + + """ + Creates a placement initializer for the objects/fixtures based on the specifications in the configurations list + + Args: + cfg_list (list): list of object configurations + + z_offset (float): offset in z direction + + Returns: + SequentialCompositeSampler: placement initializer + + """ + + placement_initializer = SequentialCompositeSampler( + name="SceneSampler", rng=self.rng + ) + + for (obj_i, cfg) in enumerate(cfg_list): + # determine which object is being placed + if cfg["type"] == "fixture": + mj_obj = self.fixtures[cfg["name"]] + elif cfg["type"] == "object": + mj_obj = self.objects[cfg["name"]] + else: + raise ValueError + + placement = cfg.get("placement", None) + if placement is None: + continue + fixture_id = placement.get("fixture", None) + if fixture_id is not None: + # get fixture to place object on + fixture = self.get_fixture( + id=fixture_id, + ref=placement.get("ref", None), + ) + + # calculate the total available space where object could be placed + sample_region_kwargs = placement.get("sample_region_kwargs", {}) + reset_region = fixture.sample_reset_region( + env=self, **sample_region_kwargs + ) + outer_size = reset_region["size"] + margin = placement.get("margin", 0.04) + outer_size = (outer_size[0] - margin, outer_size[1] - margin) + + # calculate the size of the inner region where object will actually be placed + target_size = placement.get("size", None) + if target_size is not None: + target_size = deepcopy(list(target_size)) + for size_dim in [0, 1]: + if target_size[size_dim] == "obj": + target_size[size_dim] = mj_obj.size[size_dim] + 0.005 + if target_size[size_dim] == "obj.x": + target_size[size_dim] = mj_obj.size[0] + 0.005 + if target_size[size_dim] == "obj.y": + target_size[size_dim] = mj_obj.size[1] + 0.005 + inner_size = np.min((outer_size, target_size), axis=0) + else: + inner_size = outer_size + + inner_xpos, inner_ypos = placement.get("pos", (None, None)) + offset = placement.get("offset", (0.0, 0.0)) + + # center inner region within outer region + if inner_xpos == "ref": + # compute optimal placement of inner region to match up with the reference fixture + x_halfsize = outer_size[0] / 2 - inner_size[0] / 2 + if x_halfsize == 0.0: + inner_xpos = 0.0 + else: + ref_fixture = self.get_fixture( + placement["sample_region_kwargs"]["ref"] + ) + ref_pos = ref_fixture.pos + fixture_to_ref = OU.get_rel_transform(fixture, ref_fixture)[0] + outer_to_ref = fixture_to_ref - reset_region["offset"] + inner_xpos = outer_to_ref[0] / x_halfsize + inner_xpos = np.clip(inner_xpos, a_min=-1.0, a_max=1.0) + elif inner_xpos is None: + inner_xpos = 0.0 + + if inner_ypos is None: + inner_ypos = 0.0 + # offset for inner region + intra_offset = ( + (outer_size[0] / 2 - inner_size[0] / 2) * inner_xpos + offset[0], + (outer_size[1] / 2 - inner_size[1] / 2) * inner_ypos + offset[1], + ) + + # center surface point of entire region + ref_pos = fixture.pos + [0, 0, reset_region["offset"][2]] + ref_rot = fixture.rot + + # x, y, and rotational ranges for randomization + x_range = ( + np.array([-inner_size[0] / 2, inner_size[0] / 2]) + + reset_region["offset"][0] + + intra_offset[0] + ) + y_range = ( + np.array([-inner_size[1] / 2, inner_size[1] / 2]) + + reset_region["offset"][1] + + intra_offset[1] + ) + rotation = placement.get("rotation", np.array([-np.pi / 4, np.pi / 4])) + else: + target_size = placement.get("size", None) + x_range = np.array([-target_size[0] / 2, target_size[0] / 2]) + y_range = np.array([-target_size[1] / 2, target_size[1] / 2]) + rotation = placement.get("rotation", np.array([-np.pi / 4, np.pi / 4])) + ref_pos = [0, 0, 0] + ref_rot = 0.0 + + if macros.SHOW_SITES is True: + """ + show outer reset region + """ + pos_to_vis = deepcopy(ref_pos) + pos_to_vis[:2] += T.rotate_2d_point( + [reset_region["offset"][0], reset_region["offset"][1]], rot=ref_rot + ) + size_to_vis = np.concatenate( + [ + np.abs( + T.rotate_2d_point( + [outer_size[0] / 2, outer_size[1] / 2], rot=ref_rot + ) + ), + [0.001], + ] + ) + site_str = """""".format( + pos=array_to_string(pos_to_vis), + size=array_to_string(size_to_vis), + postfix=str(obj_i), + ) + site_tree = ET.fromstring(site_str) + self.model.worldbody.append(site_tree) + + """ + show inner reset region + """ + pos_to_vis = deepcopy(ref_pos) + pos_to_vis[:2] += T.rotate_2d_point( + [np.mean(x_range), np.mean(y_range)], rot=ref_rot + ) + size_to_vis = np.concatenate( + [ + np.abs( + T.rotate_2d_point( + [ + (x_range[1] - x_range[0]) / 2, + (y_range[1] - y_range[0]) / 2, + ], + rot=ref_rot, + ) + ), + [0.002], + ] + ) + site_str = """""".format( + pos=array_to_string(pos_to_vis), + size=array_to_string(size_to_vis), + postfix=str(obj_i), + ) + site_tree = ET.fromstring(site_str) + self.model.worldbody.append(site_tree) + + placement_initializer.append_sampler( + sampler=UniformRandomSampler( + name="{}_Sampler".format(cfg["name"]), + mujoco_objects=mj_obj, + x_range=x_range, + y_range=y_range, + rotation=rotation, + ensure_object_boundary_in_range=placement.get( + "ensure_object_boundary_in_range", True + ), + ensure_valid_placement=placement.get( + "ensure_valid_placement", True + ), + reference_pos=ref_pos, + reference_rot=ref_rot, + z_offset=z_offset, + rng=self.rng, + rotation_axis=placement.get("rotation_axis", "z"), + ), + sample_args=placement.get("sample_args", None), + ) + + return placement_initializer + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + # Reset all object positions using initializer sampler if we're not directly loading from an xml + if not self.deterministic_reset and self.placement_initializer is not None: + # use pre-computed object placements + object_placements = self.object_placements + + # Loop through all objects and reset their positions + for obj_pos, obj_quat, obj in object_placements.values(): + self.sim.data.set_joint_qpos( + obj.joints[0], + np.concatenate([np.array(obj_pos), np.array(obj_quat)]), + ) + + # step through a few timesteps to settle objects + action = np.zeros(self.action_spec[0].shape) # apply empty action + + # Since the env.step frequency is slower than the mjsim timestep frequency, the internal controller will output + # multiple torque commands in between new high level action commands. Therefore, we need to denote via + # 'policy_step' whether the current step we're taking is simply an internal update of the controller, + # or an actual policy update + policy_step = True + + # Loop through the simulation at the model timestep rate until we're ready to take the next policy step + # (as defined by the control frequency specified at the environment level) + for i in range(10 * int(self.control_timestep / self.model_timestep)): + self.sim.step1() + self._pre_action(action, policy_step) + self.sim.step2() + policy_step = False + + def _get_obj_cfgs(self): + """ + Returns a list of object configurations to use in the environment. + The object configurations are usually environment-specific and should + be implemented in the subclass. + + Returns: + list: list of object configurations + """ + + return [] + + def get_ep_meta(self): + """ + Returns a dictionary containing episode meta data + """ + + def copy_dict_for_json(orig_dict): + new_dict = {} + for (k, v) in orig_dict.items(): + if isinstance(v, dict): + new_dict[k] = copy_dict_for_json(v) + elif isinstance(v, Fixture): + new_dict[k] = v.name + else: + new_dict[k] = v + return new_dict + + ep_meta = super().get_ep_meta() + ep_meta["layout_id"] = self.layout_id + ep_meta["style_id"] = self.style_id + ep_meta["object_cfgs"] = [copy_dict_for_json(cfg) for cfg in self.object_cfgs] + ep_meta["fixtures"] = { + k: {"cls": v.__class__.__name__} for (k, v) in self.fixtures.items() + } + ep_meta["gen_textures"] = self._curr_gen_fixtures or {} + ep_meta["lang"] = "" + ep_meta["fixture_refs"] = dict( + {k: v.name for (k, v) in self.fixture_refs.items()} + ) + ep_meta["cam_configs"] = deepcopy(self._cam_configs) + + return ep_meta + + def find_object_cfg_by_name(self, name): + """ + Finds and returns the object configuration with the given name. + + Args: + name (str): name of the object configuration to find + + Returns: + dict: object configuration with the given name + """ + for cfg in self.object_cfgs: + if cfg["name"] == name: + return cfg + raise ValueError + + def set_cameras(self): + """ + Adds new kitchen-relevant cameras to the environment. Will randomize cameras if specified. + """ + self._cam_configs = CamUtils.get_robot_cam_configs(self.robots[0].name) + if self.randomize_cameras: + self._randomize_cameras() + + for (cam_name, cam_cfg) in self._cam_configs.items(): + if cam_cfg.get("parent_body", None) is not None: + continue + + self.mujoco_arena.set_camera( + camera_name=cam_name, + pos=cam_cfg["pos"], + quat=cam_cfg["quat"], + camera_attribs=cam_cfg.get("camera_attribs", None), + ) + + def _randomize_cameras(self): + """ + Randomizes the position and rotation of the wrist and agentview cameras. + Note: This function is called only if randomize_cameras is set to True. + """ + for camera in self._cam_configs: + if "agentview" in camera: + pos_noise = self.rng.normal(loc=0, scale=0.05, size=(1, 3))[0] + euler_noise = self.rng.normal(loc=0, scale=3, size=(1, 3))[0] + elif "eye_in_hand" in camera: + pos_noise = np.zeros_like(pos_noise) + euler_noise = np.zeros_like(euler_noise) + else: + # skip randomization for cameras not implemented + continue + + old_pos = self._cam_configs[camera]["pos"] + new_pos = [pos + n for pos, n in zip(old_pos, pos_noise)] + self._cam_configs[camera]["pos"] = list(new_pos) + + old_euler = Rotation.from_quat(self._cam_configs[camera]["quat"]).as_euler( + "xyz", degrees=True + ) + new_euler = [eul + n for eul, n in zip(old_euler, euler_noise)] + new_quat = Rotation.from_euler("xyz", new_euler, degrees=True).as_quat() + self._cam_configs[camera]["quat"] = list(new_quat) + + def edit_model_xml(self, xml_str): + """ + This function postprocesses the model.xml collected from a MuJoCo demonstration + for retrospective model changes. + + Args: + xml_str (str): Mujoco sim demonstration XML file as string + + Returns: + str: Post-processed xml file as string + """ + xml_str = super().edit_model_xml(xml_str) + + tree = ET.fromstring(xml_str) + root = tree + worldbody = root.find("worldbody") + actuator = root.find("actuator") + asset = root.find("asset") + meshes = asset.findall("mesh") + textures = asset.findall("texture") + all_elements = meshes + textures + + robocasa_path_split = os.path.split(robocasa.__file__)[0].split("/") + + # replace robocasa-specific asset paths + for elem in all_elements: + old_path = elem.get("file") + if old_path is None: + continue + + old_path_split = old_path.split("/") + # maybe replace all paths to robosuite assets + if ( + ("models/assets/fixtures" in old_path) + or ("models/assets/textures" in old_path) + or ("models/assets/objects/objaverse" in old_path) + ): + if "/robosuite/" in old_path: + check_lst = [ + loc + for loc, val in enumerate(old_path_split) + if val == "robosuite" + ] + elif "/robocasa/" in old_path: + check_lst = [ + loc + for loc, val in enumerate(old_path_split) + if val == "robocasa" + ] + else: + raise ValueError + + ind = max(check_lst) # last occurrence index + new_path_split = robocasa_path_split + old_path_split[ind + 1 :] + + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + # set cameras + for cam_name, cam_config in self._cam_configs.items(): + parent_body = cam_config.get("parent_body", None) + + cam_root = worldbody + if parent_body is not None: + cam_root = find_elements( + root=worldbody, tags="body", attribs={"name": parent_body} + ) + if cam_root is None: + # camera config refers to body that doesnt exist on the robot + continue + + cam = find_elements( + root=cam_root, tags="camera", attribs={"name": cam_name} + ) + + if cam is None: + cam = ET.Element("camera") + cam.set("mode", "fixed") + cam.set("name", cam_name) + cam_root.append(cam) + + cam.set("pos", array_to_string(cam_config["pos"])) + cam.set("quat", array_to_string(cam_config["quat"])) + for (k, v) in cam_config.get("camera_attribs", {}).items(): + cam.set(k, v) + + # replace base -> mobilebase (this is needed for old PandaOmron demos) + for elem in find_elements( + root=worldbody, tags=["geom", "site", "body", "joint"], return_first=False + ): + if elem.get("name") is None: + continue + if elem.get("name").startswith("base0_"): + old_name = elem.get("name") + new_name = "mobilebase0_" + old_name[6:] + elem.set("name", new_name) + for elem in find_elements( + root=actuator, + tags=["velocity", "position", "motor", "general"], + return_first=False, + ): + if elem.get("name") is None: + continue + if elem.get("name").startswith("base0_"): + old_name = elem.get("name") + new_name = "mobilebase0_" + old_name[6:] + elem.set("name", new_name) + for elem in find_elements( + root=actuator, + tags=["velocity", "position", "motor", "general"], + return_first=False, + ): + if elem.get("joint") is None: + continue + if elem.get("joint").startswith("base0_"): + old_joint = elem.get("joint") + new_joint = "mobilebase0_" + old_joint[6:] + elem.set("joint", new_joint) + + # result = ET.tostring(root, encoding="utf8").decode("utf8") + result = ET.tostring(root).decode("utf8") + + # replace with generative textures + if (self.generative_textures is not None) and ( + self.generative_textures is not False + ): + # sample textures + assert self.generative_textures == "100p" + if self._curr_gen_fixtures is None or self._curr_gen_fixtures == {}: + self._curr_gen_fixtures = get_random_textures(self.rng) + + cab_tex = self._curr_gen_fixtures["cab_tex"] + counter_tex = self._curr_gen_fixtures["counter_tex"] + wall_tex = self._curr_gen_fixtures["wall_tex"] + floor_tex = self._curr_gen_fixtures["floor_tex"] + + result = replace_cab_textures( + self.rng, result, new_cab_texture_file=cab_tex + ) + result = replace_counter_top_texture( + self.rng, result, new_counter_top_texture_file=counter_tex + ) + result = replace_wall_texture( + self.rng, result, new_wall_texture_file=wall_tex + ) + result = replace_floor_texture( + self.rng, result, new_floor_texture_file=floor_tex + ) + + return result + + def _setup_references(self): + """ + Sets up references to important components. A reference is typically an + index or a list of indices that point to the corresponding elements + in a flatten array, which is how MuJoCo stores physical simulation data. + """ + super()._setup_references() + + self.obj_body_id = {} + for (name, model) in self.objects.items(): + self.obj_body_id[name] = self.sim.model.body_name2id(model.root_body) + + def _setup_observables(self): + """ + Sets up observables to be used for this environment. Creates object-based observables if enabled + + Returns: + OrderedDict: Dictionary mapping observable names to its corresponding Observable object + """ + observables = super()._setup_observables() + + # low-level object information + + # Get robot prefix and define observables modality + pf = self.robots[0].robot_model.naming_prefix + modality = "object" + + # for conversion to relative gripper frame + @sensor(modality=modality) + def world_pose_in_gripper(obs_cache): + return ( + T.pose_inv( + T.pose2mat((obs_cache[f"{pf}eef_pos"], obs_cache[f"{pf}eef_quat"])) + ) + if f"{pf}eef_pos" in obs_cache and f"{pf}eef_quat" in obs_cache + else np.eye(4) + ) + + sensors = [world_pose_in_gripper] + names = ["world_pose_in_gripper"] + actives = [False] + + # add ground-truth poses (absolute and relative to eef) for all objects + for obj_name in self.obj_body_id: + obj_sensors, obj_sensor_names = self._create_obj_sensors( + obj_name=obj_name, modality=modality + ) + sensors += obj_sensors + names += obj_sensor_names + actives += [True] * len(obj_sensors) + + # Create observables + for name, s, active in zip(names, sensors, actives): + observables[name] = Observable( + name=name, + sensor=s, + sampling_rate=self.control_freq, + active=active, + ) + + return observables + + def _create_obj_sensors(self, obj_name, modality="object"): + """ + Helper function to create sensors for a given object. This is abstracted in a separate function call so that we + don't have local function naming collisions during the _setup_observables() call. + + Args: + obj_name (str): Name of object to create sensors for + + modality (str): Modality to assign to all sensors + + Returns: + 2-tuple: + sensors (list): Array of sensors for the given obj + names (list): array of corresponding observable names + """ + + ### TODO: this was stolen from pick-place - do we want to move this into utils to share it? ### + pf = self.robots[0].robot_model.naming_prefix + + @sensor(modality=modality) + def obj_pos(obs_cache): + return np.array(self.sim.data.body_xpos[self.obj_body_id[obj_name]]) + + @sensor(modality=modality) + def obj_quat(obs_cache): + return T.convert_quat( + self.sim.data.body_xquat[self.obj_body_id[obj_name]], to="xyzw" + ) + + @sensor(modality=modality) + def obj_to_eef_pos(obs_cache): + # Immediately return default value if cache is empty + if any( + [ + name not in obs_cache + for name in [ + f"{obj_name}_pos", + f"{obj_name}_quat", + "world_pose_in_gripper", + ] + ] + ): + return np.zeros(3) + obj_pose = T.pose2mat( + (obs_cache[f"{obj_name}_pos"], obs_cache[f"{obj_name}_quat"]) + ) + rel_pose = T.pose_in_A_to_pose_in_B( + obj_pose, obs_cache["world_pose_in_gripper"] + ) + rel_pos, rel_quat = T.mat2pose(rel_pose) + obs_cache[f"{obj_name}_to_{pf}eef_quat"] = rel_quat + return rel_pos + + @sensor(modality=modality) + def obj_to_eef_quat(obs_cache): + return ( + obs_cache[f"{obj_name}_to_{pf}eef_quat"] + if f"{obj_name}_to_{pf}eef_quat" in obs_cache + else np.zeros(4) + ) + + sensors = [obj_pos, obj_quat, obj_to_eef_pos, obj_to_eef_quat] + names = [ + f"{obj_name}_pos", + f"{obj_name}_quat", + f"{obj_name}_to_{pf}eef_pos", + f"{obj_name}_to_{pf}eef_quat", + ] + + return sensors, names + + def _post_action(self, action): + """ + Do any housekeeping after taking an action. + + Args: + action (np.array): Action to execute within the environment + + Returns: + 3-tuple: + - (float) reward from the environment + - (bool) whether the current episode is completed or not + - (dict) information about the current state of the environment + """ + reward, done, info = super()._post_action(action) + + # Check if stove is turned on or not + self.update_state() + return reward, done, info + + def convert_rel_to_abs_action(self, rel_action): + # if moving mobile base, there is no notion of absolute actions. + # use relative actions instead. + + # if moving arm, get the absolute action + robot = self.robots[0] + robot.control(rel_action, policy_step=True) + rel_pose = robot.composite_controller.part_controllers[ + "right" + ].goal_origin_to_eef_pose() + ac_pos, ac_ori = rel_pose[:3, 3], rel_pose[:3, :3] + ac_ori = Rotation.from_matrix(ac_ori).as_rotvec() + action_abs = np.hstack( + [ + ac_pos, + ac_ori, + rel_action[6:], + ] + ) + return action_abs + + def update_state(self): + """ + Updates the state of the environment. + This involves updating the state of all fixtures in the environment. + """ + super().update_state() + + for fixtr in self.fixtures.values(): + fixtr.update_state(self) + + def visualize(self, vis_settings): + """ + In addition to super call, make the robot semi-transparent + + Args: + vis_settings (dict): Visualization keywords mapped to T/F, determining whether that specific + component should be visualized. Should have "grippers" keyword as well as any other relevant + options specified. + """ + # Run superclass method first + super().visualize(vis_settings=vis_settings) + + visual_geom_names = [] + + for robot in self.robots: + robot_model = robot.robot_model + visual_geom_names += robot_model.visual_geoms + + for name in visual_geom_names: + rgba = self.sim.model.geom_rgba[self.sim.model.geom_name2id(name)] + if self.translucent_robot: + rgba[-1] = 0.10 + else: + rgba[-1] = 1.0 + + def reward(self, action=None): + """ + Reward function for the task. The reward function is based on the task + and to be implemented in the subclasses. Returns 0 by default. + + Returns: + float: Reward for the task + """ + reward = 0 + if self._check_success(): + reward = 1.0 + return reward + + def _check_success(self): + """ + Checks if the task has been successfully completed. + Success condition is based on the task and to be implemented in the + subclasses. Returns False by default. + + Returns: + bool: True if the task is successfully completed, False otherwise + """ + return False + + def sample_object( + self, + groups, + exclude_groups=None, + graspable=None, + microwavable=None, + washable=None, + cookable=None, + freezable=None, + split=None, + obj_registries=None, + max_size=(None, None, None), + object_scale=None, + ): + """ + Sample a kitchen object from the specified groups and within max_size bounds. + + Args: + groups (list or str): groups to sample from or the exact xml path of the object to spawn + + exclude_groups (str or list): groups to exclude + + graspable (bool): whether the sampled object must be graspable + + washable (bool): whether the sampled object must be washable + + microwavable (bool): whether the sampled object must be microwavable + + cookable (bool): whether whether the sampled object must be cookable + + freezable (bool): whether whether the sampled object must be freezable + + split (str): split to sample from. Split "A" specifies all but the last 3 object instances + (or the first half - whichever is larger), "B" specifies the rest, and None + specifies all. + + obj_registries (tuple): registries to sample from + + max_size (tuple): max size of the object. If the sampled object is not within bounds of max size, + function will resample + + object_scale (float): scale of the object. If set will multiply the scale of the sampled object by this value + + + Returns: + dict: kwargs to apply to the MJCF model for the sampled object + + dict: info about the sampled object - the path of the mjcf, groups which the object's category belongs to, + the category of the object the sampling split the object came from, and the groups the object was sampled from + """ + return sample_kitchen_object( + groups, + exclude_groups=exclude_groups, + graspable=graspable, + washable=washable, + microwavable=microwavable, + cookable=cookable, + freezable=freezable, + rng=self.rng, + obj_registries=(obj_registries or self.obj_registries), + split=(split or self.obj_instance_split), + max_size=max_size, + object_scale=object_scale, + ) + + def _is_fxtr_valid(self, fxtr, size): + """ + checks if counter is valid for object placement by making sure it is large enough + + Args: + fxtr (Fixture): fixture to check + size (tuple): minimum size (x,y) that the counter region must be to be valid + + Returns: + bool: True if fixture is valid, False otherwise + """ + for region in fxtr.get_reset_regions(self).values(): + if region["size"][0] >= size[0] and region["size"][1] >= size[1]: + return True + return False + + def get_fixture(self, id, ref=None, size=(0.2, 0.2)): + """ + search fixture by id (name, object, or type) + + Args: + id (str, Fixture, FixtureType): id of fixture to search for + + ref (str, Fixture, FixtureType): if specified, will search for fixture close to ref (within 0.10m) + + size (tuple): if sampling counter, minimum size (x,y) that the counter region must be + + Returns: + Fixture: fixture object + """ + # case 1: id refers to fixture object directly + if isinstance(id, Fixture): + return id + # case 2: id refers to exact name of fixture + elif id in self.fixtures.keys(): + return self.fixtures[id] + + if ref is None: + # find all fixtures with names containing given name + if isinstance(id, FixtureType) or isinstance(id, int): + matches = [ + name + for (name, fxtr) in self.fixtures.items() + if fixture_is_type(fxtr, id) + ] + else: + matches = [name for name in self.fixtures.keys() if id in name] + if id == FixtureType.COUNTER or id == FixtureType.COUNTER_NON_CORNER: + matches = [ + name + for name in matches + if self._is_fxtr_valid(self.fixtures[name], size) + ] + assert len(matches) > 0 + # sample random key + key = self.rng.choice(matches) + return self.fixtures[key] + else: + ref_fixture = self.get_fixture(ref) + + assert isinstance(id, FixtureType) + cand_fixtures = [] + for fxtr in self.fixtures.values(): + if not fixture_is_type(fxtr, id): + continue + if fxtr is ref_fixture: + continue + if id == FixtureType.COUNTER: + fxtr_is_valid = self._is_fxtr_valid(fxtr, size) + if not fxtr_is_valid: + continue + cand_fixtures.append(fxtr) + + # first, try to find fixture "containing" the reference fixture + for fxtr in cand_fixtures: + if OU.point_in_fixture(ref_fixture.pos, fxtr, only_2d=True): + return fxtr + # if no fixture contains reference fixture, sample all close fixtures + dists = [ + OU.fixture_pairwise_dist(ref_fixture, fxtr) for fxtr in cand_fixtures + ] + min_dist = np.min(dists) + close_fixtures = [ + fxtr for (fxtr, d) in zip(cand_fixtures, dists) if d - min_dist < 0.10 + ] + return self.rng.choice(close_fixtures) + + def register_fixture_ref(self, ref_name, fn_kwargs): + """ + Registers a fixture reference for later use. Initializes the fixture + if it has not been initialized yet. + + Args: + ref_name (str): name of the reference + + fn_kwargs (dict): keyword arguments to pass to get_fixture + + Returns: + Fixture: fixture object + """ + if ref_name not in self.fixture_refs: + self.fixture_refs[ref_name] = self.get_fixture(**fn_kwargs) + return self.fixture_refs[ref_name] + + def get_obj_lang(self, obj_name="obj", get_preposition=False): + """ + gets a formatted language string for the object (replaces underscores with spaces) + + Args: + obj_name (str): name of object + get_preposition (bool): if True, also returns preposition for object + + Returns: + str: language string for object + """ + obj_cfg = None + for cfg in self.object_cfgs: + if cfg["name"] == obj_name: + obj_cfg = cfg + break + lang = obj_cfg["info"]["cat"].replace("_", " ") + + if not get_preposition: + return lang + + if lang in ["bowl", "pot", "pan"]: + preposition = "in" + elif lang in ["plate"]: + preposition = "on" + else: + raise ValueError + + return lang, preposition + + +class KitchenDemo(Kitchen): + def __init__( + self, + init_robot_base_pos="cab_main_main_group", + obj_groups="all", + num_objs=1, + *args, + **kwargs, + ): + self.obj_groups = obj_groups + self.num_objs = num_objs + + super().__init__(init_robot_base_pos=init_robot_base_pos, *args, **kwargs) + + def _get_obj_cfgs(self): + cfgs = [] + + for i in range(self.num_objs): + cfgs.append( + dict( + name="obj_{}".format(i), + obj_groups=self.obj_groups, + placement=dict( + fixture="counter_main_main_group", + sample_region_kwargs=dict( + ref="cab_main_main_group", + ), + size=(1.0, 1.0), + pos=(0.0, -1.0), + ), + ) + ) + + return cfgs diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/cupcake_cleanup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/cupcake_cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..9ce36fc60ca4b9a800ed4573ef8ac1624d8a175e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/cupcake_cleanup.py @@ -0,0 +1,80 @@ +import numpy as np + +from robocasa.environments.kitchen.kitchen import * + + +class CupcakeCleanup(Kitchen): + """ + Cupcake Cleanup: composite task for Baking activity. + + Simulates the task of cleaning up after baking cupcakes. + + Steps: + Move the cupcake off the tray onto the counter, and place the bowl used for + mixing into the sink. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.6, 0.4)) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Move the fresh-baked cupcake off the tray onto the counter, " + "and place the bowl used for mixing into the sink." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="cupcake", + obj_groups="cupcake", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.6, 0.4) + ), + size=(0.3, 0.5), + pos=("ref", -1.0), + try_to_place_in="tray", + ), + ) + ) + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.sink, loc="left_right"), + size=(0.3, 0.5), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_far = OU.gripper_obj_far(self, "cupcake") and OU.gripper_obj_far( + self, "bowl" + ) + bowl_in_sink = OU.obj_inside_of(self, "bowl", self.sink) + cupcake_on_counter = OU.check_obj_fixture_contact(self, "cupcake", self.counter) + + return gripper_far and bowl_in_sink and cupcake_on_counter diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/organize_baking_ingredients.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/organize_baking_ingredients.py new file mode 100644 index 0000000000000000000000000000000000000000..c3aebee8c593844c182e4eda81651628cf62a192 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/organize_baking_ingredients.py @@ -0,0 +1,126 @@ +import numpy as np + +from robocasa.environments.kitchen.kitchen import * + + +class OrganizeBakingIngredients(Kitchen): + """ + Organize Baking Ingredients: composite task for Baking activity. + + Simulates the task of organizing baking ingredients. + + Steps: + Place the eggs and milk near the bowl on the counter. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"Place the eggs and milk next to the bowl." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.40, 0.40), + pos=(0.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="egg1", + obj_groups="egg", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.3, 0.3), + pos=(-1.0, -0.4), + ), + ) + ) + + cfgs.append( + dict( + name="egg2", + obj_groups="egg", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.3, 0.3), + pos=(-1.0, -0.4), + offset=(0.2, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="milk", + obj_groups="milk", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.5, 0.5), + pos=(1.0, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + + th = 0.2 + + bowl_pos = self.sim.data.body_xpos[self.obj_body_id["bowl"]] + egg1_pos = self.sim.data.body_xpos[self.obj_body_id["egg1"]] + egg2_pos = self.sim.data.body_xpos[self.obj_body_id["egg2"]] + milk_pos = self.sim.data.body_xpos[self.obj_body_id["milk"]] + + # check if the objects are near the bowl + bowl_egg1_close = np.linalg.norm(bowl_pos - egg1_pos) < th + bowl_egg2_close = np.linalg.norm(bowl_pos - egg2_pos) < th + bowl_milk_close = np.linalg.norm(bowl_pos - milk_pos) < th + + return bowl_egg1_close and bowl_egg2_close and bowl_milk_close diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/pastry_display.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/pastry_display.py new file mode 100644 index 0000000000000000000000000000000000000000..3d962c2d5d192849c33cdb919533462929302ded --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/baking/pastry_display.py @@ -0,0 +1,136 @@ +import numpy as np + +from robocasa.environments.kitchen.kitchen import * + + +class PastryDisplay(Kitchen): + """ + Pastry Display: composite task for Baking activity. + + Simulates the task of displaying pastries. + + Steps: + Place the pastries on the plates. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"Place the pastries on the plates." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="receptacle1", + obj_groups="plate", + graspable=False, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.40, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="receptacle2", + obj_groups="plate", + graspable=False, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.40, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + # use offserts and to make it easier to initialuze pastry1 and pastry2 + cfgs.append( + dict( + name="pastry1", + obj_groups="pastry", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -0.2), + offset=(0.1, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="pastry2", + obj_groups="pastry", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -0.2), + offset=(-0.1, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_pastry1_far = OU.gripper_obj_far(self, obj_name="pastry1") + gripper_pastry2_far = OU.gripper_obj_far(self, obj_name="pastry2") + pastry1_in_receptacle1 = OU.check_obj_in_receptacle( + self, "pastry1", "receptacle1" + ) + pastry1_in_receptacle2 = OU.check_obj_in_receptacle( + self, "pastry1", "receptacle2" + ) + pastry2_in_receptacle1 = OU.check_obj_in_receptacle( + self, "pastry2", "receptacle1" + ) + pastry2_in_receptacle2 = OU.check_obj_in_receptacle( + self, "pastry2", "receptacle2" + ) + + pastrys_placed = (pastry1_in_receptacle1 and pastry2_in_receptacle2) or ( + pastry1_in_receptacle2 and pastry2_in_receptacle1 + ) + + return gripper_pastry1_far and gripper_pastry2_far and pastrys_placed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/fill_kettle.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/fill_kettle.py new file mode 100644 index 0000000000000000000000000000000000000000..bcf143b5131ef1f6fbcfed969a79f7bc2b8523e0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/fill_kettle.py @@ -0,0 +1,74 @@ +from robocasa.environments.kitchen.kitchen import * + + +class FillKettle(Kitchen): + """ + Fill Kettle: composite task for Boiling activity. + + Simulates the process of filling up a kettle with water from the sink. + + Steps: + Take the kettle from the cabinet and fill it with water from the sink. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.sink) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = f"Open the cabinet, pick the kettle from the cabinet, and place it in the sink." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0, max=0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=("kettle"), + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.30), + pos=(0, -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.25, 0.25), + pos=(0.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self) + obj_in_sink = OU.obj_inside_of(self, "obj", self.sink) + + return obj_in_sink and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/heat_multiple_water.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/heat_multiple_water.py new file mode 100644 index 0000000000000000000000000000000000000000..3357adcc7bfd4a9e0de26072eb288670a31db09d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/heat_multiple_water.py @@ -0,0 +1,143 @@ +from robocasa.environments.kitchen.kitchen import * + + +class HeatMultipleWater(Kitchen): + """ + Heat Multiple Water: composite task for Boiling activity. + + Simulates the process of heating water in a pot and a kettle. + + Steps: + Take the kettle from the cabinet and place it on a stove burner. + Take the pot from the counter and place it on another stove burner. + Turn both burners on. + + Args: + init_robot_base_pos (str): Specifies a fixture to initialize the robot + in front of. Default is "stove". + """ + + def __init__(self, init_robot_base_pos="stove", *args, **kwargs): + super().__init__(init_robot_base_pos=init_robot_base_pos, *args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.ref_cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.stove) + ) + self.ref_counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.ref_cab, size=(0.2, 0.2)) + ) + + self.init_robot_base_pos = self.ref_cab + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups=("pot"), + graspable=True, + heatable=True, + placement=dict( + fixture=self.ref_counter, + sample_region_kwargs=dict( + ref=self.ref_cab, + ), + size=(0.35, 0.35), + pos=("ref", 0), + # ensure_object_boundary_in_range=False because the pots handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups=("kettle_non_electric"), + graspable=True, + placement=dict( + fixture=self.ref_cab, + size=(0.50, 0.30), + pos=(0, -1.0), + ), + ) + ) + + return cfgs + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick the kettle from the cabinet and place it on a stove burner. " + "Then pick the pot from the counter and place it on another stove burner. " + "Finally, turn both burners on." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.ref_cab.set_door_state(min=0.9, max=1.0, env=self, rng=self.rng) + valid_knobs = self.stove.get_knobs_state(env=self).keys() + + for knob in valid_knobs: + self.stove.set_knob_state(mode="off", knob=knob, env=self, rng=self.rng) + + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + """ + Check if the object is placed on any of the stove burners + + Args: + obj_name (str): object name + + threshold (float): distance threshold from object center to stove burner site center + + Returns: + str: location of the stove burner site if the object is placed on it, None otherwise. + """ + + knobs_state = self.stove.get_knobs_state(env=self) + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + knob_on = ( + (0.35 <= np.abs(knobs_state[location]) <= 2 * np.pi - 0.35) + if location in knobs_state + else False + ) + + if obj_on_site and knob_on: + return location + + return None + + def _check_success(self): + + pan_loc = self._check_obj_location_on_stove("obj", threshold=0.15) + kettle_loc = self._check_obj_location_on_stove("obj2") + + # both objects placed on different parts of the stove + successful_stove_placement = ( + (pan_loc is not None) + and (kettle_loc is not None) + and (pan_loc != kettle_loc) + ) + + return ( + successful_stove_placement + and OU.gripper_obj_far(self) + and OU.gripper_obj_far(self, "obj2") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/veggie_boil.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/veggie_boil.py new file mode 100644 index 0000000000000000000000000000000000000000..3000fe183defe43a11efe9a3506bab0ccafbdfc7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/boiling/veggie_boil.py @@ -0,0 +1,182 @@ +from robocasa.environments.kitchen.kitchen import * + + +class VeggieBoil(Kitchen): + """ + Veggie Boil: composite task for Boiling activity. + + Simulates the process of boiling vegetables. + + Steps: + Take the pot from the counter and place it in the sink. Turn on the sink and + let the pot fill up with water. Turn the sink off and move the pot to the + stove. Turn on the stove and place the food in the pot for boiling. + """ + + def __init__(self, *args, **kwargs): + # whether the pot is filled with water + self.pot_filled = False + # how long the pot has been filled with water + self.filled_time = 0 + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter_sink = self.register_fixture_ref( + "counter_sink", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.5, 0.5)) + ) + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter_stove = self.register_fixture_ref( + "counter_stove", dict(id=FixtureType.COUNTER, ref=self.stove) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + food_name = self.get_obj_lang("food") + ep_meta["lang"] = ( + "Pick up the pot and place it in the sink. " + "Then turn on the sink faucet and let the pot fill up with water. " + "Then turn the sink faucet off and move the pot to the stove. " + f"Lastly, turn on the stove and place the {food_name} in the pot for boiling." + ) + return ep_meta + + def _reset_internal(self): + self.pot_filled = False + self.filled_time = 0 + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name=f"pot", + obj_groups="pot", + placement=dict( + fixture=self.counter_sink, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.5, 0.5) + ), + size=(0.05, 0.05), + pos=("ref", -0.55), + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name=f"food", + obj_groups="vegetable", + placement=dict( + fixture=self.counter_stove, + sample_region_kwargs=dict( + ref=self.stove, + loc="nn", + ), + size=(0.5, 0.5), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter_stove, + sample_region_kwargs=dict( + ref=self.stove, + loc="nn", + ), + size=(0.30, 0.30), + pos=(0, 1.0), + ), + ) + ) + + # mitigate randomization errors + if self.counter_sink != self.counter_stove: + + cfgs.append( + dict( + name="distr_counter2", + obj_groups="all", + placement=dict( + fixture=self.counter_sink, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=(0, 1.0), + ), + ) + ) + + return cfgs + + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + + """ + Check if the object is placed on any of the stove burners + + Args: + obj_name (str): object name + + threshold (float): distance threshold from object center to stove burner site center + + Returns: + str: location of the stove burner site if the object is placed on it, None otherwise. + """ + + knobs_state = self.stove.get_knobs_state(env=self) + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + knob_on = ( + (0.35 <= np.abs(knobs_state[location]) <= 2 * np.pi - 0.35) + if location in knobs_state + else False + ) + + if obj_on_site and knob_on: + return location + + return None + + def _check_success(self): + """ + Check if the task is successful. + First check if the object is inside the sink and the water is on. Then make sure the pot is filled with water for enough + time (10 timesteps). Once the pot is filled, check if the pot is on the stove and the food is in the pot. + """ + pot_in_sink = OU.obj_inside_of(self, "pot", self.sink) + water_on = self.sink.get_handle_state(env=self)["water_on"] + + if pot_in_sink and water_on: + self.filled_time += 1 + self.pot_filled = self.filled_time > 10 + else: + self.filled_time = 0 + + vegetables_in_pot = OU.check_obj_in_receptacle(self, "food", "pot") + pot_on_stove = self._check_obj_location_on_stove("pot") is not None + return self.pot_filled and vegetables_in_pot and not water_on and pot_on_stove diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/arrange_tea.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/arrange_tea.py new file mode 100644 index 0000000000000000000000000000000000000000..6352c2241d23f4cbfea3ce3ab0acecceaa939417 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/arrange_tea.py @@ -0,0 +1,111 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ArrangeTea(Kitchen): + """ + Arrange Tea: composite task for Brewing activity. + + Simulates the task of arranging tea. + + Steps: + Take the kettle from the counter and place it on the tray. + Take the mug from the cabinet and place it on the tray. + Close the cabinet doors. + """ + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + # use a double door cabinet so that area below is large enough to initialize all the objects + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.DOOR_TOP_HINGE_DOUBLE) + ) + # set the size argument to sample a large enough counter region + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.4)) + ) + self.init_robot_base_pos = self.cab + + def _reset_internal(self): + super()._reset_internal() + self.cab.set_door_state(min=0.9, max=1.0, env=self, rng=self.rng) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick the kettle from the counter and place it on the tray. " + "Then pick the mug from the cabinet and place it on the tray. " + "Then close the cabinet doors." + ) + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=("mug"), + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups=("kettle"), + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.5, 0.5), + pos=("ref", -1.0), + sample_region_kwargs=dict(ref=self.cab, top_size=(0.6, 0.4)), + offset=(0.1, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="container", + obj_groups=("tray"), + placement=dict( + fixture=self.counter, + size=(0.7, 0.7), + pos=("ref", -0.6), + offset=(-0.1, 0.0), + sample_region_kwargs=dict(ref=self.cab, top_size=(0.6, 0.4)), + ), + ) + ) + + return cfgs + + def _check_door_closed(self): + door_state = self.cab.get_door_state(env=self) + + success = True + for joint_p in door_state.values(): + if joint_p > 0.05: + success = False + break + + return success + + def _check_success(self): + obj1_container_contact = OU.check_obj_in_receptacle(self, "obj", "container") + obj2_container_contact = OU.check_obj_in_receptacle(self, "obj2", "container") + door_closed = self._check_door_closed() + gripper_obj_far = OU.gripper_obj_far( + self + ) # no need to check all gripper objs far bc all objs in the same place + + return ( + obj1_container_contact + and obj2_container_contact + and gripper_obj_far + and door_closed + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/kettle_boiling.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/kettle_boiling.py new file mode 100644 index 0000000000000000000000000000000000000000..5d12858a1733e8ca654b2742d9f00e409961b574 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/kettle_boiling.py @@ -0,0 +1,102 @@ +from robocasa.environments.kitchen.kitchen import * + + +class KettleBoiling(Kitchen): + """ + Kettle Boiling: composite task for Brewing activity. + + Simulates the task of boiling water in a kettle. + + Steps: + Take the kettle from the counter and place it on a stove burner. + Turn the burner on. + """ + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.init_robot_base_pos = self.stove + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=(0.2, 0.2)) + ) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups=("kettle_non_electric"), + graspable=True, + heatable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.35, 0.35), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="stove_distr", + obj_groups=("pan", "pot"), + placement=dict( + fixture=self.stove, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + size=(0.02, 0.02), + # apply rotations so the handle doesnt stick too much + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + ), + ) + ) + + return cfgs + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the kettle from the counter and place it on a stove burner. Then turn the burner on." + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + valid_knobs = self.stove.get_knobs_state(env=self).keys() + for knob in valid_knobs: + self.stove.set_knob_state(mode="off", knob=knob, env=self, rng=self.rng) + + def _check_success(self): + """ + Check if the kettle is placed on the stove burner and the burner is turned on. + """ + knobs_state = self.stove.get_knobs_state(env=self) + kettle = self.objects["obj"] + kettle_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[kettle.name]])[ + 0:2 + ] + obj_on_stove = OU.check_obj_fixture_contact(self, "obj", self.stove) + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - kettle_pos) + + kettle_on_site = dist < 0.15 + knob_on = ( + (0.35 <= np.abs(knobs_state[location]) <= 2 * np.pi - 0.35) + if location in knobs_state + else False + ) + + if kettle_on_site and knob_on and OU.gripper_obj_far(self): + return True + + return False diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/prepare_coffee.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/prepare_coffee.py new file mode 100644 index 0000000000000000000000000000000000000000..820da36f2200603a95d0c02b20b317bb2f4f2c1b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/brewing/prepare_coffee.py @@ -0,0 +1,86 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrepareCoffee(Kitchen): + """ + Prepare Coffee: composite task for Brewing activity. + + Simulates the process of preparing coffee. + + Steps: + Pick the mug from the cabinet, place it under the coffee machine dispenser, + and press the start button. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the mug is + picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.coffee_machine = self.register_fixture_ref( + "coffee_machine", dict(id="coffee_machine") + ) + self.cab = self.register_fixture_ref( + "cab", dict(id=self.cab_id, ref=self.coffee_machine) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_name = self.get_obj_lang() + ep_meta[ + "lang" + ] = f"Pick the {obj_name} from the cabinet, place it under the coffee machine dispenser, and press the start button." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups="mug", + placement=dict( + fixture=self.cab, + size=(0.30, 0.20), + pos=(0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _reset_internal(self): + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self) + contact_check = self.coffee_machine.check_receptacle_placement_for_pouring( + self, "obj" + ) + gripper_button_far = self.coffee_machine.gripper_button_far(self) + return ( + contact_check + and gripper_obj_far + and self.coffee_machine._turned_on + and gripper_button_far + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/arrange_vegetables.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/arrange_vegetables.py new file mode 100644 index 0000000000000000000000000000000000000000..60ce41fda6e8f7502faa6b6bcba5414b4fc0cb79 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/arrange_vegetables.py @@ -0,0 +1,109 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ArrangeVegetables(Kitchen): + """ + Arrange Vegetables: composite task for Chopping Food activity. + + Simulates the task of arranging vegetables on the cutting board. + + Steps: + Take the vegetables from the sink and place them on the cutting board. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.45, 0.55)) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the vegetables from the sink and place them on the cutting board." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="cutting_board", + obj_groups="cutting_board", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.45, 0.55) + ), + size=(0.35, 0.45), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="knife", + obj_groups="knife", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.45, 0.55) + ), + size=(0.45, 0.45), + pos=("ref", -1.0), + offset=(0.0, 0.05), + ), + ) + ) + + cfgs.append( + dict( + name="vegetable1", + obj_groups="vegetable", + graspable=True, + placement=dict( + fixture=self.sink, + size=(0.30, 0.20), + pos=(-1.0, 1.0), + ), + ) + ) + + cfgs.append( + dict( + name="vegetable2", + obj_groups="vegetable", + graspable=True, + placement=dict( + fixture=self.sink, + size=(0.30, 0.20), + pos=(1.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + vegetable1_cutting_board_contact = OU.check_obj_in_receptacle( + self, "vegetable1", "cutting_board" + ) + vegetable2_cutting_board_contact = OU.check_obj_in_receptacle( + self, "vegetable2", "cutting_board" + ) + gripper_obj_far = OU.gripper_obj_far(self, obj_name="cutting_board") + + return ( + vegetable1_cutting_board_contact + and vegetable2_cutting_board_contact + and gripper_obj_far + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/bread_setup_slicing.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/bread_setup_slicing.py new file mode 100644 index 0000000000000000000000000000000000000000..7d5c5c1e47767accfd721f7c5997240d941997b9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/bread_setup_slicing.py @@ -0,0 +1,82 @@ +from robocasa.environments.kitchen.kitchen import * + + +class BreadSetupSlicing(Kitchen): + """ + Bread Setup Slicing: composite task for Chopping Food activity. + + Simulates the task of setting up bread for slicing. + + Steps: + Place all breads on the cutting board. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(1.0, 0.4)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + ep_meta["lang"] = f"Place all breads on the cutting board." + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="receptacle", + obj_groups="cutting_board", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(1, 0.4), + pos=(-0.6, -0.5), + ), + ) + ) + + self.num_bread = self.rng.choice([1, 2, 3]) + for i in range(self.num_bread): + cfgs.append( + dict( + name=f"obj_{i}", + obj_groups="bread", + graspable=True, + heatable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(1, 0.4), + pos=(0, -1.0), + offset=(i * 0.07, 0), + try_to_place_in="container", + ), + ) + ) + + return cfgs + + def _check_success(self): + bread_on_board = all( + [ + OU.check_obj_in_receptacle(self, f"obj_{i}", "receptacle") + for i in range(self.num_bread) + ] + ) + + return bread_on_board and OU.gripper_obj_far(self, "obj_0") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/clearing_the_cutting_board.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/clearing_the_cutting_board.py new file mode 100644 index 0000000000000000000000000000000000000000..c598ece3c8006b276f8e8cf1a5d816ee1625ad95 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/clearing_the_cutting_board.py @@ -0,0 +1,94 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ClearingTheCuttingBoard(Kitchen): + """ + Clearing The Cutting Board: composite task for Chopping Food activity. + + Simulates the task of clearing the cutting board. + + Steps: + Clear the non-vegetable object off the cutting board and place the + vegetables onto it. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.5, 0.5)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Clear the non-vegetable object off the cutting board and place the vegetables onto it." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="non_vegetable", + graspable=True, + obj_groups="food", + exclude_obj_groups="vegetable", + placement=dict( + fixture=self.counter, + size=(0.1, 0.1), + ensure_object_boundary_in_range=False, + pos=(0, -0.3), + try_to_place_in="cutting_board", + ), + ) + ) + + cfgs.append( + dict( + name="vegetable1", + obj_groups="vegetable", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.5, 0.40), + pos=(0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="vegetable2", + obj_groups="vegetable", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.50, 0.40), + pos=(0, -1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + vegetable1_cutting_board_contact = OU.check_obj_in_receptacle( + self, "vegetable1", "non_vegetable_container" + ) + vegetable2_cutting_board_contact = OU.check_obj_in_receptacle( + self, "vegetable2", "non_vegetable_container" + ) + cutting_board_cleared = not OU.check_obj_in_receptacle( + self, "non_vegetable", "non_vegetable_container" + ) + gripper_obj_far = OU.gripper_obj_far(self, obj_name="non_vegetable_container") + + return ( + vegetable1_cutting_board_contact + and vegetable2_cutting_board_contact + and gripper_obj_far + and cutting_board_cleared + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/meat_transfer.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/meat_transfer.py new file mode 100644 index 0000000000000000000000000000000000000000..8e5bd22a69a3f668075645fe2a0eac991204a69d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/meat_transfer.py @@ -0,0 +1,105 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MeatTransfer(Kitchen): + """ + Meat Transfer: composite task for Chopping Food activity. + + Simulates the task of transferring meat to a container. + + Steps: + Retrieve a container (either a pan or a bowl) from the cabinet, then place + the raw meat into the container to avoid contamination. + + Args: + cab_id: Enum which serves as a unique identifier for different cabinets. + Default to FixtureType.DOOR_TOP_HINGE_DOUBLE to have space for + initializing bowl/pan + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.5, 0.5)) + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + cont_name = self.get_obj_lang("container") + ep_meta["lang"] = ( + f"Retrieve the {cont_name} from the cabinet, " + f"then place the raw meat into the {cont_name} to avoid contamination." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + if self.rng.random() < 0.5: + cfgs.append( + dict( + name="container", + obj_groups="pan", + graspable=True, + placement=dict( + fixture=self.cab, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + size=(0.05, 0.02), + pos=(0, 0), + # apply a custom rotation for the pan so that it fits better in the cabinet + # (if the handle sticks out it may not fit) + rotation=(2 * np.pi / 8, 3 * np.pi / 8), + ), + ) + ) + else: + cfgs.append( + dict( + name="container", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.cab, + ensure_object_boundary_in_range=False, + size=(0.02, 0.02), + pos=(0, 0), + ), + ) + ) + + cfgs.append( + dict( + name="meat", + obj_groups="meat", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab), + size=(0.5, 0.4), + pos=(0.0, -1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + return ( + OU.check_obj_fixture_contact(self, "container", self.counter) + and OU.gripper_obj_far(self, obj_name="meat") + and OU.check_obj_in_receptacle(self, "meat", "container") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/organize_vegetables.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/organize_vegetables.py new file mode 100644 index 0000000000000000000000000000000000000000..31db291c1fccbe82204c3cb794f4a650f1ba704e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/chopping_food/organize_vegetables.py @@ -0,0 +1,125 @@ +from robocasa.environments.kitchen.kitchen import * + + +class OrganizeVegetables(Kitchen): + """ + Organize Vegetables: composite task for Chopping Food activity. + + Simulates the task of organizing vegetables on cutting boards. + + Steps: + Place the vegetables on separate cutting boards + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(1.0, 0.4)) + ) + + # self.counter = self.get_fixture(FixtureType.DINING_COUNTER, ref=self.sink) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + obj_name_1 = self.get_obj_lang("vegetable1") + obj_name_2 = self.get_obj_lang("vegetable2") + + ep_meta[ + "lang" + ] = f"Place the {obj_name_1} and the {obj_name_2} on separate cutting boards." + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="cutting_board1", + obj_groups="cutting_board", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(0.05, 0.05), + rotation=np.pi / 2, + pos=(-0.6, -0.5), + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="cutting_board2", + obj_groups="cutting_board", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(0.05, 0.05), + rotation=0, + pos=(0.5, -0.4), + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="vegetable1", + obj_groups=["vegetable", "fruit"], + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(0.40, 0.40), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="vegetable2", + obj_groups=["vegetable", "fruit"], + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(0.40, 0.40), + pos=(0, -0.5), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Make sure vegetables are on different cutting boards + """ + vegetable1_cutting_board_contact1 = OU.check_obj_in_receptacle( + self, "vegetable1", "cutting_board1" + ) + vegetable2_cutting_board_contact1 = OU.check_obj_in_receptacle( + self, "vegetable2", "cutting_board1" + ) + vegetable1_cutting_board_contact2 = OU.check_obj_in_receptacle( + self, "vegetable1", "cutting_board2" + ) + vegetable2_cutting_board_contact2 = OU.check_obj_in_receptacle( + self, "vegetable2", "cutting_board2" + ) + + return ( + vegetable1_cutting_board_contact1 and vegetable2_cutting_board_contact2 + ) or (vegetable2_cutting_board_contact1 and vegetable1_cutting_board_contact2) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/bowl_and_cup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/bowl_and_cup.py new file mode 100644 index 0000000000000000000000000000000000000000..650e9578fc7d7bd12690e46797996a07372a35ab --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/bowl_and_cup.py @@ -0,0 +1,76 @@ +from robocasa.environments.kitchen.kitchen import * + + +class BowlAndCup(Kitchen): + """ + Bowl And Cup: composite task for Clearing Table activity. + + Simulates the process of efficiently clearing the table. + + Steps: + Place the cup inside the bowl on the island and move it to any counter. + + Restricted to layouts with an island. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5, 7, 8, 9] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.island = self.register_fixture_ref("island", dict(id=FixtureType.ISLAND)) + + self.init_robot_base_pos = self.island + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = f"Place the cup inside the bowl on the island and move the bowl to any counter." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name=f"cup", + obj_groups=["cup"], + graspable=True, + washable=True, + placement=dict( + fixture=self.island, + size=(0.30, 0.40), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name=f"bowl", + obj_groups=["bowl"], + graspable=True, + washable=True, + placement=dict( + fixture=self.island, + size=(0.30, 0.40), + pos=(0, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + cup_in_bowl = OU.check_obj_in_receptacle(self, "cup", "bowl") + bowl_on_counter = any( + [ + OU.check_obj_fixture_contact(self, "bowl", fxtr) + for (_, fxtr) in self.fixtures.items() + if isinstance(fxtr, Counter) and fxtr != self.island + ] + ) + return cup_in_bowl and bowl_on_counter and OU.gripper_obj_far(self, "bowl") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/candle_cleanup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/candle_cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..08a9a5aa3c619b29db67e046c5a1ec3f259ba344 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/candle_cleanup.py @@ -0,0 +1,127 @@ +from robocasa.environments.kitchen.kitchen import * + + +class CandleCleanup(Kitchen): + """ + Candle Cleanup: composite task for Clearing Table activity. + + Simulates the process of efficiently clearing the dining table decorations. + + Steps: + Pick the decorations from the dining table and place it in the open cabinet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the decorations + are picked. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + # dining table is a sufficiently large counter where there are chairs nearby + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.init_robot_base_pos = self.dining_table + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_name_1 = self.get_obj_lang("obj1") + obj_name_2 = self.get_obj_lang("obj2") + ep_meta[ + "lang" + ] = f"Pick the {obj_name_1} and {obj_name_2} from the dining table and place them in the open cabinet." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.9, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="obj1", + obj_groups="decoration", + graspable=True, + placement=dict( + fixture=self.dining_table, + size=(0.60, 0.30), + sample_region_kwargs=dict( + ref=self.cab, + ), + pos=(0, -1), + offset=(-0.05, 0), + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups="decoration", + graspable=True, + placement=dict( + fixture=self.dining_table, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.60, 0.30), + pos=(0, -1), + offset=(0.05, 0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.dining_table, + size=(1.0, 0.30), + pos=(0.0, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + obj1_inside_cab = OU.obj_inside_of(self, "obj1", self.cab) + obj2_inside_cab = OU.obj_inside_of(self, "obj2", self.cab) + + door_state = self.cab.get_door_state(env=self) + + door_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + door_closed = False + break + + return door_closed and obj1_inside_cab and obj2_inside_cab diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/clearing_cleaning_receptacles.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/clearing_cleaning_receptacles.py new file mode 100644 index 0000000000000000000000000000000000000000..cb1caedcf575b6a207edc47659adbbb2129dbe0d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/clearing_cleaning_receptacles.py @@ -0,0 +1,105 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ClearingCleaningReceptacles(Kitchen): + """ + Clearing Cleaning Receptacles: composite task for Clearing Table activity. + + Simulates the process of clearing receptacles from the dining table and + cleaning them in the sink. + + Steps: + Pick the receptacles from the dining table and place them in the sink. + Then, turn on the water. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + # dining_table is a sufficiently large counter closest to the stools + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.init_robot_base_pos = self.dining_table + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_name_1 = self.get_obj_lang("receptacle1") + obj_name_2 = self.get_obj_lang("receptacle2") + ep_meta[ + "lang" + ] = f"Pick the {obj_name_1} and {obj_name_2} and place them in the sink. Then turn on the water." + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="receptacle1", + obj_groups="receptacle", + graspable=True, + washable=True, + placement=dict( + fixture=self.dining_table, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.8, 0.4), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="receptacle2", + obj_groups="receptacle", + graspable=True, + washable=True, + placement=dict( + fixture=self.dining_table, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.8, 0.4), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.25, 0.25), + pos=(0.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + receptacle1_in_sink = OU.obj_inside_of(self, "receptacle1", self.sink) + receptacle2_in_sink = OU.obj_inside_of(self, "receptacle2", self.sink) + + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + + return receptacle1_in_sink and receptacle2_in_sink and water_on diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/condiment_collection.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/condiment_collection.py new file mode 100644 index 0000000000000000000000000000000000000000..f8b61df41763dc7e9148aa8c81039c6c68dc29bd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/condiment_collection.py @@ -0,0 +1,126 @@ +from robocasa.environments.kitchen.kitchen import * + + +class CondimentCollection(Kitchen): + """ + Condiment Collection: composite task for Clearing Table activity. + + Simulates the task of collecting condiments from the counter and placing + them in the cabinet. + + Steps: + Pick the condiments from the counter and place them in the cabinet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the + condiments are picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + obj_name_1 = self.get_obj_lang("condiment1") + obj_name_2 = self.get_obj_lang("condiment2") + + ep_meta[ + "lang" + ] = f"Pick the {obj_name_1} and {obj_name_2} from the counter and place them in the cabinet." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="condiment1", + obj_groups="condiment", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.30, 0.30), + pos=(0.60, -1.0), + offset=(0.05, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="condiment2", + obj_groups="condiment", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.30, 0.30), + pos=(-0.60, -1.0), + offset=(-0.05, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far_condiment1 = OU.gripper_obj_far(self, obj_name="condiment1") + gripper_obj_far_condiment2 = OU.gripper_obj_far(self, obj_name="condiment2") + condiment1_inside_cab = OU.obj_inside_of(self, "condiment1", self.cab) + condiment2_inside_cab = OU.obj_inside_of(self, "condiment2", self.cab) + return ( + condiment1_inside_cab + and condiment2_inside_cab + and gripper_obj_far_condiment1 + and gripper_obj_far_condiment2 + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/dessert_assembly.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/dessert_assembly.py new file mode 100644 index 0000000000000000000000000000000000000000..24c06feef97ac5e2d9544910558737ea8390bbbc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/dessert_assembly.py @@ -0,0 +1,96 @@ +from robocasa.environments.kitchen.kitchen import * + + +class DessertAssembly(Kitchen): + """ + Dessert Assembly: composite task for Clearing Table activity. + + Simulates the task of assembling desserts. + + Steps: + Pick the container with the dessert on it and place in on the tray. + Pick the cupcake and place it on the tray. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER_NON_CORNER, size=(1.0, 0.4)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + dessert1 = self.get_obj_lang("dessert1") + container = self.get_obj_lang("dessert1_container") + + ep_meta["lang"] = ( + f"Pick up the {container} with {dessert1} and place it on the tray. " + "Pick up the cupcake and place it on the tray." + ) + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="receptacle", + obj_groups="tray", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="dessert1", + obj_groups=["donut", "cake"], + graspable=True, + placement=dict( + fixture=self.counter, + size=(1, 0.4), + pos=(0, -1), + try_to_place_in="bowl", + ), + ) + ) + + cfgs.append( + dict( + name="dessert2", + obj_groups="cupcake", + graspable=True, + placement=dict( + fixture=self.counter, + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + return cfgs + + def _check_success(self): + sweets_on_tray = ( + OU.check_obj_in_receptacle(self, "dessert1", "dessert1_container") + and OU.check_obj_in_receptacle(self, "dessert2", "receptacle") + and OU.check_obj_in_receptacle(self, "dessert1_container", "receptacle") + ) + + return sweets_on_tray and OU.gripper_obj_far(self, "receptacle") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/drinkware_consolidation.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/drinkware_consolidation.py new file mode 100644 index 0000000000000000000000000000000000000000..3f37d37391ecc22c33e9a4efeb179d1549416c1c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/drinkware_consolidation.py @@ -0,0 +1,76 @@ +from robocasa.environments.kitchen.kitchen import * + + +class DrinkwareConsolidation(Kitchen): + """ + Drinkware Consolidation: composite task for Clearing Table activity. + + Simulates the task of clearing the island drinkware and placing them back in a cabinet. + + Steps: + Pick the drinkware from the island and place them in the open cabinet. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5, 7, 8, 9] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.island = self.register_fixture_ref("island", dict(id=FixtureType.ISLAND)) + self.cab = self.register_fixture_ref( + "cab", + dict(id=FixtureType.CABINET_TOP, ref=self.island), + ) + self.init_robot_base_pos = self.island + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + objs_lang = self.get_obj_lang("obj_0") + for i in range(1, self.num_drinkware): + objs_lang += f", {self.get_obj_lang(f'obj_{i}')}" + ep_meta[ + "lang" + ] = f"Pick the {objs_lang} from the island and place {'them' if self.num_drinkware > 1 else 'it'} in the open cabinet." + return ep_meta + + def reset(self): + super().reset() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + self.num_drinkware = self.rng.choice([1, 2, 3]) + + for i in range(self.num_drinkware): + cfgs.append( + dict( + name=f"obj_{i}", + obj_groups=["drink"], + graspable=True, + washable=True, + placement=dict( + fixture=self.island, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.30, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + objs_in_cab = all( + [ + OU.obj_inside_of(self, f"obj_{i}", self.cab) + for i in range(self.num_drinkware) + ] + ) + gripper_obj_far = all( + [OU.gripper_obj_far(self, f"obj_{i}") for i in range(self.num_drinkware)] + ) + return objs_in_cab and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/food_cleanup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/food_cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..f56faa70d5a4230bb6d1f4b9c78f2d717e082f4a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/clearing_table/food_cleanup.py @@ -0,0 +1,83 @@ +from robocasa.environments.kitchen.kitchen import * + + +class FoodCleanup(Kitchen): + """ + Food Cleanup: composite task for Clearing Table activity. + + Simulates the task of cleaning up various food items left on the counter. + + Steps: + Pick the food items from the counter and place them in the cabinet. + Then close the cabinet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the + food items are picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + items = self.get_obj_lang("food0") + for i in range(1, self.num_food): + items += f", {self.get_obj_lang(f'food{i}')}" + ep_meta[ + "lang" + ] = f"Pick the {items} from the counter and place {'them' if self.num_food > 1 else 'it'} in the cabinet. Then close the cabinet." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + self.num_food = self.rng.choice([i for i in range(1, 4)]) + for i in range(self.num_food): + cfgs.append( + dict( + name=f"food{i}", + obj_groups=["fruit", "vegetable", "boxed_food"], + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.05, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + food_inside_cab = all( + [OU.obj_inside_of(self, f"food{i}", self.cab) for i in range(self.num_food)] + ) + cab_closed = True + door_state = self.cab.get_door_state(env=self) + + for joint_p in door_state.values(): + if joint_p > 0.05: + cab_closed = False + break + return cab_closed and food_inside_cab diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/defrost_by_category.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/defrost_by_category.py new file mode 100644 index 0000000000000000000000000000000000000000..63b2b92f0270fcef3c0f25edbc827be396fbd60b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/defrost_by_category.py @@ -0,0 +1,98 @@ +from robocasa.environments.kitchen.kitchen import Kitchen +from robocasa.models.fixtures import * + + +class DefrostByCategory(Kitchen): + """ + Defrost By Category: composite task for Defrosting Food activity. + + Simulates the task of arranging and defrosting fruits and vegetables by type. + + Steps: + Pick place all of the fruits in the running sink and all of the + vegetables in a bowl on the counter. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.5, 0.5)) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "There is a mixed pile of frozen fruits and vegetables on the counter. " + "Locate all the frozen vegetables and place the items in a bowl on the counter. " + "Take all the frozen fruits and defrost them in a running sink." + ) + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + + # Place the four objects (two fruits, two vegetables) + placements = list() + # Making the four regions separate - might help with + # initialization speed + for i in range(4): + placements.append( + dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.5, 0.5) + ), + size=(0.3, 0.4), + pos=("ref", -1), + ) + ) + self.rng.shuffle(placements) + + for i in range(4): + cfgs.append( + dict( + name="obj" + str(i), + obj_groups="fruit" if i <= 1 else "vegetable", + graspable=True, + placement=placements[i], + ) + ) + + # Bowl to place the vegetables in + cfgs.append( + dict( + name="container", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.5, 0.5) + ), + size=(0.3, 0.4), + pos=("ref", -1), + ), + ) + ) + return cfgs + + def _check_success(self): + fruits_in_sink = OU.obj_inside_of(self, "obj0", self.sink) and OU.obj_inside_of( + self, "obj1", self.sink + ) + vegetables_in_bowl = OU.check_obj_in_receptacle( + self, "obj2", "container" + ) and OU.check_obj_in_receptacle(self, "obj3", "container") + + gripper_obj_far = True + for i in range(4): + gripper_obj_far = gripper_obj_far and OU.gripper_obj_far( + self, obj_name="obj" + str(i) + ) + + return fruits_in_sink and vegetables_in_bowl and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/microwave_thawing.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/microwave_thawing.py new file mode 100644 index 0000000000000000000000000000000000000000..e917e43e5147c526ab561e39a58d3a3b7c30ed10 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/microwave_thawing.py @@ -0,0 +1,111 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MicrowaveThawing(Kitchen): + """ + Microwave Thawing: composite task for Defrosting Food activity. + + Simulates the task of defrosting food in a microwave. + + Steps: + Pick the food from the counter and place it in the microwave. + Then turn on the microwave. + """ + + # exclude layout 8 because the microwave is far from counters + EXCLUDE_LAYOUTS = [8] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.microwave = self.register_fixture_ref( + "microwave", dict(id=FixtureType.MICROWAVE) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.microwave) + ) + self.distr_counter = self.register_fixture_ref( + "distractor_counter", + dict( + id=FixtureType.COUNTER, + ref=self.microwave, + ), + ) + self.init_robot_base_pos = self.microwave + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.microwave.set_door_state(min=0, max=0, env=self, rng=self.rng) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_name = self.get_obj_lang() + ep_meta["lang"] = ( + f"Pick the {obj_name} from the counter and place it in the microwave. " + "Then turn on the microwave." + ) + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups="food", + graspable=True, + microwavable=True, + freezable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + try_to_place_in="container", + ), + ) + ) + cfgs.append( + dict( + name="container", + obj_groups=("plate"), + placement=dict( + fixture=self.microwave, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.distr_counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.50, 0.20), + pos=(0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + obj_in_microwave = OU.obj_inside_of(self, "obj", self.microwave) + + button_pressed = self.microwave.get_state()["turned_on"] + gripper_obj_far = OU.gripper_obj_far(self) + + return obj_in_microwave and gripper_obj_far and button_pressed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/quick_thaw.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/quick_thaw.py new file mode 100644 index 0000000000000000000000000000000000000000..cf998d1168aa2c3b4e7cef4a8de588173a6ae601 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/quick_thaw.py @@ -0,0 +1,96 @@ +from robocasa.environments.kitchen.kitchen import * + + +class QuickThaw(Kitchen): + """ + Quick Thaw: composite task for Defrosting Food activity. + + Simulates the task of defrosting meat on a stove. + + Steps: + Pick the meat from the counter and place it in a pot on a burner. + Then turn on the burner. + + Args: + knob_id (str): The id of the knob who's burner the pot will be placed on. + If "random", a random knob is chosen. + """ + + def __init__(self, knob_id="random", *args, **kwargs): + self.knob_id = knob_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + + # Pick a knob/burner on a stove and a counter close to it + valid_knobs = [k for (k, v) in self.stove.knob_joints.items() if v is not None] + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=FixtureType.STOVE) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Frozen meat rests on a plate on the counter. " + "Retrieve the meat and place it in a pot on a burner. Then turn the burner on." + ) + ep_meta["knob"] = self.knob + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.stove.set_knob_state(mode="off", knob=self.knob, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="meat", + obj_groups="meat", + placement=dict( + fixture=self.counter, + size=(0.50, 0.30), + sample_region_kwargs=dict( + ref=self.stove, + ), + pos=("ref", -1.0), + try_to_place_in="plate", + ), + ) + ) + + # place the pot on the specific burner we chose earlier + cfgs.append( + dict( + name="container", + obj_groups=("pot"), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + sample_region_kwargs=dict( + locs=[self.knob], + ), + size=(0.02, 0.02), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + ), + ) + ) + return cfgs + + def _check_success(self): + knobs_state = self.stove.get_knobs_state(env=self) + knob_value = knobs_state[self.knob] + knob_on = 0.35 <= np.abs(knob_value) <= 2 * np.pi - 0.35 + return ( + knob_on + and OU.check_obj_in_receptacle(self, "meat", "container") + and OU.gripper_obj_far(self, obj_name="meat") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/thaw_in_sink.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/thaw_in_sink.py new file mode 100644 index 0000000000000000000000000000000000000000..f4440616ff46bdad75aea6d456575872686eed5e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/defrosting_food/thaw_in_sink.py @@ -0,0 +1,93 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ThawInSink(Kitchen): + """ + Thaw In Sink: composite task for Defrosting Food activity. + + Simulates the task of defrosting food in a sink. + + Steps: + Pick the food from the counter and place it in the sink. + Then turn on the sink faucet. + + Args: + obj_groups (str): The object groups to sample from for the task + """ + + def __init__(self, obj_groups="all", *args, **kwargs): + self.obj_groups = obj_groups + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.4, 0.4)) + ) + self.init_robot_base_pos = self.sink + + def _reset_internal(self): + + super()._reset_internal() + + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_name = self.get_obj_lang() + ep_meta["lang"] = ( + f"Pick the {obj_name} from the counter and place it in the sink. " + "Then turn on the sink faucet." + ) + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + graspable=True, + washable=True, + freezable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.4, 0.4) + ), + try_to_place_in="container", + size=(0.30, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.30), + ), + ) + ) + + return cfgs + + def _check_success(self): + obj_in_sink = OU.obj_inside_of(self, "obj", self.sink) + + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + + return obj_in_sink and water_on diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/assemble_cooking_array.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/assemble_cooking_array.py new file mode 100644 index 0000000000000000000000000000000000000000..31c4148730b8c6dad0fe8d8517e0eef5ffc497b4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/assemble_cooking_array.py @@ -0,0 +1,126 @@ +from robocasa.environments.kitchen.kitchen import * + + +class AssembleCookingArray(Kitchen): + """ + Assemble Cooking Array: composite task for Frying activity. + + Simulates the task of assembling ingredients for cooking. + + Steps: + Move the meat onto the pan on the stove. Then, move the condiment and + vegetable from the cabinet to the counter where the plate is. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=[0.30, 0.40]) + ) + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.counter) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + meat_name = self.get_obj_lang("meat") + condiment_name = self.get_obj_lang("condiment") + vegetable_name = self.get_obj_lang("vegetable") + ep_meta["lang"] = ( + f"Move the {meat_name} onto the pan on the stove. " + f"Then move the {condiment_name} and {vegetable_name} from the cabinet to the counter where the plate is." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="pan", + obj_groups=("pan"), + placement=dict( + fixture=self.stove, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + size=(0.05, 0.05), + ), + ) + ) + + cfgs.append( + dict( + name="meat", + obj_groups="meat", + graspable=True, + heatable=True, + placement=dict( + fixture=self.counter, + loc="nn", + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + try_to_place_in="container", + ), + ) + ) + + cfgs.append( + dict( + name="condiment", + obj_groups="condiment", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(-1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="vegetable", + obj_groups="vegetable", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(1.0, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + meat_in_pan = OU.check_obj_in_receptacle(self, "meat", "pan", th=0.07) + gripper_vegetable_far = OU.gripper_obj_far(self, obj_name="vegetable") + gripper_condiment_far = OU.gripper_obj_far(self, obj_name="condiment") + gripper_meat_far = OU.gripper_obj_far(self, obj_name="meat") + vegetable_on_counter = OU.check_obj_fixture_contact( + self, "vegetable", self.counter + ) + condiment_on_counter = OU.check_obj_fixture_contact( + self, "condiment", self.counter + ) + return ( + meat_in_pan + and gripper_vegetable_far + and gripper_condiment_far + and gripper_meat_far + and vegetable_on_counter + and condiment_on_counter + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/frying_pan_adjustment.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/frying_pan_adjustment.py new file mode 100644 index 0000000000000000000000000000000000000000..efd1a57ed327cd03ba1c05d4122455af661e6087 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/frying_pan_adjustment.py @@ -0,0 +1,101 @@ +from robocasa.environments.kitchen.kitchen import * + + +class FryingPanAdjustment(Kitchen): + """ + Frying Pan Adjustment: composite task for Frying activity. + + Simulates the task of adjusting the frying pan on the stove. + + Steps: + Move the pan from the current burner to another burner and turn on + the burner. + """ + + def __init__(self, *args, **kwargs): + self.start_loc = None + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.init_robot_base_pos = self.stove + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + + # First call super reset so that the pan is placed on the stove + # then determine where it is placed and turn on the corresponding burner and update the start_loc + super()._reset_internal() + valid_knobs = self.stove.get_knobs_state(env=self).keys() + pan_loc = self._check_obj_location_on_stove("obj") + + for knob in valid_knobs: + if pan_loc == knob: + self.start_loc = pan_loc + self.stove.set_knob_state(mode="on", knob=knob, env=self, rng=self.rng) + else: + self.stove.set_knob_state(mode="off", knob=knob, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups=("pan"), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + size=(0.05, 0.05), + ), + ) + ) + + return cfgs + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = f"Pick and place the pan from the current burner to another burner and turn the burner on." + return ep_meta + + # TODO Move this function to OU + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + """ + Check if the object is on the stove and close to a burner + Returns the location of the burner if the object is on the stove and close to a burner. None otherwise. + """ + + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + if obj_on_site: + return location + + return None + + def _check_success(self): + # get the current location of the pan on the stove + curr_loc = self._check_obj_location_on_stove("obj") + knobs_state = self.stove.get_knobs_state(env=self) + knob_on_loc = False + if curr_loc is not None and curr_loc in knobs_state: + # check if burner is on where the pan is placed + knob_on_loc = 0.35 <= np.abs(knobs_state[curr_loc]) <= 2 * np.pi - 0.35 + + # return success if the pan is on a burner, the burner is on, and the burner is not the same as the start location + return OU.gripper_obj_far(self) and knob_on_loc and curr_loc != self.start_loc diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/meal_prep_staging.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/meal_prep_staging.py new file mode 100644 index 0000000000000000000000000000000000000000..5037335e24a27319487b61fa26125c4267231e8f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/meal_prep_staging.py @@ -0,0 +1,150 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MealPrepStaging(Kitchen): + """ + Meal Prep Staging: composite task for Frying activity. + + Simulates the task of cooking various ingredients. + + Steps: + Place the pans on different burners, then place the vegetable + and meat on different pans. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=(0.3, 0.2)) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj_name_1 = self.get_obj_lang("vegetable") + obj_name_2 = self.get_obj_lang("meat") + ep_meta["lang"] = ( + "Place both pans onto different burners. " + f"Then place the {obj_name_1} and the {obj_name_2} on different pans." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + + cfgs = [] + + cfgs.append( + dict( + name="pan1", + obj_groups=("pan"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.stove, loc="left_right"), + size=(0.5, 0.05), + pos=("ref", 0.2), + offset=(-0.13, 0.0), + rotation=0, + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="pan2", + obj_groups=("pan"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + loc="left_right", + ), + size=(0.5, 0.05), + pos=("ref", -0.3), + offset=(-0.13, 0.0), + rotation=0, + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="vegetable", + obj_groups=("vegetable"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.stove, loc="left_right"), + size=(0.4, 0.4), + pos=("ref", 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="meat", + obj_groups=("meat"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.stove, loc="left_right"), + size=(0.5, 0.5), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + """ + Check if object is on a burner site on the stove. + Returns the location of the burner if the object is on the stove and close to a burner. None otherwise. + """ + + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + if obj_on_site: + return location + + return None + + def _check_success(self): + + vegetable_on_pan1 = OU.check_obj_in_receptacle(self, "vegetable", "pan1") + vegetable_on_pan2 = OU.check_obj_in_receptacle(self, "vegetable", "pan2") + meat_on_pan1 = OU.check_obj_in_receptacle(self, "meat", "pan1") + meat_on_pan2 = OU.check_obj_in_receptacle(self, "meat", "pan2") + + food_on_pans = (vegetable_on_pan1 and meat_on_pan2) or ( + vegetable_on_pan2 and meat_on_pan1 + ) + + pan1_loc = self._check_obj_location_on_stove(obj_name="pan1") + pan2_loc = self._check_obj_location_on_stove(obj_name="pan2") + + pans_on_stove = pan1_loc != None and pan2_loc != None + pans_diff = pan1_loc != pan2_loc + + return pans_on_stove and pans_diff and food_on_pans diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/searing_meat.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/searing_meat.py new file mode 100644 index 0000000000000000000000000000000000000000..6d1e664450b1f611995a3d08993770ca18c66a80 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/searing_meat.py @@ -0,0 +1,130 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SearingMeat(Kitchen): + """ + Searing Meat: composite task for Frying activity. + + Simulates the task of searing meat. + + Steps: + Place the pan on the specified burner on the stove, + then place the meat on the pan and turn the burner on. + + Args: + knob_id (str): The id of the knob who's burner the pan will be placed on. + If "random", a random knob is chosen. + """ + + def __init__(self, knob_id="random", *args, **kwargs): + self.knob_id = knob_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=[0.30, 0.40]) + ) + + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.stove) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + meat_name = self.get_obj_lang("meat") + ep_meta["lang"] = ( + f"Grab the pan from the cabinet and place it on the {self.knob.replace('_', ' ')} burner on the stove. " + f"Then place the {meat_name} on the stove and turn the burner on." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + + valid_knobs = self.stove.get_knobs_state(env=self).keys() + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + + self.stove.set_knob_state(mode="off", knob=self.knob, env=self, rng=self.rng) + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="pan", + obj_groups=("pan"), + placement=dict( + fixture=self.cab, + ensure_object_boundary_in_range=False, + pos=(0.0, -0.3), + size=(0.4, 0.02), + rotation=np.pi / 2, + ), + ) + ) + + cfgs.append( + dict( + name="meat", + obj_groups="meat", + graspable=True, + heatable=True, + placement=dict( + fixture=self.counter, + loc="nn", + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + try_to_place_in="container", + ), + ) + ) + + return cfgs + + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + """ + Check if the object is on the stove and close to a burner and the knob is on. + Returns the location of the burner if the object is on the stove, close to a burner, and the burner is on. + None otherwise. + """ + + knobs_state = self.stove.get_knobs_state(env=self) + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + knob_on = ( + (0.35 <= np.abs(knobs_state[location]) <= 2 * np.pi - 0.35) + if location in knobs_state + else False + ) + + if obj_on_site and knob_on: + return location + + return None + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, obj_name="meat") + pan_loc = self._check_obj_location_on_stove("pan", threshold=0.15) == self.knob + meat_in_pan = OU.check_obj_in_receptacle(self, "meat", "pan", th=0.07) + return gripper_obj_far and pan_loc and meat_in_pan diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/setup_frying.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/setup_frying.py new file mode 100644 index 0000000000000000000000000000000000000000..16e6d87a656694de367ac735c354164c90e275b9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/frying/setup_frying.py @@ -0,0 +1,124 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SetupFrying(Kitchen): + """ + Setup Frying: composite task for Frying activity. + + Simulates the task of setting up the frying pan on the stove. + + Steps: + Place the pan on the stove burner and turn the burner on. + + Args: + cab_id (str): The id of the cabinet where the pan is placed. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.cab = self.register_fixture_ref( + "cab", dict(id=self.cab_id, ref=self.stove) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + f"Pick the pan from the cabinet and place it on the stove. " + "Then turn on the stove burner for the pan." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.cab.set_door_state(min=0, max=0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="pan", + obj_groups="pan", + graspable=True, + placement=dict( + fixture=self.cab, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + size=(0.05, 0.02), + pos=(0, 0), + # apply a custom rotation for the pan so that it fits better in the cabinet + # (if the handle sticks out it may not fit) + rotation=(2 * np.pi / 8, 3 * np.pi / 8), + ), + ) + ) + + # distractors + for i in range(2): + cfgs.append( + dict( + name=f"distr_counter_{i}", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.50), + pos=(0.0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="distr_stove", + obj_groups=("kettle_non_electric"), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + size=(0.02, 0.02), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the pan is placed on a stove burner and the burner is turned on. + """ + knobs_state = self.stove.get_knobs_state(env=self) + obj = self.objects["pan"] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, "pan", self.stove) + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < 0.15 + knob_on = ( + (0.35 <= np.abs(knobs_state[location]) <= 2 * np.pi - 0.35) + if location in knobs_state + else False + ) + + if obj_on_site and knob_on and OU.gripper_obj_far(self, "pan"): + return True + + return False diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/bread_selection.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/bread_selection.py new file mode 100644 index 0000000000000000000000000000000000000000..2de55cabf9d78188a6661f8fa4ffbc7f6e12d2a3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/bread_selection.py @@ -0,0 +1,123 @@ +from robocasa.environments.kitchen.kitchen import * + + +class BreadSelection(Kitchen): + """ + Bread Selection: composite task for Making Toast activity. + + Simulates the task of setting up ingredients for making a bread snack. + + Steps: + Place a croissant and a jar of jam on the cutting board. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to specify the cabinet where the jam is placed. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.6)) + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "From the different types of pastries on the counter, select a croissant and place it on the cutting board. " + "Then retrieve a jar of jam from the cabinet and place it alongside the croissant on the cutting board." + ) + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="cutting_board", + obj_groups="cutting_board", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.3, 0.5), + pos=(1, -1.0), + rot=np.pi / 2, + ), + ) + ) + + # Three types of pastries + cfgs.append( + dict( + name="distr_pastry", + obj_groups=self.rng.choice(["baguette", "cupcake"]), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab), + size=(0.7, 0.5), + pos=(-1, -1.0), + try_to_place_in="plate", + ), + ) + ) + cfgs.append( + dict( + name="croissant", + obj_groups="croissant", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab), + size=(0.7, 0.5), + pos=(-1, -1.0), + try_to_place_in="plate", + ), + ) + ) + + # Jar of jam in the cabinet + cfgs.append( + dict( + name="jam", + obj_groups="jam", + placement=dict(fixture=self.cab, size=(1.0, 0.20), pos=(0, -1.0)), + ) + ) + + # Additional distractor on the counter + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab), + size=(1.0, 0.20), + pos=(0, 1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + # Check that both the croissant and jam are on the cutting board + return ( + OU.check_obj_in_receptacle(self, "croissant", "cutting_board") + and OU.gripper_obj_far(self, obj_name="croissant") + and OU.check_obj_in_receptacle(self, "jam", "cutting_board") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/cheesy_bread.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/cheesy_bread.py new file mode 100644 index 0000000000000000000000000000000000000000..5fe44de5c1b861709ed44f4f7f396feb69a89d82 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/cheesy_bread.py @@ -0,0 +1,79 @@ +from robocasa.environments.kitchen.kitchen import * + + +class CheesyBread(Kitchen): + """ + Cheesy Bread: composite task for Making Toast activity. + + Simulates the task of making cheesy bread. + + Steps: + Start with a slice of bread already on a plate and a wedge of cheese on the + counter. Pick up the wedge of cheese and place it on the slice of bread to + prepare a simple cheese on bread dish. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER_NON_CORNER, size=(0.6, 0.6)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick up the wedge of cheese and place it on the slice of bread to prepare a simple cheese on bread dish." + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="bread", + obj_groups="bread", + placement=dict( + fixture=self.counter, + size=(0.5, 0.7), + pos=(0, -1.0), + try_to_place_in="cutting_board", + ), + ) + ) + cfgs.append( + dict( + name="cheese", + obj_groups="cheese", + placement=dict(fixture=self.counter, size=(1.0, 0.3), pos=(0, -1.0)), + ) + ) + + # Distractor on the counter + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict(fixture=self.counter, size=(1.0, 0.20), pos=(0, 1.0)), + ) + ) + return cfgs + + def _check_success(self): + # Bread is still on the cutting board, and cheese is on top + return ( + OU.check_obj_in_receptacle(self, "bread", "bread_container") + and OU.gripper_obj_far(self, obj_name="cheese") + and self.check_contact(self.objects["cheese"], self.objects["bread"]) + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/prepare_toast.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/prepare_toast.py new file mode 100644 index 0000000000000000000000000000000000000000..bc331618814f5f8413fa2f9f3cc7186f3fd604d8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/prepare_toast.py @@ -0,0 +1,129 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrepareToast(Kitchen): + """ + Prepare Toast: composite task for Making Toast activity. + + Simulates the task of preparing toast. + + Steps: + Open the cabinet, pick the bread, place it on the cutting board, pick the jam, + place it on the counter, and close the cabinet + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=FixtureType.TOASTER) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick the bread, place it on the cutting board, " + "pick the jam, place it on the counter, and close the cabinet." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.9, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=("bread"), + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.30), + pos=(0, -0.1), + ), + ) + ) + + cfgs.append( + dict( + name="container", + obj_groups="cutting_board", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.5, 0.5), + pos=(0.0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="obj2", + obj_groups="jam", + placement=dict( + fixture=self.cab, + size=(0.3, 0.15), + pos=(0.0, -1.0), + offset=(-0.05, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="obj3", + obj_groups="knife", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.3, 0.3), + pos=(0.0, 0.0), + ensure_object_boundary_in_range=False, + offset=(-0.05, 0.05), + ), + ) + ) + + return cfgs + + def _check_door_closed(self): + door_state = self.cab.get_door_state(env=self) + + success = True + for joint_p in door_state.values(): + if joint_p > 0.05: + success = False + break + + return success + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self) + jam_on_counter = OU.check_obj_fixture_contact(self, "obj2", self.counter) + bread_on_cutting_board = OU.check_obj_in_receptacle(self, "obj", "container") + cutting_board_on_counter = OU.check_obj_fixture_contact( + self, "container", self.counter + ) + cabinet_closed = self._check_door_closed() + return ( + jam_on_counter + and gripper_obj_far + and bread_on_cutting_board + and cutting_board_on_counter + and cabinet_closed + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/sweet_savory_toast_setup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/sweet_savory_toast_setup.py new file mode 100644 index 0000000000000000000000000000000000000000..c607ad7a9e49a52e9e69212534ca89ecd0fe6d6f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/making_toast/sweet_savory_toast_setup.py @@ -0,0 +1,140 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SweetSavoryToastSetup(Kitchen): + """ + Sweet Savory Toast Setup: composite task for Making Toast activity. + + Simulates the task of setting up the ingredients for making sweet and savory + toast. + + Steps: + Pick the avocado and bread from the counter and place it on the plate. + Then pick the jam from the cabinet and place it next to the plate. + Lastly, close the cabinet door. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to specify the cabinet where the jam is placed. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.6)) + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick the avocado and bread from the counter and place them on the plate. " + "Then pick the jam from the cabinet and place it next to the plate. " + "Lastly, close the cabinet door." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="plate", + obj_groups="plate", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.5), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="avocado", + obj_groups="avocado", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.6, 0.6), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bread", + obj_groups="bread", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.6, 0.6), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="jam", + obj_groups="jam", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.4, 0.4), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, "plate") + jam_on_counter = self.check_contact(self.objects["jam"], self.counter) + food_on_plate = OU.check_obj_in_receptacle( + self, "bread", "plate" + ) and OU.check_obj_in_receptacle(self, "avocado", "plate") + door_state = self.cab.get_door_state(env=self) + + closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + closed = False + break + + return gripper_obj_far and food_on_plate and jam_on_counter and closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_for_tenderizing.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_for_tenderizing.py new file mode 100644 index 0000000000000000000000000000000000000000..daea91132b1edf0affb914d8cb8c46a31877312a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_for_tenderizing.py @@ -0,0 +1,85 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrepForTenderizing(Kitchen): + """ + Prep For Tenderizing: composite task for Meat Preparation activity. + + Simulates the task of preparing meat for tenderizing. + + Steps: + Retrieve a rolling pin from the cabinet and place it next to the meat on + the cutting board to prepare for tenderizing. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the rolling pin + is picked. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.5, 0.5)) + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Retrieve a rolling pin from the cabinet and place it next to the " + "meat on the cutting board to prepare for tenderizing." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="meat", + graspable=True, + obj_groups="meat", + placement=dict( + fixture=self.counter, + size=(0.1, 0.1), + ensure_object_boundary_in_range=False, + pos=(0, -0.3), + try_to_place_in="cutting_board", + ), + ) + ) + + cfgs.append( + dict( + name="rolling_pin", + obj_groups="rolling_pin", + graspable=True, + placement=dict( + fixture=self.cab, + ensure_object_boundary_in_range=False, + size=(0.05, 0.02), + pos=(0, 0), + ), + ) + ) + return cfgs + + def _check_success(self): + return ( + OU.check_obj_in_receptacle(self, "rolling_pin", "meat_container") + and OU.gripper_obj_far(self, obj_name="meat_container") + and OU.check_obj_in_receptacle(self, "meat", "meat_container") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_marinating_meat.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_marinating_meat.py new file mode 100644 index 0000000000000000000000000000000000000000..b8086d1601d2b0461e7fe9c148d95dac041a24e3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/meat_preparation/prep_marinating_meat.py @@ -0,0 +1,131 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrepMarinatingMeat(Kitchen): + """ + Prep Marinating Meat: composite task for Meat Preparation activity. + + Simulates the task of preparing meat for marinating. + + Steps: + Take the meat from its container and place it on the cutting board. Then, + take the condiment from the cabinet and place it next to the cutting board. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the condiment + is picked. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + # fixture type hingle double bc there will be a large counter space under the cabinet + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.6)) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + cond_name = self.get_obj_lang("condiment") + meat_name = self.get_obj_lang("meat") + cont_name = self.get_obj_lang("meat_container") + ep_meta["lang"] = ( + f"Pick the {meat_name} from the {cont_name} and place it on the cutting board. " + f"Then pick the {cond_name} from the cabinet and place it next to the cutting board." + ) + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="cutting_board", + obj_groups="cutting_board", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.5), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="meat", + obj_groups="meat", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + try_to_place_in="container", + ), + ) + ) + + cfgs.append( + dict( + name="condiment", + obj_groups="condiment_bottle", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.1), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, "condiment") and OU.gripper_obj_far( + self, "meat" + ) + condiment_on_counter = self.check_contact( + self.objects["condiment"], self.counter + ) + meat_on_cutting_board = OU.check_obj_in_receptacle( + self, "meat", "cutting_board" + ) + cutting_board_on_counter = OU.check_obj_fixture_contact( + self, "cutting_board", self.counter + ) + return ( + gripper_obj_far + and meat_on_cutting_board + and cutting_board_on_counter + and condiment_on_counter + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/colorful_salsa.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/colorful_salsa.py new file mode 100644 index 0000000000000000000000000000000000000000..5ccac81df0ecf32031ab89ca78749d31e728ec6c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/colorful_salsa.py @@ -0,0 +1,123 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ColorfulSalsa(Kitchen): + """ + Colorful Salsa: composite task for Mixing And Blending activity. + + Simulates the task of preparing a colorful salsa. + + Steps: + Place the avocado, onion, tomato and bell pepper on the cutting board. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER_NON_CORNER, size=(1.0, 0.4)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Place the avocado, onion, tomato and bell pepper on the cutting board." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="receptacle", + obj_groups="cutting_board", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="bell_pepper", + obj_groups="bell_pepper", + placement=dict( + fixture=self.counter, + # sample_region_kwargs=dict( + # top_size=(1.0, 0.4) + # ), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="tomato", + obj_groups="tomato", + placement=dict( + fixture=self.counter, + # sample_region_kwargs=dict( + # top_size=(1.0, 0.4) + # ), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="avocado", + obj_groups="avocado", + placement=dict( + fixture=self.counter, + # sample_region_kwargs=dict( + # top_size=(1.0, 0.4) + # ), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="onion", + obj_groups="onion", + placement=dict( + fixture=self.counter, + # sample_region_kwargs=dict( + # top_size=(1.0, 0.4) + # ), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + return cfgs + + def _check_success(self): + vegetables_on_board = ( + OU.check_obj_in_receptacle(self, "onion", "receptacle") + and OU.check_obj_in_receptacle(self, "avocado", "receptacle") + and OU.check_obj_in_receptacle(self, "tomato", "receptacle") + and OU.check_obj_in_receptacle(self, "bell_pepper", "receptacle") + ) + + return vegetables_on_board and OU.gripper_obj_far(self, "receptacle") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/setup_juicing.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/setup_juicing.py new file mode 100644 index 0000000000000000000000000000000000000000..0e31386b2174a0f2da319a2cede849b3b2436f0b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/setup_juicing.py @@ -0,0 +1,100 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SetupJuicing(Kitchen): + """ + Setup Juicing: composite task for Mixing And Blending activity. + + Simulates the task of setting up juicing. + + Steps: + Open the cabinet, pick all fruits from the cabinet and place them on the + counter. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to specify the cabinet to pick the fruits from. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = f"Open the cabinet, pick all {self.num_fruits} fruits from the cabinet and place them on the counter." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + self.num_fruits = self.rng.choice([2, 3, 4]) + cfgs = [] + for i in range(self.num_fruits): + + cfgs.append( + dict( + name=f"obj{i}", + obj_groups="fruit", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.60, 0.40), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + fruit_on_counter = all( + [ + OU.check_obj_fixture_contact(self, f"obj{i}", self.counter) + for i in range(self.num_fruits) + ] + ) + return fruit_on_counter and OU.gripper_obj_far(self, "obj1") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/spicy_marinade.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/spicy_marinade.py new file mode 100644 index 0000000000000000000000000000000000000000..28148706838c2b80477230c65466d2a801be15b8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/mixing_and_blending/spicy_marinade.py @@ -0,0 +1,132 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SpicyMarinade(Kitchen): + """ + Spicy Marinade: composite task for Mixing And Blending activity. + + Simulates the task of preparing a spicy marinade. + + Steps: + Open the cabinet. Place the bowl and condiment on the counter. Then place + the lime and garlic on the cutting board. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + # need to fit the bowl and condiment in the cab, so use double door hinge + self.cab = self.register_fixture_ref( + "cabinet", dict(id=FixtureType.DOOR_TOP_HINGE_DOUBLE) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Open the cabinet. Place the bowl and condiment on the counter. " + "Then place the lime and garlic on the cutting board." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="receptacle", + obj_groups="cutting_board", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.8, 0.4), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + placement=dict( + fixture=self.cab, + size=(0.6, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="condiment", + obj_groups="condiment", + placement=dict( + fixture=self.cab, + size=(0.5, 0.2), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="lime", + obj_groups="lime", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.3, 0.2), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="garlic", + obj_groups="garlic", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.3, 0.2), + pos=("ref", -1), + ), + ) + ) + + return cfgs + + def _check_success(self): + objs_on_counter = OU.check_obj_fixture_contact( + self, "bowl", self.counter + ) and OU.check_obj_fixture_contact(self, "condiment", self.counter) + objs_on_board = OU.check_obj_in_receptacle( + self, "lime", "receptacle" + ) and OU.check_obj_in_receptacle(self, "garlic", "receptacle") + gripper_far = ( + OU.gripper_obj_far(self, "receptacle") + and OU.gripper_obj_far(self, "bowl") + and OU.gripper_obj_far(self, "condiment") + ) + + return objs_on_counter and objs_on_board and gripper_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/heat_mug.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/heat_mug.py new file mode 100644 index 0000000000000000000000000000000000000000..f01d0a5ad5005245bf1e5cf7006cd797b133cc07 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/heat_mug.py @@ -0,0 +1,79 @@ +from robocasa.environments.kitchen.kitchen import * + + +class HeatMug(Kitchen): + """ + Heat Mug: composite task for Reheating Food activity. + + Simulates the task of reheating a mug. + + Steps: + Open the cabinet, pick the mug, place it inside the microwave, and close + the microwave. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.microwave = self.register_fixture_ref( + "microwave", dict(id=FixtureType.MICROWAVE) + ) + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.microwave) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the mug from the cabinet and place it inside the microwave. Then close the microwave." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + self.microwave.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups="mug", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self) + obj_in_microwave = OU.obj_inside_of(self, "obj", self.microwave) + door_state = self.microwave.get_door_state(self)["door"] + door_closed = door_state <= 0.005 + + return obj_in_microwave and gripper_obj_far and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/make_loaded_potato.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/make_loaded_potato.py new file mode 100644 index 0000000000000000000000000000000000000000..9b8ceb49d0901af919920ff4635a5eb4a59ca0a8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/make_loaded_potato.py @@ -0,0 +1,102 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MakeLoadedPotato(Kitchen): + """ + Make Loaded Potato: composite task for Reheating Food activity. + + Simulates the task of making a loaded potato. + + Steps: + Retrieve the reheated potato from the microwave, then place it on the + cutting board along with cheese and a bottle of condiment. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.microwave = self.register_fixture_ref( + "microwave", dict(id=FixtureType.MICROWAVE) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.6, 0.6), ref=self.microwave) + ) + self.init_robot_base_pos = self.microwave + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + f"Retrieve the reheated potato from the microwave, then place it on " + "the cutting board along with cheese and a bottle of condiment." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + # Initialize potato in the microwave + cfgs.append( + dict( + name="potato", + obj_groups="potato", + placement=dict( + fixture=self.microwave, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + try_to_place_in="bowl", + ), + ) + ) + + # Cutting board at the center of the counter + cfgs.append( + dict( + name="cutting_board", + obj_groups="cutting_board", + placement=dict( + fixture=self.counter, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + pos=(0, 0), + rotation=np.pi / 2, + ), + ) + ) + + # Cheese and condiment to be placed on the cutting board + cfgs.append( + dict( + name="condiment", + obj_groups="condiment", + placement=dict(fixture=self.counter, size=(0.6, 0.5), pos=(0, -1)), + ) + ) + cfgs.append( + dict( + name="cheese", + obj_groups="cheese", + placement=dict(fixture=self.counter, size=(0.6, 0.5), pos=(0, -1)), + ) + ) + return cfgs + + def _check_success(self): + gripper_far = ( + OU.gripper_obj_far(self, "potato") + and OU.gripper_obj_far(self, "condiment") + and OU.gripper_obj_far(self, "cheese") + ) + objects_in_place = ( + OU.check_obj_in_receptacle(self, "potato", "cutting_board") + and OU.check_obj_in_receptacle(self, "condiment", "cutting_board") + and OU.check_obj_in_receptacle(self, "cheese", "cutting_board") + ) + return gripper_far and objects_in_place diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/simmering_sauce.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/simmering_sauce.py new file mode 100644 index 0000000000000000000000000000000000000000..6a63b65a76ac3a89f6e3f61bddbbf3f8119dd952 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/simmering_sauce.py @@ -0,0 +1,138 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SimmeringSauce(Kitchen): + """ + Simmering Sauce: composite task for Reheating Food activity. + + Simulates the task of simmering a sauce. + + Steps: + Place the pan on a specific burner on the stove, then place the tomato and + the onion in the pan and turn on the burner. + + Args: + knob_id (str): The id of the knob who's burner the pan will be placed on. + If "random", a random knob is chosen. + """ + + def __init__(self, knob_id="random", *args, **kwargs): + self.knob_id = knob_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=(0.5, 0.4)) + ) + self.init_robot_base_pos = self.stove + + if "refs" in self._ep_meta: + self.knob = self._ep_meta["refs"]["knob"] + else: + valid_knobs = [ + k for (k, v) in self.stove.knob_joints.items() if v is not None + ] + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + f"Place the pan on the {self.knob.replace('_', ' ')} burner on the stove. " + f"Then place the tomato and the onion in the pan and turn on the {self.knob.replace('_', ' ')} burner." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="pan", + obj_groups="pan", + placement=dict( + fixture=self.counter, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + sample_region_kwargs=dict(ref=self.stove, top_size=(0.50, 0.40)), + size=(0.25, 0.05), + pos=("ref", 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="tomato", + obj_groups="tomato", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.35, 0.2), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="onion", + obj_groups="onion", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.35, 0.2), + pos=("ref", 0.0), + ), + ) + ) + + return cfgs + + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + """ + Check if the object is on the stove and close to a burner. + Returns the location of the burner if the object is on the stove and close to a burner. None otherwise. + """ + + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + if obj_on_site: + return location + + return None + + def _check_success(self): + pan_on_stove = self._check_obj_location_on_stove("pan") == self.knob + tomato_in_pan = OU.check_obj_in_receptacle(self, "tomato", "pan") + onion_in_pan = OU.check_obj_in_receptacle(self, "onion", "pan") + + knobs_state = self.stove.get_knobs_state(env=self) + knob_value = knobs_state[self.knob] + knob_on = 0.35 <= np.abs(knob_value) <= 2 * np.pi - 0.35 + + return pan_on_stove and tomato_in_pan and onion_in_pan and knob_on diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/waffle_reheat.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/waffle_reheat.py new file mode 100644 index 0000000000000000000000000000000000000000..1c76c760d27428c4793d4f53627fb13c66e7176e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/waffle_reheat.py @@ -0,0 +1,64 @@ +from robocasa.environments.kitchen.kitchen import * + + +class WaffleReheat(Kitchen): + """ + Waffle Reheat: composite task for Reheating Food activity. + + Simulates the task of reheating a waffle. + + Steps: + Open the microwave. Place the bowl with waffle inside the microwave, then + close the microwave door and turn it on. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.microwave = self.register_fixture_ref( + "microwave", dict(id=FixtureType.MICROWAVE) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.6, 0.6), ref=self.microwave) + ) + self.init_robot_base_pos = self.microwave + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + f"Open the microwave, place the bowl with waffle inside the microwave, " + "then close the microwave door and turn it on." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="waffle", + obj_groups="waffle", + placement=dict( + fixture=self.counter, + size=(0.3, 0.3), + pos=(-1.0, -1.0), + try_to_place_in="bowl", + ), + ) + ) + return cfgs + + def _check_success(self): + gripper_far = OU.gripper_obj_far(self, "waffle") + waffle_in_bowl = OU.check_obj_in_receptacle(self, "waffle", "waffle_container") + bowl_in_microwave = OU.obj_inside_of(self, "waffle_container", self.microwave) + microwave_on = self.microwave.get_state()["turned_on"] + return waffle_in_bowl and bowl_in_microwave and microwave_on and gripper_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/warm_croissant.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/warm_croissant.py new file mode 100644 index 0000000000000000000000000000000000000000..b568627fd263d2f97fe8bbfad235ccde97fdebc5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/reheating_food/warm_croissant.py @@ -0,0 +1,95 @@ +from robocasa.environments.kitchen.kitchen import * + + +class WarmCroissant(Kitchen): + """ + Warm Croissant: composite task for Reheating Food activity. + + Simulates the task of warming a croissant. + + Steps: + Place the croissant on the pan and turn on the stove to warm the croissant. + + Args: + knob_id (str): The id of the knob who's burner the pan will be placed on. + If "random", a random knob is chosen. + """ + + def __init__(self, knob_id="random", *args, **kwargs): + self.knob_id = knob_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + + # Pick a knob/burner on a stove and a counter close to it + valid_knobs = [k for (k, v) in self.stove.knob_joints.items() if v is not None] + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=FixtureType.STOVE) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the croissant and place it on the pan. Then turn on the stove to warm the croissant." + ep_meta["knob"] = self.knob + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.stove.set_knob_state(mode="off", knob=self.knob, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="croissant", + obj_groups="croissant", + placement=dict( + fixture=self.counter, + size=(0.30, 0.30), + sample_region_kwargs=dict( + ref=self.stove, + ), + pos=("ref", -1.0), + try_to_place_in_container=True, + container_group="plate", + ), + ) + ) + cfgs.append( + dict( + name="pan", + obj_groups="pan", + placement=dict( + fixture=self.stove, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + sample_region_kwargs=dict( + locs=[self.knob], + ), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + size=(0.02, 0.02), + ), + ) + ) + return cfgs + + def _check_success(self): + knobs_state = self.stove.get_knobs_state(env=self) + knob_value = knobs_state[self.knob] + knob_on = 0.35 <= np.abs(knob_value) <= 2 * np.pi - 0.35 + return ( + knob_on + and OU.check_obj_in_receptacle(self, "croissant", "pan") + and OU.gripper_obj_far(self, obj_name="croissant") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/beverage_sorting.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/beverage_sorting.py new file mode 100644 index 0000000000000000000000000000000000000000..4b1ff408e9c49dc1ebbf20a6ab4f7fd9e80f60a6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/beverage_sorting.py @@ -0,0 +1,117 @@ +from robocasa.environments.kitchen.kitchen import * + + +class BeverageSorting(Kitchen): + """ + Beverage Sorting: composite task for Restocking Supplies activity. + + Simulates the task of sorting beverages. + + Steps: + Sort all alcoholic drinks to one cabinet, and non-alcoholic drinks to the + other. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab1 = self.register_fixture_ref( + "cabinet1", dict(id=FixtureType.CABINET_TOP) + ) + self.cab2 = self.register_fixture_ref( + "cabinet2", dict(id=FixtureType.CABINET_TOP, ref=self.cab1) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(0.5, 0.5), ref=self.cab1) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Sort all alcoholic drinks to one cabinet, and non-alcoholic drinks to the other." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab1.set_door_state(min=0.85, max=0.9, env=self, rng=self.rng) + self.cab2.set_door_state(min=0.85, max=0.9, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="alcohol1", + obj_groups="alcohol", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.5, 0.40), + pos=(0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="alcohol2", + obj_groups="alcohol", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.50, 0.40), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="non_alcohol1", + obj_groups="drink", + exclude_obj_groups="alcohol", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.5, 0.40), + pos=(0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="non_alcohol2", + obj_groups="drink", + exclude_obj_groups="alcohol", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.50, 0.40), + pos=(0, -1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + gripper_far = True + for obj_name in ["alcohol1", "alcohol2", "non_alcohol1", "non_alcohol2"]: + gripper_far = gripper_far and OU.gripper_obj_far(self, obj_name=obj_name) + if not gripper_far: + return False + + # Two possible arrangements + for (c1, c2) in [(self.cab1, self.cab2), (self.cab2, self.cab1)]: + if OU.obj_inside_of(self, "alcohol1", c1) and OU.obj_inside_of( + self, "alcohol2", c1 + ): + if OU.obj_inside_of(self, "non_alcohol1", c2) and OU.obj_inside_of( + self, "non_alcohol2", c2 + ): + return True diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_bowls.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_bowls.py new file mode 100644 index 0000000000000000000000000000000000000000..dc32c00f981c186fd00be1e33186ed81cc530585 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_bowls.py @@ -0,0 +1,96 @@ +from robocasa.environments.kitchen.kitchen import * + + +class RestockBowls(Kitchen): + """ + Restock Bowls: composite task for Restocking Supplies activity. + + Simulates the task of restocking bowls. + + Steps: + Restock two bowls from the counter to the cabinet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet to which the bowls are + restocked. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + # use double door cabinet as default to have space for two bowls + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.4)) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + obj_name_1 = self.get_obj_lang("obj1") + obj_name_2 = self.get_obj_lang("obj2") + + ep_meta["lang"] = ( + "Open the cabinet. " + f"Pick the {obj_name_1} and the {obj_name_2} from the counter and place it in the cabinet directly in front. " + "Then close the cabinet." + ) + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj1", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab, top_size=(0.6, 0.4)), + size=(0.50, 0.50), + pos=(-0.5, -1), + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab, top_size=(0.6, 0.4)), + size=(0.50, 0.50), + pos=(0.5, -1), + ), + ) + ) + + return cfgs + + def _check_success(self): + obj1_inside_cab = OU.obj_inside_of(self, "obj1", self.cab) + obj2_inside_cab = OU.obj_inside_of(self, "obj2", self.cab) + + door_state = self.cab.get_door_state(env=self) + door_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + door_closed = False + break + + return obj1_inside_cab and obj2_inside_cab and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_pantry.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_pantry.py new file mode 100644 index 0000000000000000000000000000000000000000..c015e300454d97c9f0bca1fa77277dd4f3fe141e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/restock_pantry.py @@ -0,0 +1,161 @@ +from robocasa.environments.kitchen.kitchen import * + + +class RestockPantry(Kitchen): + """ + Restock Pantry: composite task for Restocking Supplies activity. + + Simulates the task of organizing cans when restocking them. + + Steps: + Pick the cans from the counter and place them on the side of the cabinet + that already has a can. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.DOOR_TOP_HINGE_DOUBLE) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the cans from the counter and place them in their designated side in the cabinet." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=1.0, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj1", + obj_groups="canned_food", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.30), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups="canned_food", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.30), + pos=("ref", -1), + ), + ) + ) + + # randomize the side of the cabinet that already has a can + side = int(self.rng.choice([-1, 1])) + + cfgs.append( + dict( + name="cab_obj1", + obj_groups="canned_food", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.2, 0.30), + pos=(side, -0.3), + ), + ) + ) + + cfgs.append( + dict( + name="cab_obj2", + obj_groups="all", + exclude_obj_groups="canned_food", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.2, 0.30), + pos=(side * -1, 0.3), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + + return cfgs + + def _close_to_cab_cans(self, obj_name, ratio=2): + """ + Check if the object is closer to the cabinet cans than the other object + + Args: + obj_name (str): name of the object + + ratio (float): ratio of the distance between the object and the cabinet cans to the distance + between the object and the other object + + Returns: + bool: True if the object is closer to the cabinet cans than the other object, False otherwise + """ + obj = self.objects[obj_name] + can = self.objects["cab_obj1"] + other_obj = self.objects["cab_obj2"] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]]) + can_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[can.name]]) + other_obj_pos = np.array( + self.sim.data.body_xpos[self.obj_body_id[other_obj.name]] + ) + + can_dist = np.linalg.norm(obj_pos - can_pos) + other_dist = np.linalg.norm(other_obj_pos - obj_pos) + + return can_dist * ratio < other_dist + + def _check_success(self): + obj1_inside_cab = OU.obj_inside_of(self, "obj1", self.cab) + obj2_inside_cab = OU.obj_inside_of(self, "obj2", self.cab) + + cans_close = self._close_to_cab_cans("obj1") and self._close_to_cab_cans("obj2") + + gripper_obj_far = OU.gripper_obj_far(self, "obj1") and OU.gripper_obj_far( + self, "obj2" + ) + + return obj1_inside_cab and obj2_inside_cab and cans_close and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/stocking_breakfast_foods.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/stocking_breakfast_foods.py new file mode 100644 index 0000000000000000000000000000000000000000..cbcc0afaadbf8f8e4489f292343549340033b72b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/restocking_supplies/stocking_breakfast_foods.py @@ -0,0 +1,208 @@ +from robocasa.environments.kitchen.kitchen import * + + +class StockingBreakfastFoods(Kitchen): + """ + Stocking Breakfast Foods: composite task for Restocking Supplies activity. + + Simulates the task of restocking breakfast foods. + + Steps: + Restock two packaged foods from the counter to the cabinet. + + Args: + cab_id1 (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the first cabinet to which the foods + are restocked. + cab_id2 (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the second cabinet to which the foods + are restocked. + """ + + def __init__( + self, + cab_id1=FixtureType.CABINET_TOP, + cab_id2=FixtureType.CABINET_TOP, + *args, + **kwargs, + ): + self.cab_id1 = cab_id1 + self.cab_id2 = cab_id2 + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + if "cab2" in self.fixture_refs: + self.cab1 = self.fixture_refs["cab1"] + self.cab2 = self.fixture_refs["cab2"] + self.counter = self.fixture_refs["counter"] + self.counter2 = self.fixture_refs["counter2"] + else: + self.cab1 = self.register_fixture_ref("cab1", dict(id=self.cab_id1)) + + while True: + # sample until 2 different cabinets are selected + self.cab2 = self.get_fixture(self.cab_id2) + if self.cab2 != self.cab1: + break + + self.fixture_refs["cab2"] = self.cab2 + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab1) + ) + self.counter2 = self.register_fixture_ref( + "counter2", dict(id=FixtureType.COUNTER, ref=self.cab2) + ) + self.init_robot_base_pos = self.cab1 + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + obj_name_1 = self.get_obj_lang("obj1") + obj_name_2 = self.get_obj_lang("obj2") + + # TODO: change for task + ep_meta[ + "lang" + ] = f"Pick the {obj_name_1} and {obj_name_2} from the counter and place them in the cabinets closest to them." + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab1.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + self.cab2.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj1", + obj_groups="packaged_food", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab1, + ), + size=(0.40, 0.20), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups="packaged_food", + graspable=True, + placement=dict( + fixture=self.counter2, + sample_region_kwargs=dict( + ref=self.cab2, + ), + size=(0.40, 0.20), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter1", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab1, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + + # cfgs.append(dict( + # name="distr2_counter1", + # obj_groups="all", + # placement=dict( + # fixture=self.counter, + # sample_region_kwargs=dict( + # ref=self.cab1, + # ), + # size=(1.0, 0.30), + # pos=(0.0, 1.0), + # offset=(0.0, 0.05), + # ), + # )) + + cfgs.append( + dict( + name="distr_cab1", + obj_groups="all", + placement=dict( + fixture=self.cab1, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter2", + obj_groups="all", + placement=dict( + fixture=self.counter2, + sample_region_kwargs=dict( + ref=self.cab2, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + # cfgs.append(dict( + # name="distr2_counter2", + # obj_groups="all", + # placement=dict( + # fixture=self.counter2, + # sample_region_kwargs=dict( + # ref=self.cab2, + # ), + # size=(1.0, 0.30), + # pos=(0.0, 1.0), + # offset=(0.0, 0.05), + # ), + # )) + + cfgs.append( + dict( + name="distr_cab2", + obj_groups="all", + placement=dict( + fixture=self.cab2, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + obj1_inside_cab1 = OU.obj_inside_of(self, "obj1", self.cab1) + obj2_inside_cab2 = OU.obj_inside_of(self, "obj2", self.cab2) + gripper_objs_far = OU.gripper_obj_far(self, "obj1") and OU.gripper_obj_far( + self, "obj2" + ) + + return obj1_inside_cab1 and obj2_inside_cab2 and gripper_objs_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/clean_microwave.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/clean_microwave.py new file mode 100644 index 0000000000000000000000000000000000000000..5744fbc38581126a59e5e44b7139d94bd1460bb0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/clean_microwave.py @@ -0,0 +1,91 @@ +from robocasa.environments.kitchen.kitchen import * + + +class CleanMicrowave(Kitchen): + """ + Clean Microwave: composite task for Sanitize Surface activity. + + Simulates the preparation for cleaning the microwave. + + Steps: + Open the microwave, pick the sponge from the counter and place it in the + microwave. + """ + + # Exclude layout 8 because the microwave is far from counters + EXCLUDE_LAYOUTS = [8] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.microwave = self.register_fixture_ref( + "microwave", + dict(id=FixtureType.MICROWAVE), + ) + self.counter = self.register_fixture_ref( + "counter", + dict(id=FixtureType.COUNTER, ref=self.microwave), + ) + self.distr_counter = self.register_fixture_ref( + "distr_counter", + dict(id=FixtureType.COUNTER, ref=self.microwave), + ) + self.init_robot_base_pos = self.microwave + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.microwave.set_door_state(min=0, max=0, env=self, rng=self.rng) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Open the microwave. Then pick the sponge from the counter and place it in the microwave." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups="sponge", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.distr_counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + + obj_micro_contact = OU.obj_inside_of(self, "obj", self.microwave) + gripper_obj_far = OU.gripper_obj_far(self) + return obj_micro_contact and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/countertop_cleanup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/countertop_cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..cfc4263c4d5d3f809ad4bcb96b0e8d69c4613b8f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/countertop_cleanup.py @@ -0,0 +1,154 @@ +from robocasa.environments.kitchen.kitchen import * + + +class CountertopCleanup(Kitchen): + """ + Countertop Cleanup: composite task for Sanitize Surface activity. + + Simulates the task of cleaning the countertop. + + Steps: + Pick the fruit and vegetable from the counter and place it in the cabinet. + Then, open the drawer and pick the cleaner and sponge from the drawer and + place it on the counter. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=FixtureType.CABINET_TOP)) + self.drawer = self.register_fixture_ref( + "drawer", dict(id=FixtureType.TOP_DRAWER, ref=self.cab) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + + self.init_robot_base_pos = self.drawer + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick the fruit and vegetable from the counter and place them in the cabinet. " + "Then open the drawer and pick the cleaner and sponge from the drawer and place them on the counter." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + # objects appear on different sides + direction = self.rng.choice([1.0, -1.0]) + + cfgs.append( + dict( + name="obj", + obj_groups=("spray", "bar_soap", "soap_dispenser"), + graspable=True, + placement=dict( + fixture=self.drawer, + size=(0.3, 0.3), + pos=(-1.0 * direction, -0.5), + rotation=np.pi / 2, + rotation_axis="x", + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups="sponge", + graspable=True, + placement=dict( + fixture=self.drawer, + size=(0.3, 0.3), + pos=(1.0 * direction, -0.5), + ), + ) + ), + + cfgs.append( + dict( + name="obj3", + obj_groups=("fruit"), + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.60, 0.30), + pos=(0.0, -1.0), + offset=(0.0, 0.10), + ), + ) + ) + + cfgs.append( + dict( + name="obj4", + obj_groups=("vegetable"), + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.60, 0.30), + pos=(0.0, -1.0), + offset=(0.0, 0.10), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self) and OU.gripper_obj_far(self, "obj3") + objs_on_counter = OU.check_obj_fixture_contact( + self, "obj", self.counter + ) and OU.check_obj_fixture_contact(self, "obj2", self.counter) + objs_inside_cab = OU.obj_inside_of(self, "obj3", self.cab) and OU.obj_inside_of( + self, "obj4", self.cab + ) + + return gripper_obj_far and objs_inside_cab and objs_on_counter diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/prep_for_sanitizing.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/prep_for_sanitizing.py new file mode 100644 index 0000000000000000000000000000000000000000..3ae8cfba58acf646a50eeaded099d1d6b2de01ea --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/prep_for_sanitizing.py @@ -0,0 +1,111 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrepForSanitizing(Kitchen): + """ + Prep For Sanitizing: composite task for Sanitize Surface activity. + + Simulates the preparation for sanitizing the surface. + + Steps: + Pick the cleaners from the cabinet and place it on the counter. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the + cleaners are picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + obj1_name = self.get_obj_lang("obj1") + obj2_name = self.get_obj_lang("obj2") + ep_meta[ + "lang" + ] = f"Pick the {obj1_name} and {obj2_name} from the cabinet and place them on the counter." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj1", + obj_groups="cleaner", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(-0.5, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups="cleaner", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0.5, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + obj1_on_counter = OU.check_obj_fixture_contact(self, "obj1", self.counter) + obj2_on_counter = OU.check_obj_fixture_contact(self, "obj2", self.counter) + gripper_obj_far = OU.gripper_obj_far(self, "obj1") and OU.gripper_obj_far( + self, "obj2" + ) + return obj1_on_counter and obj2_on_counter and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/push_utensils_to_sink.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/push_utensils_to_sink.py new file mode 100644 index 0000000000000000000000000000000000000000..4f7cb45920b2101e98e546824f8b930ae1dc154f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/sanitize_surface/push_utensils_to_sink.py @@ -0,0 +1,120 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PushUtensilsToSink(Kitchen): + """ + Push Utensils To Sink: composite task for Sanitize Surface activity. + + Simulates the task of pushing (since utensils are difficult to grasp) + utensils into the sink. + + Steps: + Push the utensils into the sink. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + obj1_name = self.get_obj_lang("utensil1") + obj2_name = self.get_obj_lang("utensil2") + + ep_meta["lang"] = f"Push the {obj1_name} and {obj2_name} into the sink." + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="utensil1", + obj_groups=["utensil"], + graspable=False, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.40), + pos=("ref", -1.0), + offset=(0.07, 0), + ), + ) + ) + + cfgs.append( + dict( + name="utensil2", + obj_groups=["utensil"], + graspable=False, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.sink, loc="left_right"), + size=(1.0, 0.30), + pos=(0.0, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.25, 0.25), + pos=(0.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + utensil1_in_sink = OU.obj_inside_of(self, "utensil1", self.sink) + utensil2_in_sink = OU.obj_inside_of(self, "utensil2", self.sink) + gripper_utensil1_far = OU.gripper_obj_far(self, obj_name="utensil1") + gripper_utensil2_far = OU.gripper_obj_far(self, obj_name="utensil2") + return ( + utensil1_in_sink + and utensil2_in_sink + and gripper_utensil1_far + and gripper_utensil2_far + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/dessert_upgrade.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/dessert_upgrade.py new file mode 100644 index 0000000000000000000000000000000000000000..b53346feed00aadae4f139e2e4a11f02d9b130a2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/dessert_upgrade.py @@ -0,0 +1,88 @@ +from robocasa.environments.kitchen.kitchen import * + + +class DessertUpgrade(Kitchen): + """ + Dessert Upgrade: composite task for Serving Food activity. + + Simulates the task of serving dessert. + + Steps: + Move the dessert items from the plate to the tray. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER_NON_CORNER, size=(1.0, 0.4)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + ep_meta["lang"] = f"Move the dessert items from the plate to the tray." + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="receptacle", + obj_groups="tray", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(1.0, 0.4)), + size=(1, 0.4), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="dessert1", + obj_groups="sweets", + graspable=True, + placement=dict( + fixture=self.counter, + size=(1, 0.4), + pos=(0, -1), + try_to_place_in="plate", + ), + ) + ) + + cfgs.append( + dict( + name="dessert2", + obj_groups="sweets", + graspable=True, + placement=dict( + fixture=self.counter, + size=(1, 0.4), + pos=(0, -1), + try_to_place_in="plate", + ), + ) + ) + + return cfgs + + def _check_success(self): + sweets_on_tray = OU.check_obj_in_receptacle( + self, "dessert1", "receptacle" + ) and OU.check_obj_in_receptacle(self, "dessert2", "receptacle") + + return sweets_on_tray and OU.gripper_obj_far(self, "receptacle") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/pan_transfer.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/pan_transfer.py new file mode 100644 index 0000000000000000000000000000000000000000..3a88ad93dc64b806a2891d3f25c6c34c2607bbd7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/pan_transfer.py @@ -0,0 +1,109 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PanTransfer(Kitchen): + """ + Pan Transfer: composite task for Serving Food activity. + + Simulates the task of transferring vegetables from a pan to a plate. + + Steps: + Pick up the pan and dump the vegetables in it onto the plate. + Then, return the pan to the stove. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.init_robot_base_pos = self.stove + self.dining_table = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=(0.5, 0.5)) + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick up the pan and dump the vegetables in it onto the plate. " + "Then return the pan to the stove." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="vegetable", + obj_groups="vegetable", + placement=dict( + fixture=self.stove, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + try_to_place_in="pan", + container_kwargs=dict( + rotation=[ + (-3 * np.pi / 8, -np.pi / 4), + (np.pi / 4, 3 * np.pi / 8), + ], + ), + ), + ) + ) + # cfgs.append(dict( + # name="vegetable2", + # obj_groups="vegetable", + # placement=dict( + # size=(0.01, 0.01), + # ensure_object_boundary_in_range=False, + # sample_args=dict( + # reference="vegetable_container" + # ) + # ), + # )) + + cfgs.append( + dict( + name="plate", + obj_groups="plate", + graspable=False, + placement=dict( + fixture=self.dining_table, + sample_region_kwargs=dict( + ref=FixtureType.STOOL, + ), + size=(0.50, 0.50), + pos=("ref", 1.0), + ), + ) + ) + cfgs.append( + dict( + name="dstr_dining", + obj_groups="all", + exclude_obj_groups=["plate", "pan", "vegetable"], + placement=dict( + fixture=self.dining_table, + size=(0.30, 0.20), + pos=(0.5, 0.5), + ), + ) + ) + return cfgs + + def _check_success(self): + vegetable_on_plate = OU.check_obj_in_receptacle(self, "vegetable", "plate") + pan_on_stove = OU.check_obj_fixture_contact( + self, "vegetable_container", self.stove + ) + gripper_obj_far = OU.gripper_obj_far( + self, "vegetable_container" + ) and OU.gripper_obj_far(self, "vegetable") + + return vegetable_on_plate and pan_on_stove and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/place_food_in_bowls.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/place_food_in_bowls.py new file mode 100644 index 0000000000000000000000000000000000000000..bd45233ed6a10380dd2d766acced9f3aeb1aa603 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/place_food_in_bowls.py @@ -0,0 +1,152 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PlaceFoodInBowls(Kitchen): + """ + Place Food In Bowls: composite task for Serving Food activity. + + Simulates the task of placing food in bowls. + + Steps: + Pick up two bowls and place them on the counter. + Then, pick up two food items and place them in the bowls. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the bowls are + picked. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + # use double door cabinet as default to have space for two bowls + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + food1 = self.get_obj_lang("food1") + food2 = self.get_obj_lang("food2") + ep_meta["lang"] = ( + "Pick both bowls and place them on the counter. " + f"Then pick the {food1} and place it in one bowl and pick the {food2} and place it in the other bowl." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="receptacle1", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.4, 0.4), + pos=(-1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="receptacle2", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.4, 0.4), + pos=(1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="food1", + obj_groups="food_set1", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.50), + pos=("ref", -0.5), + ), + ) + ) + + cfgs.append( + dict( + name="food2", + obj_groups="food_set1", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.50), + pos=("ref", -0.5), + offset=(0.07, 0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.20), + pos=("ref", 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_food1_far = OU.gripper_obj_far(self, obj_name="food1") + gripper_food2_far = OU.gripper_obj_far(self, obj_name="food2") + food1_in_receptacle1 = OU.check_obj_in_receptacle(self, "food1", "receptacle1") + food1_in_receptacle2 = OU.check_obj_in_receptacle(self, "food1", "receptacle2") + food2_in_receptacle1 = OU.check_obj_in_receptacle(self, "food2", "receptacle1") + food2_in_receptacle2 = OU.check_obj_in_receptacle(self, "food2", "receptacle2") + + receptacles_on_counter = OU.check_obj_fixture_contact( + self, "receptacle1", self.counter + ) and OU.check_obj_fixture_contact(self, "receptacle2", self.counter) + + # make sure food are in different bowls + food_in_bowls = (food1_in_receptacle1 and food2_in_receptacle2) or ( + food1_in_receptacle2 and food2_in_receptacle1 + ) + + return ( + gripper_food1_far + and gripper_food2_far + and food_in_bowls + and receptacles_on_counter + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/prepare_soup_serving.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/prepare_soup_serving.py new file mode 100644 index 0000000000000000000000000000000000000000..3461a685b9c228cac00dc619b1055fb4773a37b1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/prepare_soup_serving.py @@ -0,0 +1,103 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrepareSoupServing(Kitchen): + """ + Prepare Soup Serving: composite task for Serving Food activity. + + Simulates the task of serving soup. + + Steps: + Move the ladle from the cabinet to the pot. Then, close the cabinet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the ladle is + picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.cabinet = self.register_fixture_ref( + "cab", dict(id=self.cab_id, ref=self.stove) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove) + ) + self.init_robot_base_pos = self.cabinet + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Open the cabinet and move the ladle to the pot. Then close the cabinet." + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.cabinet.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="ladle", + obj_groups="ladle", + graspable=True, + placement=dict( + fixture=self.cabinet, + size=(0.50, 0.20), + pos=(0, -1.0), + # rotation is such that the ladle fits in the cabinet + rotation=(np.pi / 2 - np.pi / 8, np.pi / 2 + np.pi / 8), + ), + ) + ) + + cfgs.append( + dict( + name="pot", + obj_groups=("pot"), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + size=(0.02, 0.02), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + ), + ) + ) + + cfgs.append( + dict( + name="bowl1", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.4, 0.4), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + ladle_in_pot = OU.check_obj_in_receptacle(self, "ladle", "pot") + + door_state = self.cabinet.get_door_state(env=self) + door_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + door_closed = False + break + + return ladle_in_pot and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/serve_steak.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/serve_steak.py new file mode 100644 index 0000000000000000000000000000000000000000..f52c38dade56542ae7742b67139f276914bedbb2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/serve_steak.py @@ -0,0 +1,90 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ServeSteak(Kitchen): + """ + Serve Steak: composite task for Serving Food activity. + + Simulates the task of serving steak. + + Steps: + Pick up the pan with the steak in it and place it on the dining table. + Then, place the steak on the plate. + + Restricted to layouts which have a dining table (long counter area with + stools). + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.init_robot_base_pos = self.stove + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick up the pan with the steak in it and place it on the dining table. " + "Then place the steak on the plate." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups="steak", + placement=dict( + fixture=self.stove, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + try_to_place_in="pan", + ), + ) + ) + cfgs.append( + dict( + name="plate", + obj_groups="plate", + graspable=False, + placement=dict( + fixture=self.dining_table, + sample_region_kwargs=dict( + ref=FixtureType.STOOL, + ), + size=(0.50, 0.50), + pos=("ref", 1.0), + ), + ) + ) + cfgs.append( + dict( + name="dstr_dining", + obj_groups=("mug", "cup"), + placement=dict( + fixture=self.dining_table, + size=(0.30, 0.20), + pos=(0.5, 0.5), + ), + ) + ) + return cfgs + + def _check_success(self): + steak_on_plate = OU.check_obj_in_receptacle(self, "obj", "plate") + pan_on_table = OU.check_obj_fixture_contact( + self, "obj_container", self.dining_table + ) + return steak_on_plate and pan_on_table and OU.gripper_obj_far(self) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/wine_serving_prep.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/wine_serving_prep.py new file mode 100644 index 0000000000000000000000000000000000000000..554e65d07403700d59bcbe1e0137cac460cbecf2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/serving_food/wine_serving_prep.py @@ -0,0 +1,141 @@ +from robocasa.environments.kitchen.kitchen import * + + +class WineServingPrep(Kitchen): + """ + Wine Serving Prep: composite task for Serving Food activity. + + Simulates the task of serving wine. + + Steps: + Move the wine and the cup from the cabinet to the dining table. + + Restricted to layouts which have a dining table (long counter area + with stools). + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the wine and + cup are picked. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + alcohol_name = self.get_obj_lang("alcohol") + cup_name = self.get_obj_lang("cup") + decoration_name = self.get_obj_lang("decoration") + ep_meta["lang"] = ( + "Open the cabinet directly in front. " + f"Then move the {alcohol_name} and the {cup_name} to the counter with the {decoration_name} on it." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="alcohol", + obj_groups="alcohol", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(-0.6, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="cup", + obj_groups=["cup", "mug"], + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0.6, -1.0), + ), + ) + ) + + # adding indicator + cfgs.append( + dict( + name="decoration", + obj_groups="decoration", + placement=dict( + fixture=self.dining_table, + size=(0.30, 0.30), + pos=(0.0, 0.0), + ), + ) + ) + + # adding distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups=["vegetable", "fruit", "sweets", "dairy"], + placement=dict( + fixture=self.dining_table, + size=(0.30, 0.30), + pos=(-1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.25, 0.25), + pos=(0.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_alcohol_far = OU.gripper_obj_far(self, obj_name="alcohol") + gripper_cup_far = OU.gripper_obj_far(self, obj_name="cup") + condiment1_on_counter = OU.check_obj_fixture_contact( + self, "alcohol", self.dining_table + ) + condiment2_on_counter = OU.check_obj_fixture_contact( + self, "cup", self.dining_table + ) + + return ( + gripper_alcohol_far + and gripper_cup_far + and condiment1_on_counter + and condiment2_on_counter + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/arrange_bread_basket.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/arrange_bread_basket.py new file mode 100644 index 0000000000000000000000000000000000000000..58fa0a1524c7d83c13ba685c5d146d7d44ccb23b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/arrange_bread_basket.py @@ -0,0 +1,122 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ArrangeBreadBasket(Kitchen): + """ + Arrange Bread Basket: composite task for Setting The Table activity. + + Simulates the task of arranging the bread basket. + + Steps: + Pick the bread from the cabinet and place it in the bowl. Then move the bowl + to the dining counter. + + Restricted to layouts which have a dining table (long counter area with + stools). + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the bread is + picked. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter_small = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + bread_name = self.get_obj_lang("bread") + ep_meta["lang"] = ( + f"Open the cabinet, pick up the {bread_name} from the cabinet and place it in the bowl. " + "Then move the bowl to the dining counter." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="bread", + obj_groups="bread", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.40), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter_small, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.50), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="dstr_dining", + obj_groups="all", + placement=dict( + fixture=self.dining_table, + size=(1, 0.30), + pos=(0, 0), + ), + ) + ) + + cfgs.append( + dict( + name="dstr_dining2", + obj_groups="all", + placement=dict( + fixture=self.dining_table, + size=(1, 0.30), + pos=(0, 0), + offset=(0.05, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, obj_name="bowl") + bread_in_bowl = OU.check_obj_in_receptacle(self, "bread", "bowl") + bowl_on_counter = OU.check_obj_fixture_contact(self, "bowl", self.dining_table) + + return gripper_obj_far and bread_in_bowl and bowl_on_counter diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/beverage_organization.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/beverage_organization.py new file mode 100644 index 0000000000000000000000000000000000000000..a1fdde1f64a8f9b8b5d22051da0135da55bfb5ec --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/beverage_organization.py @@ -0,0 +1,81 @@ +from robocasa.environments.kitchen.kitchen import * + + +class BeverageOrganization(Kitchen): + """ + Beverage Organization: composite task for Setting The Table activity. + + Simulates the task of organizing beverages. + + Steps: + Move the drinks to the dining counter. + + Restricted to layouts which have a dining table (long counter area with + stools). + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + if "counter" in self.fixture_refs: + self.counter = self.fixture_refs["counter"] + self.dining_table = self.fixture_refs["dining_table"] + else: + + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.counter = self.get_fixture(id=FixtureType.COUNTER) + # do not want to sample the dining table or a counter with a builtin sink + # TODO Change later! + while self.counter == self.dining_table or "corner" in self.counter.name: + self.counter = self.get_fixture(FixtureType.COUNTER) + self.fixture_refs["counter"] = self.counter + + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"Move the drinks to the dining counter." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + self.num_bev = self.rng.choice([2, 3, 4]) + for i in range(self.num_bev): + cfgs.append( + dict( + name=f"obj_{i}", + obj_groups="drink", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(0.6, 0.4)), + size=(0.6, 0.4), + pos=(0, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + + drinks_on_dining = all( + [ + OU.check_obj_fixture_contact(self, f"obj_{i}", self.dining_table) + for i in range(self.num_bev) + ] + ) + return drinks_on_dining and OU.gripper_obj_far(self, "obj_0") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/date_night.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/date_night.py new file mode 100644 index 0000000000000000000000000000000000000000..ab3ce49d549ff3e86b944616390f004af18f83ab --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/date_night.py @@ -0,0 +1,96 @@ +from robocasa.environments.kitchen.kitchen import * + + +class DateNight(Kitchen): + """ + Date Night: composite task for Setting The Table activity. + + Simulates the task of setting the table for a date night. + + Steps: + Pick up the decoration and the alcohol from the cabinet and move them to the + dining counter. + + Restricted to layouts which have a dining table (long counter area with + stools). + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the decoration + and alcohol are picked. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + decoration_name = self.get_obj_lang("decoration") + alcohol_name = self.get_obj_lang("alcohol") + ep_meta[ + "lang" + ] = f"Pick up the {decoration_name} and the {alcohol_name} from the cabinet and move them to the dining counter." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="decoration", + obj_groups="decoration", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="alcohol", + obj_groups="alcohol", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(-1.0, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, obj_name="decoration") + alcohol_on_dining_table = OU.check_obj_fixture_contact( + self, "alcohol", self.dining_table + ) + decoration_on_dining_table = OU.check_obj_fixture_contact( + self, "decoration", self.dining_table + ) + + return ( + gripper_obj_far and decoration_on_dining_table and alcohol_on_dining_table + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/seasoning_spice_setup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/seasoning_spice_setup.py new file mode 100644 index 0000000000000000000000000000000000000000..551b75ff9c381242cb92d5d7178bdd461393c656 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/seasoning_spice_setup.py @@ -0,0 +1,126 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SeasoningSpiceSetup(Kitchen): + """ + Seasoning Spice Setup: composite task for Setting The Table activity. + + Simulates the task of setting the table with seasoning and spices. + + Steps: + Move the seasoning and spices from the cabinet directly in front to the + dining counter. + + Restricted to layouts which have a dining table (long counter area with + stools). + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the seasoning + and spices are picked. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.dining_table = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + condiment1_name = self.get_obj_lang("condiment1") + condiment2_name = self.get_obj_lang("condiment2") + ep_meta[ + "lang" + ] = f"Move the {condiment1_name} and {condiment2_name} from the cabinet to the dining counter." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="condiment1", + obj_groups="condiment", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.4, 0.20), + pos=(-0.5, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="condiment2", + obj_groups="condiment", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.4, 0.20), + pos=(0.5, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="dstr_dining", + obj_groups="all", + placement=dict( + fixture=self.dining_table, + size=(1, 0.30), + pos=(0, 0), + ), + ) + ) + + cfgs.append( + dict( + name="dstr_dining2", + obj_groups="all", + placement=dict( + fixture=self.dining_table, + size=(1, 0.30), + pos=(0, 0), + offset=(0.05, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_condiment1_far = OU.gripper_obj_far(self, obj_name="condiment1") + gripper_condiment2_far = OU.gripper_obj_far(self, obj_name="condiment2") + condiment1_on_counter = OU.check_obj_fixture_contact( + self, "condiment1", self.dining_table + ) + condiment2_on_counter = OU.check_obj_fixture_contact( + self, "condiment2", self.dining_table + ) + return ( + gripper_condiment1_far + and gripper_condiment2_far + and condiment1_on_counter + and condiment2_on_counter + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/set_bowls_for_soup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/set_bowls_for_soup.py new file mode 100644 index 0000000000000000000000000000000000000000..e8e9bcd483e9b6ecfcc49c0e4e7bb964a3ef12ab --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/set_bowls_for_soup.py @@ -0,0 +1,129 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SetBowlsForSoup(Kitchen): + """ + Set Bowls For Soup: composite task for Setting The Table activity. + + Simulates the task of setting the table with bowls for soup. + + Steps: + Move the bowls from the cabinet to the plates on the dining table. + + Restricted to layouts which have a dining table (long counter area with + stools). + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the bowls are + picked. + """ + + EXCLUDE_LAYOUTS = [0, 2, 4, 5] + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter_large = self.register_fixture_ref( + "dining_table", + dict(id=FixtureType.COUNTER, ref=FixtureType.STOOL, size=(0.75, 0.2)), + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Move the bowls from the cabinet to the plates on the dining table." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + # set both plates' ref as self.cab to put the plates in a similar area since dining table can be large + cfgs.append( + dict( + name="plate1", + obj_groups="plate", + graspable=False, + placement=dict( + fixture=self.counter_large, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.80, 0.50), + pos=(-0.3, -1.0), + offset=(-0.05, 0), + ), + ) + ) + + cfgs.append( + dict( + name="plate2", + obj_groups="plate", + graspable=False, + placement=dict( + fixture=self.counter_large, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.80, 0.50), + pos=(0.3, -1.0), + offset=(0.05, 0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl1", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.50), + pos=(-1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl2", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.50), + pos=(1.0, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_bowl1_far = OU.gripper_obj_far(self, obj_name="bowl1") + gripper_bowl2_far = OU.gripper_obj_far(self, obj_name="bowl2") + bowl1_on_plate1 = OU.check_obj_in_receptacle(self, "bowl1", "plate1") + bowl1_on_plate2 = OU.check_obj_in_receptacle(self, "bowl1", "plate2") + bowl2_on_plate1 = OU.check_obj_in_receptacle(self, "bowl2", "plate1") + bowl2_on_plate2 = OU.check_obj_in_receptacle(self, "bowl2", "plate2") + + bowls_set = (bowl1_on_plate1 and bowl2_on_plate2) or ( + bowl1_on_plate2 or bowl2_on_plate1 + ) + + return gripper_bowl1_far and gripper_bowl2_far and bowls_set diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/size_sorting.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/size_sorting.py new file mode 100644 index 0000000000000000000000000000000000000000..adedc945368a1f5cb2c55be7a1ec894d4718186a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/setting_the_table/size_sorting.py @@ -0,0 +1,72 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SizeSorting(Kitchen): + + """ + Size Sorting: composite task for Setting The Table activity. + + Simulates the task of stacking objects by size. + + Steps: + Stack the objects from largest to smallest. + """ + + def __init__(self, *args, **kwargs): + + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + # sample a large enough counter for multiple stackable categories + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(1, 0.4)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + stackable_cat = self.get_obj_lang("obj_0") + ep_meta["lang"] = f"Stack the {stackable_cat}s from largest to smallest." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + self.objs = self.rng.choice([2, 3, 4]) + stack_cat = self.rng.choice(["cup", "bowl"]) + scale = 0.8 + # pass in object scale to the config to make the objects smaller and thus stackable + for i in range(self.objs): + cfgs.append( + dict( + name=f"obj_{i}", + obj_groups=stack_cat, + object_scale=scale**i, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(top_size=(0.6, 0.4)), + size=(0.6, 0.4), + pos=(0, -1.0), + offset=(i * 0.1, 0), + ), + ) + ) + + return cfgs + + def _check_success(self): + + objs_stacked_inorder = all( + [ + OU.check_obj_in_receptacle(self, f"obj_{i}", f"obj_{i-1}") + for i in range(1, self.objs) + ] + ) + return objs_stacked_inorder and OU.gripper_obj_far(self, "obj_0") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/bread_and_cheese.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/bread_and_cheese.py new file mode 100644 index 0000000000000000000000000000000000000000..784a9cfc84eb5c7f927c45264103f62e62c5ed09 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/bread_and_cheese.py @@ -0,0 +1,84 @@ +from robocasa.environments.kitchen.kitchen import * + + +class BreadAndCheese(Kitchen): + """ + Bread And Cheese: composite task for Snack Preparation activity. + + Simulates the preparation of a bread and cheese snack. + + Steps: + Pick the bread and cheese, place them on the cutting board. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER_NON_CORNER, size=(0.6, 0.6)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = "Place the bread and cheese on the cutting board." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=("bread"), + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + top_size=(0.6, 0.6), + ), + size=(0.50, 0.30), + pos=(0, -1), + ), + ) + ) + + cfgs.append( + dict( + name="container", + obj_groups="cutting_board", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + top_size=(0.6, 0.6), + ), + size=(0.5, 0.5), + pos=(0.0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="obj2", + obj_groups="cheese", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + top_size=(0.6, 0.6), + ), + size=(0.3, 0.15), + pos=(0.0, -1.0), + offset=(-0.05, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self) + food_on_cutting_board = OU.check_obj_in_receptacle( + self, "obj", "container" + ) and OU.check_obj_in_receptacle(self, "obj2", "container") + return food_on_cutting_board and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/cereal_and_bowl.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/cereal_and_bowl.py new file mode 100644 index 0000000000000000000000000000000000000000..d7cd656ff3521dc7040e0052f171a86168c57dd4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/cereal_and_bowl.py @@ -0,0 +1,120 @@ +from robocasa.environments.kitchen.kitchen import * + + +class CerealAndBowl(Kitchen): + """ + Cereal And Bowl: composite task for Snack Preparation activity. + + Simulates the preparation of a cereal snack. + + Steps: + Pick the cereal and bowl from the cabinet and place them on the counter. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the bowl and + cereal are picked. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + # use double door cabinet as default to have space for the bowl and cereal + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Open the cabinet. Pick the cereal and bowl from the cabinet and place them on the counter. " + "Then close the cabinet." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + # make sure bowl and cereal show up on diff sides randomly + direction = self.rng.choice([1.0, -1.0]) + + cfgs.append( + dict( + name="cereal", + obj_groups="boxed_food", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.30, 0.30), + pos=(1.0 * direction, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.50), + pos=(-1.0 * direction, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + ), + ) + ) + + cfgs.append( + dict( + name="milk", + obj_groups="milk", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.5, 0.30), + pos=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + box_on_counter = OU.check_obj_fixture_contact(self, "cereal", self.counter) + bowl_on_counter = OU.check_obj_fixture_contact(self, "bowl", self.counter) + + door_state = self.cab.get_door_state(env=self) + cabinet_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + cabinet_closed = False + break + return box_on_counter and bowl_on_counter and cabinet_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/make_fruit_bowl.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/make_fruit_bowl.py new file mode 100644 index 0000000000000000000000000000000000000000..0b0333b79f76eec34a13c919c39f357e8c73a181 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/make_fruit_bowl.py @@ -0,0 +1,112 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MakeFruitBowl(Kitchen): + """ + Make Fruit Bowl: composite task for Snack Preparation activity. + + Simulates the preparation of a fruit bowl snack. + + Steps: + Pick the fruit from the cabinet and place them in the bowl. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the fruit are + picked. + """ + + def __init__(self, cab_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.4)) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + fruit1_name = self.get_obj_lang("fruit1") + fruit2_name = self.get_obj_lang("fruit2") + ep_meta["lang"] = ( + "Open the cabinet. " + f"Pick the {fruit1_name} and {fruit2_name} from the cabinet and place them into the bowl. " + "Then close the cabinet." + ) + + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.cab, top_size=(0.6, 0.4)), + size=(1, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="fruit1", + obj_groups="fruit", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(-0.5, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="fruit2", + obj_groups="fruit", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0.5, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + fruit1_in_bowl = OU.check_obj_in_receptacle(self, "fruit1", "bowl") + fruit2_in_bowl = OU.check_obj_in_receptacle(self, "fruit2", "bowl") + + door_state = self.cab.get_door_state(env=self) + + door_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + door_closed = False + break + + return fruit1_in_bowl and fruit2_in_bowl and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/veggie_dip_prep.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/veggie_dip_prep.py new file mode 100644 index 0000000000000000000000000000000000000000..40235b3e6fcb74a8c75dc5a0a9621169fce6f916 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/veggie_dip_prep.py @@ -0,0 +1,104 @@ +from robocasa.environments.kitchen.kitchen import * + + +class VeggieDipPrep(Kitchen): + """ + Veggie Dip Prep: composite task for Snack Preparation activity. + + Simulates the preparation of a vegetable dip snack. + + Steps: + Place the two vegetables and a bowl onto the tray for setting up a vegetable + dip station. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, size=(1, 0.6)) + ) + self.init_robot_base_pos = self.counter + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Place the two vegetables and a bowl onto the tray for setting up a vegetable dip station." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + # Tray in the center of the counter + cfgs.append( + dict( + name="tray", + obj_groups="tray", + placement=dict( + fixture=self.counter, + size=(0.3, 0.6), + pos=(0, -1), + ), + ) + ) + + # Two "dippable" vegetables to the left of tray + cfgs.append( + dict( + name="cucumber", + obj_groups="cucumber", + placement=dict( + fixture=self.counter, + size=(0.8, 0.6), + pos=(0, -1.0), + ), + ) + ) + cfgs.append( + dict( + name="carrot", + obj_groups="carrot", + placement=dict( + fixture=self.counter, + size=(0.8, 0.6), + pos=(0, -1.0), + ), + ) + ) + + # Bowl to the right of tray + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter, + size=(0.8, 0.6), + pos=(0, -1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + gripper_far = ( + OU.gripper_obj_far(self, "bowl") + and OU.gripper_obj_far(self, "cucumber") + and OU.gripper_obj_far(self, "carrot") + ) + vegetables_in_tray = OU.check_obj_in_receptacle( + self, "cucumber", "tray" + ) and OU.check_obj_in_receptacle(self, "carrot", "tray") + bowl_in_tray = OU.check_obj_in_receptacle(self, "bowl", "tray") + + return gripper_far and vegetables_in_tray and bowl_in_tray diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/yogurt_delight_prep.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/yogurt_delight_prep.py new file mode 100644 index 0000000000000000000000000000000000000000..6fa963ca41dc08ea07ee1f56c923a57b0ee7d609 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/snack_preparation/yogurt_delight_prep.py @@ -0,0 +1,89 @@ +from robocasa.environments.kitchen.kitchen import * + + +class YogurtDelightPrep(Kitchen): + """ + Yogurt Delight Prep: composite task for Snack Preparation activity. + + Simulates the preparation of a yogurt delight snack. + + Steps: + Place the yogurt and fruit onto the counter. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + # want space for all the objects + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.DOOR_TOP_HINGE_DOUBLE) + ) + + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = "Place the yogurt and fruit onto the counter." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="yogurt", + obj_groups="yogurt", + placement=dict( + fixture=self.cab, + size=(0.5, 0.3), + pos=(0, -1), + ), + ) + ) + + self.num_fruits = self.rng.choice([1, 2, 3]) + for i in range(self.num_fruits): + cfgs.append( + dict( + name=f"fruit_{i}", + obj_groups="fruit", + placement=dict( + fixture=self.cab, + size=(0.5, 0.2), + pos=(0, -1), + offset=(0.05 * i, 0), + ), + ) + ) + + return cfgs + + def _check_success(self): + items_on_counter = all( + [ + OU.check_obj_fixture_contact(self, f"fruit_{i}", self.counter) + for i in range(self.num_fruits) + ] + ) + items_on_counter = items_on_counter and OU.check_obj_fixture_contact( + self, "yogurt", self.counter + ) + + objs_far = all( + [OU.gripper_obj_far(self, f"fruit_{i}") for i in range(self.num_fruits)] + ) + objs_far = objs_far and OU.gripper_obj_far(self, "yogurt") + + return items_on_counter and objs_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/multistep_steaming.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/multistep_steaming.py new file mode 100644 index 0000000000000000000000000000000000000000..e16012a8662664c53f0eb889e762a451f64e26d5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/multistep_steaming.py @@ -0,0 +1,161 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MultistepSteaming(Kitchen): + """ + Multistep Steaming: composite task for Steaming Food activity. + + Simulates the task of steaming a vegetable. + + Steps: + Turn on the sink. Then move the vegetable from the counter to the sink. + Turn of the sink. Move the vegetable from the sink to the pot next to the + stove. Finally, move the pot to the stove burner. + + Args: + knob_id (str): The id of the knob who's burner the pot will be placed on. + """ + + def __init__(self, knob_id="random", *args, **kwargs): + self.knob_id = knob_id + # Flags to keep track of the task progress + self.water_was_turned_on = False + self.vegetable_was_in_sink = False + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.stove_counter = self.register_fixture_ref( + "stove_counter", dict(id=FixtureType.COUNTER, ref=self.stove) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + vegetable_name = self.get_obj_lang("vegetable1") + ep_meta["lang"] = ( + "Turn on the sink faucet. " + f"Then move the {vegetable_name} from the counter to the sink. " + "Turn off the sink. Move the vegetable from the sink to the pot next to the stove. " + f"Finally, move the pot to the {self.knob.replace('_', ' ')} burner." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + + valid_knobs = self.stove.get_knobs_state(env=self).keys() + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + + self.stove.set_knob_state(mode="off", knob=self.knob, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="pot", + obj_groups="pot", + placement=dict( + fixture=self.stove_counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.05, 0.05), + pos=("ref", -0.7), + rotation=np.pi / 2, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="vegetable1", + obj_groups="vegetable", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.sink, loc="left_right"), + size=(0.5, 0.5), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="obj", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.sink, loc="left_right"), + size=(0.4, 0.4), + pos=(-1.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_obj_location_on_stove(self, obj_name, threshold=0.08): + """ + Check if the object is on any of the burners of the stove + Returns the location of the burner if the object is on it. Otherwise, returns None + """ + + obj = self.objects[obj_name] + obj_pos = np.array(self.sim.data.body_xpos[self.obj_body_id[obj.name]])[0:2] + obj_on_stove = OU.check_obj_fixture_contact(self, obj_name, self.stove) + + if obj_on_stove: + for location, site in self.stove.burner_sites.items(): + if site is not None: + burner_pos = np.array( + self.sim.data.get_site_xpos(site.get("name")) + )[0:2] + dist = np.linalg.norm(burner_pos - obj_pos) + + obj_on_site = dist < threshold + if obj_on_site: + return location + + return None + + def _check_success(self): + + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + + if water_on: + self.water_was_turned_on = True + + pot_loc = self._check_obj_location_on_stove(obj_name="pot") + pot_on_burner = pot_loc == self.knob + + vegetable_in_sink = OU.obj_inside_of(self, "vegetable1", self.sink) + + # make sure the vegetable was in the sink when the water was turned + if vegetable_in_sink and water_on: + self.vegetable_was_in_sink = True + + vegetable_in_pot = OU.check_obj_in_receptacle(self, "vegetable1", "pot") + + return ( + self.water_was_turned_on + and self.vegetable_was_in_sink + and (not water_on) + and pot_on_burner + and vegetable_in_pot + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/steam_in_microwave.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/steam_in_microwave.py new file mode 100644 index 0000000000000000000000000000000000000000..b6dee7288119d6b715a6aeb8ad3efb0b37ffad67 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/steam_in_microwave.py @@ -0,0 +1,127 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SteamInMicrowave(Kitchen): + """ + Steam In Microwave: composite task for Steaming Food activity. + + Simulates the task of steaming a vegetable in a microwave. + + Steps: + Pick the vegetable from the sink and place it in the bowl. Then pick the + bowl and place it in the microwave. Then close the microwave door and press + the start button. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.microwave = self.register_fixture_ref( + "microwave", dict(id=FixtureType.MICROWAVE) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + vegetable_name = self.get_obj_lang("vegetable") + ep_meta["lang"] = ( + f"Pick the {vegetable_name} from the sink and place it in the bowl. " + "Then pick the bowl and place it in the microwave. " + "Then close the microwave door and press the start button." + ) + + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + self.microwave.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.35, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="vegetable", + obj_groups="vegetable", + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + size=(0.3, 0.2), + pos=(0.0, 1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter_0", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.50, 0.50), + pos=("ref", -1.0), + offset=(0.0, 0.40), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter_1", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.sink, loc="left_right"), + size=(0.50, 0.50), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + vegetable_in_bowl = OU.check_obj_in_receptacle(self, "vegetable", "bowl") + bowl_in_microwave = OU.obj_inside_of(self, "bowl", self.microwave) + + door_state = self.microwave.get_door_state(env=self) + door_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + door_closed = False + break + + button_pressed = self.microwave.get_state()["turned_on"] + + return ( + vegetable_in_bowl and bowl_in_microwave and door_closed and button_pressed + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/steam_vegetables.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/steam_vegetables.py new file mode 100644 index 0000000000000000000000000000000000000000..eb4697b4493a496a850945d35b6eda14fae737fa --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/steaming_food/steam_vegetables.py @@ -0,0 +1,132 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SteamVegetables(Kitchen): + """ + Steam Vegetables: composite task for Steaming Food activity. + + Simulates the task of steaming vegetables based on their cooking time. + + Steps: + Place vegetables into the pot based on the amount of time it would take to + steam each. e.g. potatoes and carrots would take the longest. Then, turn + off the burner beneath the pot. + + Args: + knob_id (str): The id of the knob who's burner the pot will be placed on. + If "random", a random knob is chosen. + """ + + def __init__(self, knob_id="random", *args, **kwargs): + self.knob_id = knob_id + # Used to see if the vegetables were placed in the wrong order. If so, task always fails. + self.task_failed = False + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + + # Pick a knob/burner on a stove and a counter close to it + valid_knobs = [k for (k, v) in self.stove.knob_joints.items() if v is not None] + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=FixtureType.STOVE) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Place vegetables into the pot based on the amount of time it would take to steam each, " + "e.g. potatoes and carrots would take the longest. " + "Then turn off the burner beneath the pot." + ) + ep_meta["knob"] = self.knob + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.stove.set_knob_state(mode="on", knob=self.knob, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="vegetable_hard", + obj_groups=["potato", "carrot"], + placement=dict( + fixture=self.counter, + size=(0.30, 0.50), + sample_region_kwargs=dict( + ref=self.stove, + ), + pos=("ref", -1.0), + ), + ) + ) + cfgs.append( + dict( + name="vegetable_easy", + obj_groups="vegetable", + exclude_obj_groups=["potato", "carrot"], + placement=dict( + fixture=self.counter, + size=(0.30, 0.50), + sample_region_kwargs=dict( + ref=self.stove, + ), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="pot", + obj_groups="pot", + placement=dict( + fixture=self.stove, + # ensure_object_boundary_in_range=False because the pans handle is a part of the + # bounding box making it hard to place it if set to True + ensure_object_boundary_in_range=False, + sample_region_kwargs=dict( + locs=[self.knob], + ), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + size=(0.02, 0.02), + ), + ) + ) + return cfgs + + def _check_success(self): + if self.task_failed: + return False + + # Must place vegetables into pot in sequence + hard_in_pot = OU.check_obj_in_receptacle(self, "vegetable_hard", "pot") + easy_in_pot = OU.check_obj_in_receptacle(self, "vegetable_easy", "pot") + if easy_in_pot and not hard_in_pot: + self.task_failed = True + return False + vegetables_in_pot = hard_in_pot and easy_in_pot + + knobs_state = self.stove.get_knobs_state(env=self) + knob_value = knobs_state[self.knob] + knob_off = not (0.35 <= np.abs(knob_value) <= 2 * np.pi - 0.35) + + gripper_far = ( + OU.gripper_obj_far(self, "vegetable_hard") + and OU.gripper_obj_far(self, "vegetable_easy") + and OU.gripper_obj_far(self, "pot") + ) + pot_on_stove = pan_on_stove = OU.check_obj_fixture_contact( + self, "pot", self.stove + ) + + return knob_off and gripper_far and pot_on_stove and vegetables_in_pot diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/drawer_utensil_sort.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/drawer_utensil_sort.py new file mode 100644 index 0000000000000000000000000000000000000000..7264c3e18374b86a2cae889a4f53be99c1f920c6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/drawer_utensil_sort.py @@ -0,0 +1,96 @@ +from robocasa.environments.kitchen.kitchen import * +from robocasa.environments.kitchen.single_stage.kitchen_drawer import ManipulateDrawer + +# Inherit from ManipulateDrawer class since it involved opening drawers +class DrawerUtensilSort(ManipulateDrawer): + """ + Drawer Utensil Sort: composite task for Tidying Cabinets And Drawers activity. + + Simulates the task of placing utensils in the drawer. + + Steps: + Open the drawer and push the utensils inside it. + + Args: + drawer_id (int): Enum which serves as a unique identifier for different + drawer types. Used to choose the drawer in which the utensils are + placed. TOP_DRAWER specifies the uppermost drawer. + """ + + def __init__(self, drawer_id=FixtureType.TOP_DRAWER, *args, **kwargs): + super().__init__(behavior="open", drawer_id=drawer_id, *args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.drawer, size=(0.2, 0.2)) + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = f"{self.behavior} the {self.drawer_side} drawer and push the utensils inside it." + ep_meta["lang"] = ep_meta["lang"][0].capitalize() + ep_meta["lang"][1:] + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="utensil1", + obj_groups="utensil", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.drawer, + ), + size=(0.3, 0.4), + pos=("ref", -1.0), + offset=(-0.05, 0.0), + ), + ) + ) + + cfgs.append( + dict( + name="utensil2", + obj_groups="utensil", + graspable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.drawer, + ), + size=(0.3, 0.4), + pos=("ref", -1.0), + offset=(0.05, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + + # need to make sure utensils not on the counter. Since the top drawer (when closed) is so close to the counter, + # its bounding box may overlap with the top of the counter. So when the utensil is on the counter it may be falsely identified as inside the drawer + utensil1_inside_drawer = OU.obj_inside_of( + self, "utensil1", self.drawer + ) and not OU.check_obj_fixture_contact(self, "utensil1", self.counter) + utensil2_inside_drawer = OU.obj_inside_of( + self, "utensil2", self.drawer + ) and not OU.check_obj_fixture_contact(self, "utensil2", self.counter) + + gripper_obj_far = OU.gripper_obj_far( + self, obj_name="utensil1" + ) and OU.gripper_obj_far(self, obj_name="utensil2") + return utensil1_inside_drawer and utensil2_inside_drawer and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/organize_cleaning_supplies.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/organize_cleaning_supplies.py new file mode 100644 index 0000000000000000000000000000000000000000..bddf1fe31f1de59fb3d458301b34832de2050324 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/organize_cleaning_supplies.py @@ -0,0 +1,129 @@ +from robocasa.environments.kitchen.kitchen import * + + +class OrganizeCleaningSupplies(Kitchen): + """ + Organize Cleaning Supplies: composite task for Tidying Cabinets And Drawers activity. + + Simulates the task of preparing to clean the sink. + + Steps: + Open the cabinet. Pick the cleaner and place it next to the sink. + Then close the cabinet. + + Args: + cab_id (str): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which the cleaner is + picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id, ref=self.sink)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + + cleaner_name = self.get_obj_lang("cleaner") + + ep_meta["lang"] = ( + "Open the cabinet. " + f"Pick the {cleaner_name} and place it next to the sink. " + "Then close the cabinet." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="cleaner", + obj_groups="cleaner", + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter_1", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.30), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter_2", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _obj_sink_dist(self, obj_name): + """ + Returns the distance of the object from the sink + """ + sink_points = self.sink.get_ext_sites(all_points=True, relative=False) + obj_point = self.sim.data.body_xpos[self.obj_body_id[obj_name]] + + all_dists = [np.linalg.norm(p1 - obj_point) for p1 in sink_points] + return np.min(all_dists) + + def _check_success(self): + + # must make sure the cleaner is on the counter and close to the sink + gripper_obj_far = OU.gripper_obj_far(self, obj_name="cleaner") + obj_on_counter = OU.check_obj_fixture_contact(self, "cleaner", self.counter) + + obj_name = self.objects["cleaner"].name + obj_sink_close = self._obj_sink_dist(obj_name) < 0.35 + + door_state = self.cab.get_door_state(env=self) + + door_closed = True + for joint_p in door_state.values(): + if joint_p > 0.05: + door_closed = False + break + + return gripper_obj_far and obj_on_counter and door_closed and obj_sink_close diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/pantry_mishap.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/pantry_mishap.py new file mode 100644 index 0000000000000000000000000000000000000000..57180eba42bbd68de236ff7195f1450e3340cfad --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/pantry_mishap.py @@ -0,0 +1,88 @@ +from robocasa.environments.kitchen.kitchen import * +from robocasa.environments.kitchen.single_stage.kitchen_drawer import * + +# inherit from ManipulateDrawer class to start off the task with the drawer open +class PantryMishap(ManipulateDrawer): + """ + Pantry Mishap: composite task for Tidying Cabinets And Drawers activity. + + Simulates the task of organizing the pantry after a mishap from the incorrect + placement of items in the cabinet. + + Steps: + Open the cabinet. Pick the vegetable and place it on the counter. Pick the + canned food and place it in the drawer. Close the cabinet. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.drawer) + ) + + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.drawer) + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + vegetable = self.get_obj_lang("vegetable") + ep_meta["lang"] = ( + f"Place the {vegetable} on the counter and the canned food in the drawer. " + "Close the cabinet." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.9, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="vegetable", + obj_groups="vegetable", + placement=dict( + fixture=self.cab, + size=(0.5, 0.2), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="canned_food", + obj_groups="canned_food", + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + vegetable_on_counter = OU.check_obj_fixture_contact( + self, "vegetable", self.counter + ) + canned_food_in_drawer = OU.obj_inside_of(self, "canned_food", self.drawer) + + door_state = self.cab.get_door_state(env=self) + + door_closed = True + for joint_p in door_state.values(): + + if joint_p > 0.05: + door_closed = False + break + + return vegetable_on_counter and canned_food_in_drawer and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/shaker_shuffle.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/shaker_shuffle.py new file mode 100644 index 0000000000000000000000000000000000000000..db7fad2f9b23b84dcde35ff9560b9020b6007dcc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/shaker_shuffle.py @@ -0,0 +1,95 @@ +from robocasa.environments.kitchen.kitchen import * +from robocasa.environments.kitchen.single_stage.kitchen_drawer import * + +# Inherit from ManipulateDrawer class since the class starts off with the drawer open +class ShakerShuffle(ManipulateDrawer): + """ + Shaker Shuffle: composite task for Tidying Cabinets And Drawers activity. + + Simulates the task of reorganizing the pantry by only placing the shakers in + the drawer. + + Steps: + Open the cabinet. Place the shakers in the drawer. Close the cabinet. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.drawer) + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick and place the shaker into the drawer. Then close the cabinet." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.9, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="shaker1", + obj_groups="shaker", + placement=dict( + fixture=self.cab, + size=(0.5, 0.2), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="shaker2", + obj_groups="shaker", + placement=dict( + fixture=self.cab, + size=(0.5, 0.2), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="condiment", + obj_groups="condiment_bottle", + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + return cfgs + + def _check_success(self): + # make sure only the shakers were placed in the drawer! + shaker_in_drawer = ( + OU.obj_inside_of(self, "shaker1", self.drawer) + and OU.obj_inside_of(self, "shaker2", self.drawer) + and not OU.obj_inside_of(self, "condiment", self.drawer) + ) + + door_state = self.cab.get_door_state(env=self) + + door_closed = True + for joint_p in door_state.values(): + + if joint_p > 0.05: + door_closed = False + break + + return shaker_in_drawer and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/snack_sorting.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/snack_sorting.py new file mode 100644 index 0000000000000000000000000000000000000000..4a8d65d21a823c324a72628c2422365a6a0b7c54 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/tidying_cabinets_and_drawers/snack_sorting.py @@ -0,0 +1,86 @@ +from robocasa.environments.kitchen.kitchen import * +from robocasa.environments.kitchen.single_stage.kitchen_drawer import * + +# Inherit from ManipulateDrawer class since drawer is open to start +class SnackSorting(ManipulateDrawer): + """ + Snack Sorting: composite task for Tidying Cabinets And Drawers activity. + + Simulates the task of placing snacks in the bowl. + + Steps: + Place the bar in the bowl and close the drawer. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.drawer) + ) + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"Place the bar in the bowl and close the drawer." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="bar", + obj_groups="bar", + graspable=True, + # have to make sure that the sampled object can fit inside the drawer hence the max_size being 0.1 in the z axis + max_size=(None, None, 0.10), + placement=dict( + fixture=self.drawer, + size=(0.30, 0.30), + # put object towards the front of the drawer + pos=(None, -0.75), + # offset to make sure the object is correctly placed since the drawer will be open to start + offset=(0, -self.drawer.size[1] * 0.55), + ), + ) + ) + + cfgs.append( + dict( + name="dist", + obj_groups="all", + max_size=(None, None, 0.10), + placement=dict( + fixture=self.drawer, + size=(0.30, 0.30), + pos=(None, 1), + # offset to make sure the object is correctly placed since the drawer will be open to start + offset=(0, -self.drawer.size[1] * 0.55), + ), + ) + ) + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.drawer), + size=(0.60, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs + return cfgs + + def _check_success(self): + bars_in_bowl = OU.check_obj_in_receptacle(self, "bar", "bowl") + + # user super class to make sure that the drawer is closed + door_closed = super()._check_success() + + return bars_in_bowl and door_closed diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_dishes.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_dishes.py new file mode 100644 index 0000000000000000000000000000000000000000..1e2f46aa4a5b510ad84a69f5673e8fb2a904d930 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_dishes.py @@ -0,0 +1,99 @@ +from robocasa.environments.kitchen.kitchen import * + + +class DryDishes(Kitchen): + """ + Dry Dishes: composite task for Washing Dishes activity. + + Simulates the task of drying dishes. + + Steps: + Pick the cup and bowl from the sink and place them on the counter for drying. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", + dict( + id=FixtureType.COUNTER, + ref=self.sink, + ), + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the cup and bowl from the sink and place them on the counter for drying." + return ep_meta + + def _get_obj_cfgs(self): + cfgs = [] + + # sample a random back corner for the cup to be placed on + cup_pos = self.rng.choice([(1.0, 1.0), (-1.0, 1.0)]) + cfgs.append( + dict( + name="obj1", + obj_groups=("cup"), + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + # hard code the cup to be in corners so that the cup and bowl fit in the sink + size=(0.1, 0.1), + # offset=(0.25, 0.25) + pos=cup_pos, + ), + ) + ) + cfgs.append( + dict( + name="obj2", + obj_groups=("bowl"), + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + # place the bowl in the middle of the sink and turn of ensure_object_boundary_in_range + # otherwise it becomes difficult to initialize since the bowl is so big + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.30), + ), + ) + ) + + return cfgs + + def _check_success(self): + objs_on_counter = self.check_contact( + self.objects["obj1"], self.counter + ) and self.check_contact(self.objects["obj2"], self.counter) + gripper_objs_far = OU.gripper_obj_far(self, "obj1") and OU.gripper_obj_far( + self, "obj2" + ) + return objs_on_counter and gripper_objs_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_drinkware.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_drinkware.py new file mode 100644 index 0000000000000000000000000000000000000000..eba0c09acb4feb76d26a7e2f193b518ea8d97a96 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/dry_drinkware.py @@ -0,0 +1,134 @@ +import math + +from robocasa.environments.kitchen.kitchen import * + + +class DryDrinkware(Kitchen): + """ + Dry Drinkware: composite task for Washing Dishes activity. + + Simulates the task of drying drinkware. + + Steps: + Pick the mug from the counter and place it upside down in the open cabinet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet in which the mug is placed. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab, size=(0.6, 0.5)) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "A wet mug is on the counter and needs to be dried. " + "Pick it up and place it upside down in the open cabinet." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.9, max=1, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + x_positions = [-1, 1] + self.rng.shuffle(x_positions) + + cfgs.append( + dict( + name="mug", + obj_groups="mug", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.3, 0.3), + pos=(x_positions[0], -1.0), + ), + ) + ) + # cfgs.append(dict( + # name="cup", + # obj_groups="cup", + # placement=dict( + # fixture=self.counter, + # sample_region_kwargs=dict( + # ref=self.cab, + # ), + # size=(0.3, 0.3), + # pos=(x_positions[1], -1.0) + # ), + # )) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.20), + pos=(0.0, 1.0), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def euler_from_quaternion(self, x, y, z, w): + t0 = +2.0 * (w * x + y * z) + t1 = +1.0 - 2.0 * (x * x + y * y) + roll_x = math.atan2(t0, t1) + + t2 = +2.0 * (w * y - z * x) + t2 = +1.0 if t2 > +1.0 else t2 + t2 = -1.0 if t2 < -1.0 else t2 + pitch_y = math.asin(t2) + + t3 = +2.0 * (w * z + x * y) + t4 = +1.0 - 2.0 * (y * y + z * z) + yaw_z = math.atan2(t3, t4) + + return roll_x, pitch_y, yaw_z + + def _check_success(self): + mug_rot = self.sim.data.xquat[self.obj_body_id["mug"]] + # make sure the mug is placed upside down + mug_rot = self.euler_from_quaternion(*mug_rot) + return ( + OU.gripper_obj_far(self, obj_name="mug") + and np.abs(mug_rot[2]) > 3 + and OU.check_obj_fixture_contact(self, "mug", self.cab) + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/pre_soak_pan.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/pre_soak_pan.py new file mode 100644 index 0000000000000000000000000000000000000000..ab15a82cc9e56f1b7ff3161be483cec79f7834ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/pre_soak_pan.py @@ -0,0 +1,85 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PreSoakPan(Kitchen): + """ + Pre Soak Pan: composite task for Washing Dishes activity. + + Simulates the task of pre-soaking a pan. + + Steps: + Pick the pan and sponge and place them into the sink. Then turn on the sink. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.6, 0.4)) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = "Pick the pan and sponge and place them into the sink. Then turn on the water." + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + cfgs.append( + dict( + name="obj1", + obj_groups=("pan"), + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + # make sure sampled counter region is large enough to place the pan + top_size=(0.6, 0.4), + ), + size=(0.35, 0.55), + pos=("ref", -1.0), + ), + # make sure the sampled pan would fit in the sink basin + max_size=(0.35, 0.45, None), + ) + ) + + cfgs.append( + dict( + name="obj2", + obj_groups=("sponge"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict(ref=self.sink, loc="left_right"), + size=(0.3, 0.3), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + pan_in_sink = OU.obj_inside_of(self, "obj1", self.sink) + sponge_in_sink = OU.obj_inside_of(self, "obj2", self.sink) + return ( + water_on + and pan_in_sink + and sponge_in_sink + and OU.gripper_obj_far(self, "obj1") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/sorting_cleanup.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/sorting_cleanup.py new file mode 100644 index 0000000000000000000000000000000000000000..16fd0ada2739b975240f0d30b326ed20d6eef5e4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/sorting_cleanup.py @@ -0,0 +1,128 @@ +from robocasa.environments.kitchen.kitchen import * + + +class SortingCleanup(Kitchen): + """ + Sorting Cleanup: composite task for Washing Dishes activity. + + Simulates the task of sorting and cleaning dishes. + + Steps: + Pick the mug and place it in the sink. Pick the bowl and place it in the + cabinet and then close the cabinet. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.cab = self.register_fixture_ref( + "cab", dict(id=FixtureType.CABINET_TOP, ref=self.sink) + ) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.5, 0.5)) + ) + + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick the mug and place it in the sink. " + "Pick the bowl and place it in the cabinet and then close the cabinet." + ) + return ep_meta + + def _reset_internal(self): + super()._reset_internal() + # not fully open since it may come in contact with eef + self.cab.set_door_state(min=0.5, max=0.6, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="mug", + obj_groups=("mug"), + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.4, 0.4), + pos=("ref", -1), + ), + ) + ) + cfgs.append( + dict( + name="bowl", + obj_groups=("bowl"), + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + # large enough region to sample the bowl + top_size=(0.5, 0.5), + ), + size=(0.7, 0.7), + pos=("ref", -1), + ), + ) + ) + + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=(0, 1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + mug_in_sink = OU.obj_inside_of(self, "mug", self.sink) + bowl_in_cab = OU.obj_inside_of(self, "bowl", self.cab) + closed = True + door_state = self.cab.get_door_state(env=self) + + for joint_p in door_state.values(): + if joint_p > 0.05: + closed = False + break + + return ( + mug_in_sink and bowl_in_cab and closed and OU.gripper_obj_far(self, "mug") + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/stack_bowls.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/stack_bowls.py new file mode 100644 index 0000000000000000000000000000000000000000..8a55d243dfa8e375f872f9dce388f0653e3c0875 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_dishes/stack_bowls.py @@ -0,0 +1,98 @@ +from robocasa.environments.kitchen.kitchen import * + + +class StackBowlsInSink(Kitchen): + """ + Stack Bowls: composite task for Washing Dishes activity. + + Simulates the task of stacking bowls in the sink. + + Steps: + Stack the bowls in the sink. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"Stack the bowls in the sink." + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="receptacle1", + obj_groups="bowl", + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.50, 0.65), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="receptacle2", + obj_groups="bowl", + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.50, 0.65), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + receptacle1_in_sink = OU.obj_inside_of(self, "receptacle1", self.sink) + receptacle2_in_sink = OU.obj_inside_of(self, "receptacle2", self.sink) + + receptacle2_in_receptacle1 = OU.check_obj_in_receptacle( + self, "receptacle2", "receptacle1" + ) + receptacle1_in_receptacle2 = OU.check_obj_in_receptacle( + self, "receptacle1", "receptacle2" + ) + + gripper_receptacle1_far = OU.gripper_obj_far(self, obj_name="receptacle1") + gripper_receptacle2_far = OU.gripper_obj_far(self, obj_name="receptacle2") + + return ( + receptacle1_in_sink + and receptacle2_in_sink + and (receptacle2_in_receptacle1 or receptacle1_in_receptacle2) + and gripper_receptacle1_far + and gripper_receptacle2_far + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/afterwash_sorting.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/afterwash_sorting.py new file mode 100644 index 0000000000000000000000000000000000000000..353218f5612974e8e8dfc1f15e082abd18a2dffd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/afterwash_sorting.py @@ -0,0 +1,149 @@ +import random + +from robocasa.environments.kitchen.kitchen import * +from robocasa.models.objects.kitchen_objects import get_cats_by_type + + +class AfterwashSorting(Kitchen): + """ + Afterwash Sorting: composite task for Washing Fruits And Vegetables activity. + + Simulates the task of sorting washed fruits and vegetables. + + Steps: + Pick the foods of the same kind from the sink and place them in one bowl. + Place the food of a different kind in the other bowl. Then, turn off the + sink. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + food12_name = self.get_obj_lang("food1") + food3_name = self.get_obj_lang("food3") + ep_meta["lang"] = ( + f"Pick the {food12_name}s from the sink and place them in one bowl. " + f"Place the {food3_name} in the other bowl. Then turn off the sink faucet." + ) + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.sink.set_handle_state(mode="on", env=self, rng=self.rng) + + def _get_obj_cfgs(self): + + food_items = get_cats_by_type( + types=["vegetable", "fruit"], obj_registries=self.obj_registries + ) + food1, food2 = self.rng.choice(food_items, size=2, replace=False) + + cfgs = [] + + cfgs.append( + dict( + name="food1", + obj_groups=food1, + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + size=(0.2, 0.2), + pos=(-1.0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="food2", + obj_groups=food1, + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + size=(0.2, 0.2), + pos=(1.0, 1.0), + ), + ) + ) + + cfgs.append( + dict( + name="food3", + obj_groups=food2, + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + size=(0.2, 0.2), + pos=(-1.0, 1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl1", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.50, 0.50), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl2", + obj_groups="bowl", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.50, 0.50), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + + food1_in_bowl1 = OU.check_obj_in_receptacle(self, "food1", "bowl1") + food1_in_bowl2 = OU.check_obj_in_receptacle(self, "food1", "bowl2") + food2_in_bowl1 = OU.check_obj_in_receptacle(self, "food2", "bowl1") + food2_in_bowl2 = OU.check_obj_in_receptacle(self, "food2", "bowl2") + food3_in_bowl1 = OU.check_obj_in_receptacle(self, "food3", "bowl1") + food3_in_bowl2 = OU.check_obj_in_receptacle(self, "food3", "bowl2") + + food12_in_bowl_1 = food1_in_bowl1 and food2_in_bowl1 + food12_in_bowl_2 = food1_in_bowl2 and food2_in_bowl2 + + return (not water_on) and ( + (food12_in_bowl_1 and food3_in_bowl2) + or (food12_in_bowl_2 and food3_in_bowl1) + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/clear_clutter.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/clear_clutter.py new file mode 100644 index 0000000000000000000000000000000000000000..0e027bb26a076fec25bc99b3a675df10eee22485 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/clear_clutter.py @@ -0,0 +1,147 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ClearClutter(Kitchen): + """ + Clear Clutter: composite task for Washing Fruits And Vegetables activity. + + Simulates the task of washing fruits and vegetables. + + Steps: + Pick up the fruits and vegetables and place them in the sink turn on the + sink to wash them. Then, turn the sink off, put them in the tray. + """ + + def __init__(self, *args, **kwargs): + # internal state variables to keep track of task progress + self.food_washed = False + self.washed_time = 0 + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + # sample large enough region to place the food items + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.6, 0.6)) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + ep_meta["lang"] = ( + "Pick up the fruits and vegetables and place them in the sink. " + "Turn on the sink faucet to wash them. Then turn the sink off and put them in the tray." + ) + return ep_meta + + def _reset_internal(self): + self.food_washed = False + self.washed_time = 0 + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + self.num_food = self.rng.choice([1, 2]) + self.num_unwashable = self.rng.choice([1, 2]) + + for i in range(self.num_food): + cfgs.append( + dict( + name=f"obj_{i}", + obj_groups=["vegetable", "fruit"], + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.40, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + for i in range(self.num_unwashable): + cfgs.append( + dict( + name=f"unwashable_obj_{i}", + obj_groups="all", + # make the object not washable and make sure there aren't 2 trays + exclude_obj_groups=["food", "tray"], + washable=False, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.40, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="receptacle", + obj_groups="tray", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.6, 0.6) + ), + size=(0.6, 0.8), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + food_in_sink = all( + [ + OU.obj_inside_of(self, f"obj_{i}", self.sink) + for i in range(self.num_food) + ] + ) + unwashables_not_in_sink = all( + [ + not OU.obj_inside_of(self, f"unwashable_obj_{i}", self.sink) + for i in range(self.num_unwashable) + ] + ) + water_on = self.sink.get_handle_state(env=self)["water_on"] + # make sure the food has been washed for suffient time (10 steps) + if food_in_sink and unwashables_not_in_sink and water_on: + self.washed_time += 1 + self.food_washed = self.washed_time > 10 + else: + self.washed_time = 0 + + food_in_tray = all( + [ + OU.check_obj_in_receptacle(self, f"obj_{i}", "receptacle") + for i in range(self.num_food) + ] + ) + unwashables_not_in_tray = all( + [ + not OU.check_obj_in_receptacle( + self, f"unwashable_obj_{i}", "receptacle" + ) + for i in range(self.num_unwashable) + ] + ) + + return ( + self.food_washed + and food_in_tray + and unwashables_not_in_tray + and not water_on + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/drain_veggies.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/drain_veggies.py new file mode 100644 index 0000000000000000000000000000000000000000..57f201f304116462fae9b39016838275495c807a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/drain_veggies.py @@ -0,0 +1,79 @@ +from robocasa.environments.kitchen.kitchen import * + + +class DrainVeggies(Kitchen): + """ + Drain Veggies: composite task for Washing Fruits And Vegetables activity. + + Simulates the task of draining washed vegetables. + + Steps: + Dump the vegetables from the pot into the sink. Then turn on the sink and + wash the vegetables. Then turn off the sink and put the vegetables back in + the pot. + """ + + def __init__(self, *args, **kwargs): + # internal state variables for the task + self.vegetables_washed = False + self.washed_time = 0 + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.sink, size=(0.6, 0.6)) + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + food_name = self.get_obj_lang("obj") + ep_meta["lang"] = ( + f"Dump the {food_name} from the pot into the sink. Then turn on the water and wash the {food_name}. " + f"Then turn off the water and put the {food_name} back in the pot." + ) + return ep_meta + + def _reset_internal(self): + # reset task progress variables + self.vegetables_washed = False + self.washed_time = 0 + super()._reset_internal() + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name=f"obj", + obj_groups="vegetable", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, loc="left_right", top_size=(0.6, 0.6) + ), + try_to_place_in="pot", + size=(0.6, 0.4), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + vegetables_in_sink = OU.obj_inside_of(self, f"obj", self.sink) + water_on = self.sink.get_handle_state(env=self)["water_on"] + # make sure the vegetables are washed for at least 10 steps + if vegetables_in_sink and water_on: + self.washed_time += 1 + self.vegetables_washed = self.washed_time > 10 + else: + self.washed_time = 0 + + vegetables_in_pot = OU.check_obj_in_receptacle(self, f"obj", "obj_container") + + return self.vegetables_washed and vegetables_in_pot and not water_on diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/prewash_food_assembly.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/prewash_food_assembly.py new file mode 100644 index 0000000000000000000000000000000000000000..b7c0dd42025877c73062c6e2043324e2934552cd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/multi_stage/washing_fruits_and_vegetables/prewash_food_assembly.py @@ -0,0 +1,106 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PrewashFoodAssembly(Kitchen): + """ + Prewash Food Assembly: composite task for Washing Fruits And Vegetables activity. + + Simulates the process of assembling fruits and vegetables in a bowl and + prewashing them. + + Steps: + Pick the fruit/vegetable from the cabinet and place it in the bowl. Then + pick the bowl and place it in the sink. Then turn on the sink facuet. + + Args: + cab_id (int): Enum which serves as a unique identifier for different + cabinet types. Used to choose the cabinet from which food is picked. + """ + + def __init__(self, cab_id=FixtureType.CABINET_TOP, *args, **kwargs): + self.cab_id = cab_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.sink = self.register_fixture_ref("sink", dict(id=FixtureType.SINK)) + self.counter_cab = self.register_fixture_ref( + "counter_cab", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.counter_sink = self.register_fixture_ref( + "counter_sink", dict(id=FixtureType.COUNTER, ref=self.sink) + ) + + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + ep_meta = super().get_ep_meta() + food_name = self.get_obj_lang("food") + ep_meta["lang"] = ( + f"Pick the {food_name} from the cabinet and place it in the bowl. " + "Then pick the bowl and place it in the sink. Then turn on the sink facuet." + ) + + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + cfgs = [] + + cfgs.append( + dict( + name="food", + obj_groups=["vegetable", "fruit"], + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="bowl", + obj_groups="bowl", + graspable=True, + placement=dict( + fixture=self.counter_cab, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.50, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + gripper_obj_far = OU.gripper_obj_far(self, obj_name="bowl") + food_in_bowl = OU.check_obj_in_receptacle(self, "food", "bowl") + bowl_in_sink = OU.obj_inside_of(self, "bowl", self.sink) + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + return gripper_obj_far and food_in_bowl and bowl_in_sink and water_on diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_coffee.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_coffee.py new file mode 100644 index 0000000000000000000000000000000000000000..6ac74d6a42d7587db5f3d5b25cb71e41bc89bac7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_coffee.py @@ -0,0 +1,189 @@ +import numpy as np + +from robocasa.environments.kitchen.kitchen import * + + +class PnPCoffee(Kitchen): + """ + Class encapsulating the atomic pick and place coffee tasks. + + Args: + behavior (str): "counter_to_machine" or "machine_to_counter". Used to define the desired + pick and place behavior for the task. + """ + + def __init__(self, behavior="machine_to_counter", *args, **kwargs): + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the coffee tasks. (Coffee machine and counter) + """ + super()._setup_kitchen_references() + self.coffee_machine = self.get_fixture("coffee_machine") + self.counter = self.get_fixture(FixtureType.COUNTER, ref=self.coffee_machine) + self.init_robot_base_pos = self.coffee_machine + + def get_ep_meta(self): + """ + Get the episode metadata for the coffee tasks. + This includes the language description of the task. + + Returns: + dict: Episode metadata. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + if self.behavior == "counter_to_machine": + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the counter and place it under the coffee machine dispenser" + elif self.behavior == "machine_to_counter": + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from under the coffee machine dispenser and place it on the counter" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the coffee tasks. This includes the object placement configurations. + Place the mug on the counter or under the coffee machine dispenser based on the behavior. + + Returns: + list: List of object configurations. + """ + cfgs = [] + if self.behavior == "counter_to_machine": + cfgs.append( + dict( + name="obj", + obj_groups="mug", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.coffee_machine, + ), + size=(0.30, 0.40), + pos=("ref", -1.0), + rotation=[np.pi / 4, np.pi / 2], + ), + ) + ) + elif self.behavior == "machine_to_counter": + cfgs.append( + dict( + name="obj", + obj_groups="mug", + placement=dict( + fixture=self.coffee_machine, + ensure_object_boundary_in_range=False, + margin=0.0, + ensure_valid_placement=False, + rotation=(np.pi / 8, np.pi / 4), + ), + ) + ) + else: + raise NotImplementedError + + return cfgs + + def _check_success(self): + """ + Check if the coffee task is successful. + This includes checking if the gripper is far from the object and the object is in corretly placed + on the desired fixture (counter or coffee machine). + """ + gripper_obj_far = OU.gripper_obj_far(self) + + if self.behavior == "counter_to_machine": + contact_check = self.coffee_machine.check_receptacle_placement_for_pouring( + self, "obj" + ) + elif self.behavior == "machine_to_counter": + contact_check = OU.check_obj_fixture_contact(self, "obj", self.counter) + return contact_check and gripper_obj_far + + +class CoffeeSetupMug(PnPCoffee): + """ + Class encapsulating the coffee setup task. Pick the mug from the counter and place it under the coffee machine dispenser. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="counter_to_machine", *args, **kwargs) + + +class CoffeeServeMug(PnPCoffee): + """ + Class encapsulating the coffee serve task. Pick the mug from under the coffee machine dispenser and place it on the counter. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="machine_to_counter", *args, **kwargs) + + +class CoffeePressButton(Kitchen): + """ + Class encapsulating the coffee press button task. Press the button on the coffee machine to serve coffee. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the coffee press button task. (Coffee machine and counter the coffee machine is on) + """ + super()._setup_kitchen_references() + self.coffee_machine = self.get_fixture("coffee_machine") + self.counter = self.get_fixture(FixtureType.COUNTER, ref=self.coffee_machine) + self.init_robot_base_pos = self.coffee_machine + + def get_ep_meta(self): + """ + Get the episode metadata for the coffee press button task. + This includes the language description of the task. + + Returns: + dict: Episode metadata. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = "press the button on the coffee machine to serve coffee" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the coffee press button task. This includes the object placement configurations. + Places the mug under the coffee machine dispenser. + + Returns: + list: List of object configurations. + """ + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups="mug", + placement=dict( + fixture=self.coffee_machine, + ensure_object_boundary_in_range=False, + margin=0.0, + ensure_valid_placement=False, + rotation=(np.pi / 8, np.pi / 4), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the coffee press button task is successful. + This includes checking if the gripper is far from the object and the coffee machine is turned on/button has been pressed. + """ + gripper_button_far = self.coffee_machine.gripper_button_far(self) + + turned_on = self.coffee_machine.get_state()["turned_on"] + return turned_on and gripper_button_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_doors.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_doors.py new file mode 100644 index 0000000000000000000000000000000000000000..7656fccd21cb83bc6ab3dbcaae789034b2f43a32 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_doors.py @@ -0,0 +1,161 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ManipulateDoor(Kitchen): + """ + Class encapsulating the atomic manipulate door tasks. + + Args: + behavior (str): "open" or "close". Used to define the desired + door manipulation behavior for the task. + + door_id (str): The door fixture id to manipulate. + """ + + def __init__( + self, behavior="open", door_id=FixtureType.DOOR_TOP_HINGE, *args, **kwargs + ): + self.door_id = door_id + assert behavior in ["open", "close"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the door tasks. + """ + super()._setup_kitchen_references() + self.door_fxtr = self.register_fixture_ref("door_fxtr", dict(id=self.door_id)) + self.init_robot_base_pos = self.door_fxtr + + def get_ep_meta(self): + """ + Get the episode metadata for the door tasks. + This includes the language description of the task. + + Returns: + dict: Episode metadata. + """ + ep_meta = super().get_ep_meta() + if isinstance(self.door_fxtr, Microwave): + door_fxtr_name = "microwave" + door_name = "door" + elif isinstance(self.door_fxtr, SingleCabinet): + door_fxtr_name = "cabinet" + door_name = "door" + elif isinstance(self.door_fxtr, HingeCabinet): + door_fxtr_name = "cabinet" + door_name = "doors" + elif isinstance(self.door_fxtr, Drawer): + door_fxtr_name = "drawer" + door_name = "doors" + ep_meta["lang"] = f"{self.behavior} the {door_fxtr_name} {door_name}" + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the door tasks. + This includes setting the door state based on the behavior. + """ + if self.behavior == "open": + self.door_fxtr.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.door_fxtr.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + # set the door state then place the objects otherwise objects initialized in opened drawer will fall down before the drawer is opened + super()._reset_internal() + + def _check_success(self): + """ + Check if the door manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + door_state = self.door_fxtr.get_door_state(env=self) + + success = True + for joint_p in door_state.values(): + if self.behavior == "open": + if joint_p < 0.90: + success = False + break + elif self.behavior == "close": + if joint_p > 0.05: + success = False + break + + return success + + def _get_obj_cfgs(self): + """ + Get the object configurations for the door tasks. This includes the object placement configurations. + Place one object inside the door fixture and 1-4 distractors on the counter. + """ + cfgs = [] + + cfgs.append( + dict( + name="door_obj", + obj_groups="all", + graspable=True, + microwavable=(True if isinstance(self.door_fxtr, Microwave) else None), + placement=dict( + fixture=self.door_fxtr, + size=(0.30, 0.30), + pos=(None, -1.0), + ), + ) + ) + + # distractors + num_distr = self.rng.integers(1, 4) + for i in range(num_distr): + cfgs.append( + dict( + name=f"distr_counter_{i+1}", + obj_groups="all", + placement=dict( + fixture=self.get_fixture( + FixtureType.COUNTER, ref=self.door_fxtr + ), + sample_region_kwargs=dict( + ref=self.door_fxtr, + ), + size=(1.0, 0.50), + pos=(None, -1.0), + offset=(0.0, 0.10), + ), + ) + ) + + return cfgs + + +class OpenDoor(ManipulateDoor): + def __init__(self, *args, **kwargs): + super().__init__(behavior="open", *args, **kwargs) + + +class OpenSingleDoor(OpenDoor): + def __init__(self, door_id=FixtureType.DOOR_TOP_HINGE_SINGLE, *args, **kwargs): + super().__init__(door_id=door_id, *args, **kwargs) + + +class OpenDoubleDoor(OpenDoor): + def __init__(self, door_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + super().__init__(door_id=door_id, *args, **kwargs) + + +class CloseDoor(ManipulateDoor): + def __init__(self, behavior=None, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) + + +class CloseSingleDoor(CloseDoor): + def __init__(self, door_id=FixtureType.DOOR_TOP_HINGE_SINGLE, *args, **kwargs): + super().__init__(door_id=door_id, *args, **kwargs) + + +class CloseDoubleDoor(CloseDoor): + def __init__(self, door_id=FixtureType.DOOR_TOP_HINGE_DOUBLE, *args, **kwargs): + super().__init__(door_id=door_id, *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_drawer.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_drawer.py new file mode 100644 index 0000000000000000000000000000000000000000..0b2ef524db5c85b0f0be5e49eddbfb08842456e3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_drawer.py @@ -0,0 +1,291 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ManipulateDrawer(Kitchen): + """ + Class encapsulating the atomic manipulate drawer tasks. + + Args: + behavior (str): "open" or "close". Used to define the desired + drawer manipulation behavior for the task. + + drawer_id (str): The drawer fixture id to manipulate + """ + + def __init__( + self, behavior="open", drawer_id=FixtureType.TOP_DRAWER, *args, **kwargs + ): + # for open and close tasks the robot will next to the drawer. + # since for open tasks all drawers will be close it is ambigious which drawer to open, + # so we specify a which side the drawer is on to open. The side is determined in _load_model + self.robot_side = "" + self.drawer_id = drawer_id + assert behavior in ["open", "close"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _load_model(self): + super()._load_model() + robot_model = self.robots[0].robot_model + x_ofs = (self.drawer.width / 2) + 0.3 + inits = [] + + # compute where the robot placement if it is to the left of the drawer + ( + robot_base_pos_left, + robot_base_ori_left, + ) = self.compute_robot_base_placement_pose( + ref_fixture=self.drawer, offset=(-x_ofs, -0.23) + ) + # get a test point to check if the robot is in contact with any fixture. + test_pos_left, _ = self.compute_robot_base_placement_pose( + ref_fixture=self.drawer, offset=(-x_ofs - 0.3, -0.23) + ) + + # check if the robot will be in contact with any fixture or wall during initialization + if not self.check_fxtr_contact( + test_pos_left + ) and not self.check_sidewall_contact(test_pos_left): + # drawer is to the right of the robot + inits.append((robot_base_pos_left, robot_base_ori_left, "right")) + + # compute where the robot placement if it is to the right of the drawer + ( + robot_base_pos_right, + robot_base_ori_right, + ) = self.compute_robot_base_placement_pose( + ref_fixture=self.drawer, offset=(x_ofs, -0.23) + ) + # get a test point to check if the robot is in contact with any fixture if initialized to the right of the drawer + test_pos_right, _ = self.compute_robot_base_placement_pose( + ref_fixture=self.drawer, offset=(x_ofs + 0.3, -0.23) + ) + + if not self.check_fxtr_contact( + test_pos_right + ) and not self.check_sidewall_contact(test_pos_right): + inits.append((robot_base_pos_right, robot_base_ori_right, "left")) + + assert len(inits) > 0 + random_index = self.rng.integers(len(inits)) + robot_base_pos, robot_base_ori, side = inits[random_index] + self.drawer_side = side + robot_model.set_base_xpos(robot_base_pos) + robot_model.set_base_ori(robot_base_ori) + + def _reset_internal(self): + """ + Reset the environment internal state for the drawer tasks. + This includes setting the drawer state based on the behavior + """ + if self.behavior == "open": + self.drawer.set_door_state(min=0.0, max=0.0, env=self, rng=self.rng) + elif self.behavior == "close": + self.drawer.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + # set the door state then place the objects otherwise objects initialized in opened drawer will fall down before the drawer is opened + super()._reset_internal() + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the drawer tasks + """ + super()._setup_kitchen_references() + self.drawer = self.register_fixture_ref("drawer", dict(id=self.drawer_id)) + self.init_robot_base_pos = self.drawer + + def get_ep_meta(self): + """ + Get the episode metadata for the drawer tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"{self.behavior} the {self.drawer_side} drawer" + return ep_meta + + def check_fxtr_contact(self, pos): + """ + Check if the point is in contact with any fixture + + Args: + pos (tuple): The position of the point to check + + Returns: + bool: True if the point is in contact with any fixture, False otherwise + """ + fxtrs = [ + fxtr + for fxtr in self.fixtures.values() + if isinstance(fxtr, Counter) + or isinstance(fxtr, Stove) + or isinstance(fxtr, Stovetop) + or isinstance(fxtr, HousingCabinet) + or isinstance(fxtr, SingleCabinet) + or isinstance(fxtr, HingeCabinet) + ] + + for fxtr in fxtrs: + # get bounds of fixture + if OU.point_in_fixture(point=pos, fixture=fxtr, only_2d=True): + return True + return False + + def check_sidewall_contact(self, pos): + """ + Check if the point is in contact with any wall. + This is separate from check_fxtr_contact because the point could be outside of the wall's + bounds but still in contact with the wall since the wall is thin. + + Args: + pos (tuple): The position of the point to check + + Returns: + bool: True if the point is in contact with any wall, False otherwise + """ + + walls = [ + fxtr for (name, fxtr) in self.fixtures.items() if isinstance(fxtr, Wall) + ] + for wall in walls: + if wall.wall_side == "right" and pos[0] > wall.pos[0]: + return True + # terrible hack change later we only want to check if its outside the main left wall not a secondary left wall + if ( + wall.wall_side == "left" + and "2" not in wall.name + and pos[0] < wall.pos[0] + ): + return True + if wall.wall_side == "back" and pos[1] > wall.pos[1]: + return True + return False + + def _check_success(self): + """ + Check if the drawer manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + door_state = self.drawer.get_door_state(env=self) + + success = True + for joint_p in door_state.values(): + if self.behavior == "open": + if joint_p < 0.95: + success = False + break + elif self.behavior == "close": + if joint_p > 0.05: + success = False + break + + return success + + +class OpenDrawer(ManipulateDrawer): + """ + Class encapsulating the atomic open drawer task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="open", *args, **kwargs) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the drawer tasks. This includes the object placement configurations. + Place the object inside the drawer and 1-4 distractors on the counter. + + Returns: + list: List of object configurations. + """ + cfgs = [] + + cfgs.append( + dict( + name="drawer_obj", + obj_groups="all", + graspable=True, + max_size=(None, None, 0.10), + placement=dict( + fixture=self.drawer, + size=(0.30, 0.30), + pos=(None, -0.75), + ), + ) + ) + + # distractors + num_distr = self.rng.integers(1, 4) + for i in range(num_distr): + cfgs.append( + dict( + name=f"distr_counter_{i+1}", + obj_groups="all", + placement=dict( + fixture=self.get_fixture(FixtureType.COUNTER, ref=self.drawer), + sample_region_kwargs=dict( + ref=self.drawer, + ), + size=(1.0, 0.50), + pos=(None, -1.0), + offset=(0.0, 0.10), + ), + ) + ) + + return cfgs + + +class CloseDrawer(ManipulateDrawer): + """ + Class encapsulating the atomic close drawer task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(behavior="close", *args, **kwargs) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the drawer tasks. This includes the object placement configurations. + Place the object inside the drawer and 1-4 distractors on the counter. + + Returns: + list: List of object configurations. + """ + cfgs = [] + + cfgs.append( + dict( + name="drawer_obj", + obj_groups="all", + graspable=True, + max_size=(None, None, 0.10), + placement=dict( + fixture=self.drawer, + size=(0.30, 0.30), + pos=(None, -0.75), + offset=(0, -self.drawer.size[1] * 0.55), + ), + ) + ) + + # distractors + num_distr = self.rng.integers(1, 4) + for i in range(num_distr): + cfgs.append( + dict( + name=f"distr_counter_{i+1}", + obj_groups="all", + placement=dict( + fixture=self.get_fixture(FixtureType.COUNTER, ref=self.drawer), + sample_region_kwargs=dict( + ref=self.drawer, + ), + size=(1.0, 0.50), + pos=(None, -1.0), + offset=(0.0, 0.10), + ), + ) + ) + + return cfgs diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_microwave.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_microwave.py new file mode 100644 index 0000000000000000000000000000000000000000..f5519eb21d92da672454b5f814d5fb0a5f32c016 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_microwave.py @@ -0,0 +1,90 @@ +from robocasa.environments.kitchen.kitchen import * + + +class MicrowavePressButton(Kitchen): + """ + Class encapsulating the atomic microwave press button tasks. + + Args: + behavior (str): "turn_on" or "turn_off". Used to define the desired + microwave manipulation behavior for the task + """ + + def __init__(self, behavior="turn_on", *args, **kwargs): + assert behavior in ["turn_on", "turn_off"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the microwave tasks + """ + super()._setup_kitchen_references() + self.microwave = self.get_fixture(FixtureType.MICROWAVE) + if self.behavior == "turn_off": + self.microwave._turned_on = True + self.init_robot_base_pos = self.microwave + + def get_ep_meta(self): + """ + Get the episode metadata for the microwave tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + if self.behavior == "turn_on": + ep_meta["lang"] = "press the start button on the microwave" + elif self.behavior == "turn_off": + ep_meta["lang"] = "press the stop button on the microwave" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the microwave tasks. This includes the object placement configurations. + Place the object inside the microwave and on top of another container object inside the microwave + + Returns: + list: List of object configurations. + """ + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups="all", + heatable=True, + placement=dict( + fixture=self.microwave, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + try_to_place_in="container", + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the microwave manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + turned_on = self.microwave.get_state()["turned_on"] + gripper_button_far = self.microwave.gripper_button_far( + self, button="start_button" if self.behavior == "turn_on" else "stop_button" + ) + + if self.behavior == "turn_on": + return turned_on and gripper_button_far + elif self.behavior == "turn_off": + return not turned_on and gripper_button_far + + +class TurnOnMicrowave(MicrowavePressButton): + def __init__(self, behavior=None, *args, **kwargs): + super().__init__(behavior="turn_on", *args, **kwargs) + + +class TurnOffMicrowave(MicrowavePressButton): + def __init__(self, behavior=None, *args, **kwargs): + super().__init__(behavior="turn_off", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_navigate.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_navigate.py new file mode 100644 index 0000000000000000000000000000000000000000..ff4f54fcde9a13a32251d794154a0183e29a5241 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_navigate.py @@ -0,0 +1,122 @@ +from robocasa.environments.kitchen.kitchen import * + + +class NavigateKitchen(Kitchen): + """ + Class encapsulating the atomic navigate kitchen tasks. + Involves navigating the robot to a target fixture. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the navigate kitchen tasks. + If not already chosen, selects a random start and destination fixture for the robot to navigate from/to. + """ + super()._setup_kitchen_references() + if "src_fixture" in self.fixture_refs: + self.src_fixture = self.fixture_refs["src_fixture"] + self.target_fixture = self.fixture_refs["target_fixture"] + else: + # choose a valid random start and destination fixture + fixtures = list(self.fixtures.values()) + valid_src_fixture_classes = [ + "CoffeeMachine", + "Toaster", + "Stove", + "Stovetop", + "SingleCabinet", + "HingeCabinet", + "OpenCabinet", + "Drawer", + "Microwave", + "Sink", + "Hood", + "Oven", + "Fridge", + "Dishwasher", + ] + # keep choosing src fixture until it is a valid fixture + while True: + self.src_fixture = self.rng.choice(fixtures) + fxtr_class = type(self.src_fixture).__name__ + if fxtr_class not in valid_src_fixture_classes: + continue + break + + fxtr_classes = [type(fxtr).__name__ for fxtr in fixtures] + valid_target_fxtr_classes = [ + cls + for cls in fxtr_classes + if fxtr_classes.count(cls) == 1 + and cls + in [ + "CoffeeMachine", + "Toaster", + "Stove", + "Stovetop", + "OpenCabinet", + "Microwave", + "Sink", + "Hood", + "Oven", + "Fridge", + "Dishwasher", + ] + ] + + while True: + self.target_fixture = self.rng.choice(fixtures) + fxtr_class = type(self.target_fixture).__name__ + if ( + self.target_fixture == self.src_fixture + or fxtr_class not in valid_target_fxtr_classes + ): + continue + if fxtr_class == "Accessory": + continue + # don't sample closeby fixtures + if ( + OU.fixture_pairwise_dist(self.src_fixture, self.target_fixture) + <= 1.0 + ): + continue + break + + self.fixture_refs["src_fixture"] = self.src_fixture + self.fixture_refs["target_fixture"] = self.target_fixture + + self.target_pos, self.target_ori = self.compute_robot_base_placement_pose( + self.target_fixture + ) + + self.init_robot_base_pos = self.src_fixture + + def get_ep_meta(self): + """ + Get the episode metadata for the navigate kitchen tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"navigate to the {self.target_fixture.nat_lang}" + return ep_meta + + def _check_success(self): + """ + Check if the navigation task is successful. + This is done by checking if the robot is within a certain distance of the target fixture and the robot is facing the fixture. + + Returns: + bool: True if the task is successful, False otherwise. + """ + robot_id = self.sim.model.body_name2id("mobilebase0_base") + base_pos = np.array(self.sim.data.body_xpos[robot_id]) + pos_check = np.linalg.norm(self.target_pos[:2] - base_pos[:2]) <= 0.20 + base_ori = T.mat2euler( + np.array(self.sim.data.body_xmat[robot_id]).reshape((3, 3)) + ) + ori_check = np.cos(self.target_ori[2] - base_ori[2]) >= 0.98 + + return pos_check and ori_check diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_pnp.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_pnp.py new file mode 100644 index 0000000000000000000000000000000000000000..f702dd1e078a58372d03455b5c6ef51bbc23ca4e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_pnp.py @@ -0,0 +1,908 @@ +from robocasa.environments.kitchen.kitchen import * + + +class PnP(Kitchen): + """ + Class encapsulating the atomic pick and place tasks. + + Args: + obj_groups (str): Object groups to sample the target object from. + + exclude_obj_groups (str): Object groups to exclude from sampling the target object. + """ + + def __init__(self, obj_groups="all", exclude_obj_groups=None, *args, **kwargs): + self.obj_groups = obj_groups + self.exclude_obj_groups = exclude_obj_groups + + super().__init__(*args, **kwargs) + + def _get_obj_cfgs(self): + raise NotImplementedError + + +class PnPCounterToCab(PnP): + """ + Class encapsulating the atomic counter to cabinet pick and place task + + Args: + cab_id (str): The cabinet fixture id to place the object. + + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__( + self, cab_id=FixtureType.CABINET_TOP, obj_groups="all", *args, **kwargs + ): + + self.cab_id = cab_id + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the counter to cabinet pick and place task: + The cabinet to place object in and the counter to initialize it on + """ + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref("cab", dict(id=self.cab_id)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.cab) + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + """ + Get the episode metadata for the counter to cabinet pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the counter and place it in the cabinet" + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the counter to cabinet pick and place task. + Puts the target object in the front area of the counter. Puts a distractor object on the counter + and the back area of the cabinet. + + """ + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(0.60, 0.30), + pos=(0.0, -1.0), + offset=(0.0, 0.10), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the counter to cabinet pick and place task is successful. + Checks if the object is inside the cabinet and the gripper is far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj_inside_cab = OU.obj_inside_of(self, "obj", self.cab) + gripper_obj_far = OU.gripper_obj_far(self) + return obj_inside_cab and gripper_obj_far + + +class PnPCabToCounter(PnP): + """ + Class encapsulating the atomic cabinet to counter pick and place task + + Args: + cab_id (str): The cabinet fixture id to pick the object from. + + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__( + self, cab_id=FixtureType.CABINET_TOP, obj_groups="all", *args, **kwargs + ): + self.cab_id = cab_id + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the cabinet to counter pick and place task: + The cabinet to pick object from and the counter to place it on + """ + super()._setup_kitchen_references() + self.cab = self.register_fixture_ref( + "cab", + dict(id=self.cab_id), + ) + self.counter = self.register_fixture_ref( + "counter", + dict(id=FixtureType.COUNTER, ref=self.cab), + ) + self.init_robot_base_pos = self.cab + + def get_ep_meta(self): + """ + Get the episode metadata for the cabinet to counter pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the cabinet and place it on the counter" + return ep_meta + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.cab.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the cabinet to counter pick and place task. + Puts the target object in the front area of the cabinet. Puts a distractor object on the counter + and the back area of the cabinet. + """ + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + placement=dict( + fixture=self.cab, + size=(0.50, 0.20), + pos=(0, -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.cab, + ), + size=(1.0, 0.30), + pos=(0.0, 1.0), + offset=(0.0, -0.05), + ), + ) + ) + cfgs.append( + dict( + name="distr_cab", + obj_groups="all", + placement=dict( + fixture=self.cab, + size=(1.0, 0.20), + pos=(0.0, 1.0), + offset=(0.0, 0.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the cabinet to counter pick and place task is successful. + Checks if the object is on the counter and the gripper is far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + gripper_obj_far = OU.gripper_obj_far(self) + obj_on_counter = OU.check_obj_fixture_contact(self, "obj", self.counter) + return obj_on_counter and gripper_obj_far + + +class PnPCounterToSink(PnP): + """ + Class encapsulating the atomic counter to sink pick and place task + + Args: + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__(self, obj_groups="all", *args, **kwargs): + + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the counter to sink pick and place task: + The sink to place object in and the counter to initialize it on + """ + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref( + "sink", + dict(id=FixtureType.SINK), + ) + self.counter = self.register_fixture_ref( + "counter", + dict(id=FixtureType.COUNTER, ref=self.sink), + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + """ + Get the episode metadata for the counter to sink pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the counter and place it in the sink" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the counter to sink pick and place task. + Puts the target object in the front area of the counter. Puts a distractor object on the counter + and the sink. + """ + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + washable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.30), + ), + ) + ) + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.25, 0.25), + pos=(0.0, 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the counter to sink pick and place task is successful. + Checks if the object is inside the sink and the gripper is far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj_in_sink = OU.obj_inside_of(self, "obj", self.sink, partial_check=True) + gripper_obj_far = OU.gripper_obj_far(self) + return obj_in_sink and gripper_obj_far + + +class PnPSinkToCounter(PnP): + """ + Class encapsulating the atomic sink to counter pick and place task + + Args: + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__(self, obj_groups="food", *args, **kwargs): + + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the sink to counter pick and place task: + The sink to pick object from and the counter to place it on + """ + super()._setup_kitchen_references() + self.sink = self.register_fixture_ref( + "sink", + dict(id=FixtureType.SINK), + ) + self.counter = self.register_fixture_ref( + "counter", + dict(id=FixtureType.COUNTER, ref=self.sink), + ) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + """ + Get the episode metadata for the sink to counter pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + cont_lang = self.get_obj_lang(obj_name="container") + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the sink and place it on the {cont_lang} located on the counter" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the sink to counter pick and place task. + Puts the target object in the sink. Puts a distractor object on the counter + and places a container on the counter for the target object to be placed on. + """ + cfgs = [] + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + washable=True, + placement=dict( + fixture=self.sink, + size=(0.25, 0.25), + pos=(0.0, 1.0), + ), + ) + ) + cfgs.append( + dict( + name="container", + obj_groups="container", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.35, 0.40), + pos=("ref", -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.30), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the sink to counter pick and place task is successful. + Checks if the object is in the container, the container on the counter, and the gripper far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj_in_recep = OU.check_obj_in_receptacle(self, "obj", "container") + recep_on_counter = self.check_contact(self.objects["container"], self.counter) + gripper_obj_far = OU.gripper_obj_far(self) + return obj_in_recep and recep_on_counter and gripper_obj_far + + +class PnPCounterToMicrowave(PnP): + # exclude layout 8 because the microwave is far from counters + EXCLUDE_LAYOUTS = [8] + """ + Class encapsulating the atomic counter to microwave pick and place task + + Args: + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__(self, obj_groups="food", *args, **kwargs): + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the counter to microwave pick and place task: + The microwave to place object on, the counter to initialize it/the container on, and a distractor counter + """ + super()._setup_kitchen_references() + self.microwave = self.register_fixture_ref( + "microwave", + dict(id=FixtureType.MICROWAVE), + ) + self.counter = self.register_fixture_ref( + "counter", + dict(id=FixtureType.COUNTER, ref=self.microwave), + ) + self.distr_counter = self.register_fixture_ref( + "distr_counter", + dict(id=FixtureType.COUNTER, ref=self.microwave), + ) + self.init_robot_base_pos = self.microwave + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.microwave.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def get_ep_meta(self): + """ + Get the episode metadata for the counter to microwave pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the counter and place it in the microwave" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the counter to microwave pick and place task. + Puts the target object in a container on the counter. Puts a distractor object on the distractor + counter and places another container in the microwave. + """ + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + microwavable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + try_to_place_in="container", + ), + ) + ) + cfgs.append( + dict( + name="container", + obj_groups=("plate"), + placement=dict( + fixture=self.microwave, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.distr_counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the counter to microwave pick and place task is successful. + Checks if the object is inside the microwave and on the container and the gripper is far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj = self.objects["obj"] + container = self.objects["container"] + + obj_container_contact = self.check_contact(obj, container) + container_micro_contact = self.check_contact(container, self.microwave) + gripper_obj_far = OU.gripper_obj_far(self) + return obj_container_contact and container_micro_contact and gripper_obj_far + + +class PnPMicrowaveToCounter(PnP): + # exclude layout 8 because the microwave is far from counters + EXCLUDE_LAYOUTS = [8] + """ + Class encapsulating the atomic microwave to counter pick and place task + + Args: + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__(self, obj_groups="food", *args, **kwargs): + + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the microwave to counter pick and place task: + The microwave to pick object from, the counter to place it on, and a distractor counter + """ + super()._setup_kitchen_references() + self.microwave = self.register_fixture_ref( + "microwave", + dict(id=FixtureType.MICROWAVE), + ) + self.counter = self.register_fixture_ref( + "counter", + dict(id=FixtureType.COUNTER, ref=self.microwave), + ) + self.distr_counter = self.register_fixture_ref( + "distr_counter", + dict(id=FixtureType.COUNTER, ref=self.microwave), + ) + self.init_robot_base_pos = self.microwave + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + self.microwave.set_door_state(min=0.90, max=1.0, env=self, rng=self.rng) + + def get_ep_meta(self): + """ + Get the episode metadata for the microwave to counter pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + cont_lang = self.get_obj_lang(obj_name="container") + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the microwave and place it on {cont_lang} located on the counter" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the microwave to counter pick and place task. + Puts the target object in a container in the microwave. Puts a distractor object on the distractor + counter and places another container on the counter.""" + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + microwavable=True, + placement=dict( + fixture=self.microwave, + size=(0.05, 0.05), + ensure_object_boundary_in_range=False, + try_to_place_in="container", + ), + ) + ) + cfgs.append( + dict( + name="container", + obj_groups=("container"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + ), + ) + ) + + # distractors + cfgs.append( + dict( + name="distr_counter", + obj_groups="all", + placement=dict( + fixture=self.distr_counter, + sample_region_kwargs=dict( + ref=self.microwave, + ), + size=(0.30, 0.30), + pos=("ref", 1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the microwave to counter pick and place task is successful. + Checks if the object is inside the container and the gripper far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj_container_contact = OU.check_obj_in_receptacle(self, "obj", "container") + gripper_obj_far = OU.gripper_obj_far(self) + return obj_container_contact and gripper_obj_far + + +class PnPCounterToStove(PnP): + """ + Class encapsulating the atomic counter to stove pick and place task + + Args: + obj_groups (str): Object groups to sample the target object from. + """ + + def __init__(self, obj_groups="food", *args, **kwargs): + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the counter to stove pick and place task: + The stove to place object on and the counter to initialize it/container on + """ + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=[0.30, 0.40]) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + """ + Get the episode metadata for the counter to stove pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + cont_lang = self.get_obj_lang(obj_name="container") + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the plate and place it in the {cont_lang}" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the counter to stove pick and place task. + Puts the target object in a container on the counter and places pan on the stove. + """ + cfgs = [] + + cfgs.append( + dict( + name="container", + obj_groups=("pan"), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + size=(0.02, 0.02), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + ), + ) + ) + + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + cookable=True, + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + try_to_place_in="container", + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the counter to stove pick and place task is successful. + Checks if the object is on the pan and the gripper far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj_in_container = OU.check_obj_in_receptacle(self, "obj", "container", th=0.07) + gripper_obj_far = OU.gripper_obj_far(self) + + return obj_in_container and gripper_obj_far + + +class PnPStoveToCounter(PnP): + """ + Class encapsulating the atomic stove to counter pick and place task + """ + + def __init__(self, obj_groups="food", *args, **kwargs): + super().__init__(obj_groups=obj_groups, *args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the stove to counter pick and place task: + The counter to place object/container on and the stove to initialize it/the pan on + """ + super()._setup_kitchen_references() + self.stove = self.register_fixture_ref("stove", dict(id=FixtureType.STOVE)) + self.counter = self.register_fixture_ref( + "counter", dict(id=FixtureType.COUNTER, ref=self.stove, size=[0.30, 0.40]) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + """ + Get the episode metadata for the stove to counter pick and place task. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + obj_lang = self.get_obj_lang() + obj_cont_lang = self.get_obj_lang(obj_name="obj_container") + cont_lang, preposition = self.get_obj_lang( + obj_name="container", get_preposition=True + ) + ep_meta[ + "lang" + ] = f"pick the {obj_lang} from the {obj_cont_lang} and place it {preposition} the {cont_lang}" + return ep_meta + + def _get_obj_cfgs(self): + """ + Get the object configurations for the stove to counter pick and place task. + Puts the target object in a pan on the stove and places a container on the counter. + """ + cfgs = [] + + cfgs.append( + dict( + name="obj", + obj_groups=self.obj_groups, + exclude_obj_groups=self.exclude_obj_groups, + graspable=True, + cookable=True, + max_size=(0.15, 0.15, None), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + size=(0.02, 0.02), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + try_to_place_in="pan", + ), + ) + ) + + cfgs.append( + dict( + name="container", + obj_groups=("plate", "bowl"), + placement=dict( + fixture=self.counter, + sample_region_kwargs=dict( + ref=self.stove, + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the stove to counter pick and place task is successful. + Checks if the object is inside the container on the counter and the gripper far from the object. + + Returns: + bool: True if the task is successful, False otherwise + """ + obj_in_container = OU.check_obj_in_receptacle(self, "obj", "container", th=0.07) + gripper_obj_far = OU.gripper_obj_far(self) + + return obj_in_container and gripper_obj_far diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_sink.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_sink.py new file mode 100644 index 0000000000000000000000000000000000000000..f45d358de1edf1df7a2e90dee0fd832154632e46 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_sink.py @@ -0,0 +1,218 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ManipulateSinkFaucet(Kitchen): + """ + Class encapsulating the atomic manipulate sink faucet tasks. + + Args: + behavior (str): "turn_on" or "turn_off". Used to define the desired + sink faucet manipulation behavior for the task. + """ + + def __init__(self, behavior="turn_on", *args, **kwargs): + + assert behavior in ["turn_on", "turn_off"] + self.behavior = behavior + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the sink faucet tasks + """ + super()._setup_kitchen_references() + self.sink = self.get_fixture(FixtureType.SINK) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + """ + Get the episode metadata for the sink faucet tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"{self.behavior.replace('_', ' ')} the sink faucet" + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the sink faucet tasks. + This includes setting the sink faucet state based on the behavior + """ + super()._reset_internal() + + if self.behavior == "turn_on": + self.sink.set_handle_state(mode="off", env=self, rng=self.rng) + elif self.behavior == "turn_off": + self.sink.set_handle_state(mode="on", env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the sink faucet tasks. This includes the object placement configurations. + Place the objects on the counter and sink as distractors. + + Returns: + list: List of object configurations + """ + cfgs = [] + + # distractors + num_distr = self.rng.integers(1, 4) + for i in range(num_distr): + cfgs.append( + dict( + name=f"distr_counter_{i}", + obj_groups="all", + placement=dict( + fixture=self.get_fixture(FixtureType.COUNTER, ref=self.sink), + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.10), + ), + ) + ) + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.30, 0.40), + pos=(None, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the sink faucet manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + handle_state = self.sink.get_handle_state(env=self) + water_on = handle_state["water_on"] + + if self.behavior == "turn_on": + success = water_on + elif self.behavior == "turn_off": + success = not water_on + + return success + + +class TurnOnSinkFaucet(ManipulateSinkFaucet): + def __init__(self, *args, **kwargs): + super().__init__(behavior="turn_on", *args, **kwargs) + + +class TurnOffSinkFaucet(ManipulateSinkFaucet): + def __init__(self, *args, **kwargs): + super().__init__(behavior="turn_off", *args, **kwargs) + + +class TurnSinkSpout(Kitchen): + """ + Class encapsulating the atomic turn sink spout tasks. + + Args: + behavior (str): "left" or "right". Used to define the desired sink spout + manipulation behavior for the task. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the sink spout tasks + """ + super()._setup_kitchen_references() + self.sink = self.get_fixture(FixtureType.SINK) + if "task_refs" in self._ep_meta: + self.behavior = self._ep_meta["task_refs"]["behavior"] + self.init_sink_mode = self._ep_meta["task_refs"]["init_sink_mode"] + else: + self.behavior = self.rng.choice(["left", "right"]) + self.init_sink_mode = self.rng.choice(["on", "off"]) + self.init_robot_base_pos = self.sink + + def get_ep_meta(self): + """ + Get the episode metadata for the sink spout tasks. + This includes the language description of the task. + """ + ep_meta = super().get_ep_meta() + ep_meta["lang"] = f"turn the sink spout to the {self.behavior}" + ep_meta["task_refs"] = dict( + behavior=self.behavior, + init_sink_mode=self.init_sink_mode, + ) + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the sink spout tasks. + This includes setting the sink spout state based on the behavior + """ + super()._reset_internal() + self.sink.set_handle_state(mode=self.init_sink_mode, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the sink spout tasks. This includes the object placement configurations. + Place the objects on the counter and sink as distractors. + """ + cfgs = [] + + # distractors + num_distr = self.rng.integers(1, 4) + for i in range(num_distr): + cfgs.append( + dict( + name=f"distr_counter_{i}", + obj_groups="all", + placement=dict( + fixture=self.get_fixture(FixtureType.COUNTER, ref=self.sink), + sample_region_kwargs=dict( + ref=self.sink, + loc="left_right", + ), + size=(0.30, 0.30), + pos=("ref", -1.0), + offset=(0.0, 0.10), + ), + ) + ) + cfgs.append( + dict( + name="distr_sink", + obj_groups="all", + washable=True, + placement=dict( + fixture=self.sink, + size=(0.30, 0.40), + pos=(None, -1.0), + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the sink spout manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + handle_state = self.sink.get_handle_state(env=self) + success = handle_state["spout_ori"] == self.behavior + + return success diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_stove.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_stove.py new file mode 100644 index 0000000000000000000000000000000000000000..3c8ef20c9c8bb965bba0b1a20decaeea89bdfa25 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/environments/kitchen/single_stage/kitchen_stove.py @@ -0,0 +1,132 @@ +from robocasa.environments.kitchen.kitchen import * + + +class ManipulateStoveKnob(Kitchen): + """ + Class encapsulating the atomic manipulate stove knob tasks. + + Args: + knob_id (str): The stove knob id to manipulate. If set to "random", a random knob will be selected. + + behavior (str): "turn_on" or "turn_off". Used to define the desired + stove knob manipulation behavior for the task. + """ + + def __init__(self, knob_id="random", behavior="turn_on", *args, **kwargs): + assert behavior in ["turn_on", "turn_off"] + self.behavior = behavior + self.knob_id = knob_id + super().__init__(*args, **kwargs) + + def _setup_kitchen_references(self): + """ + Setup the kitchen references for the stove knob tasks + This includes the stove and the stove knob to manipulate, and the burner to place the cookware on. + """ + super()._setup_kitchen_references() + self.stove = self.get_fixture(FixtureType.STOVE) + if "task_refs" in self._ep_meta: + self.knob = self._ep_meta["task_refs"]["knob"] + self.cookware_burner = self._ep_meta["task_refs"]["cookware_burner"] + else: + valid_knobs = [ + k for (k, v) in self.stove.knob_joints.items() if v is not None + ] + if self.knob_id == "random": + self.knob = self.rng.choice(list(valid_knobs)) + else: + assert self.knob_id in valid_knobs + self.knob = self.knob + self.cookware_burner = ( + self.knob + if self.rng.uniform() <= 0.50 + else self.rng.choice(valid_knobs) + ) + self.init_robot_base_pos = self.stove + + def get_ep_meta(self): + """ + Get the episode metadata for the stove knob tasks. + This includes the language description of the task and the task references. + """ + ep_meta = super().get_ep_meta() + ep_meta[ + "lang" + ] = f"{self.behavior.replace('_', ' ')} the {self.knob.replace('_', ' ')} burner of the stove" + ep_meta["task_refs"] = dict( + knob=self.knob, + cookware_burner=self.cookware_burner, + ) + return ep_meta + + def _reset_internal(self): + """ + Reset the environment internal state for the stove knob tasks. + This includes setting the stove knob state based on the behavior. + """ + super()._reset_internal() + + if self.behavior == "turn_on": + self.stove.set_knob_state( + mode="off", knob=self.knob, env=self, rng=self.rng + ) + elif self.behavior == "turn_off": + self.stove.set_knob_state(mode="on", knob=self.knob, env=self, rng=self.rng) + + def _get_obj_cfgs(self): + """ + Get the object configurations for the stove knob tasks. + This includes the object placement configurations. + Place the cookware on the stove burner. + + Returns: + list: List of object configurations + """ + cfgs = [] + + cfgs.append( + dict( + name="cookware", + obj_groups=("cookware"), + placement=dict( + fixture=self.stove, + ensure_object_boundary_in_range=False, + sample_region_kwargs=dict( + locs=[self.cookware_burner], + ), + size=(0.02, 0.02), + rotation=[(-3 * np.pi / 8, -np.pi / 4), (np.pi / 4, 3 * np.pi / 8)], + ), + ) + ) + + return cfgs + + def _check_success(self): + """ + Check if the stove knob manipulation task is successful. + + Returns: + bool: True if the task is successful, False otherwise. + """ + knobs_state = self.stove.get_knobs_state(env=self) + knob_value = knobs_state[self.knob] + + knob_on = 0.35 <= np.abs(knob_value) <= 2 * np.pi - 0.35 + + if self.behavior == "turn_on": + success = knob_on + elif self.behavior == "turn_off": + success = not knob_on + + return success + + +class TurnOnStove(ManipulateStoveKnob): + def __init__(self, *args, **kwargs): + super().__init__(behavior="turn_on", *args, **kwargs) + + +class TurnOffStove(ManipulateStoveKnob): + def __init__(self, *args, **kwargs): + super().__init__(behavior="turn_off", *args, **kwargs) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/macros.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/macros.py new file mode 100644 index 0000000000000000000000000000000000000000..4ad923efd2a84b02a93114806bd968a39865dcf1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/macros.py @@ -0,0 +1,32 @@ +""" +Macro settings that can be imported and toggled. Internally, specific parts of the codebase rely on these settings +for determining core functionality. + +To make sure global reference is maintained, should import these settings as: + +`import robocasa.macros as macros` +""" + +SHOW_SITES = False + +# whether to print debugging information +VERBOSE = False + +# Spacemouse settings. Used by SpaceMouse class in robosuite/devices/spacemouse.py +SPACEMOUSE_VENDOR_ID = 9583 +SPACEMOUSE_PRODUCT_ID = 50741 + +DATASET_BASE_PATH = None + +try: + from robocasa.macros_private import * +except ImportError: + from robosuite.utils.log_utils import ROBOSUITE_DEFAULT_LOGGER + + import robocasa + + ROBOSUITE_DEFAULT_LOGGER.warn("No private macro file found!") + ROBOSUITE_DEFAULT_LOGGER.warn("It is recommended to use a private macro file") + ROBOSUITE_DEFAULT_LOGGER.warn( + "To setup, run: python {}/scripts/setup_macros.py".format(robocasa.__path__[0]) + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4eb69cbf75946578508a38c3d3e60381e68c4091 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/__init__.py @@ -0,0 +1,3 @@ +import os + +assets_root = os.path.join(os.path.dirname(__file__), "assets") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/arenas/empty_kitchen_arena.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/arenas/empty_kitchen_arena.xml new file mode 100644 index 0000000000000000000000000000000000000000..806dc03b163762a5c1c9ca5873a27d3c0bda90bb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/arenas/empty_kitchen_arena.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/dark_wood/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/dark_wood/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..38b7d06789938b42a43096ed07e2d178f2098df4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/dark_wood/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/fuji/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/fuji/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..904fd35631787b7571bc262e4a771d5958635d37 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/fuji/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/knife_block_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/knife_block_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..90c144a0f681d214c0b3b8fa39c993491a6de971 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/knife_block_1/model.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..eb289a5a57000b3fd7b94ab1a6228ed8f6ff0ab5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood/model.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..1e41317c61ea5d3f4aef0ff947416ee1b89f8671 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_2/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..3a945c09920b3a962bbae3c80d2a9953f900ce9e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/knife_blocks/light_wood_3/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/light_switches/white_wide_switch/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/light_switches/white_wide_switch/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f5f40bce6986324312b3faf68443a11c41fa1d6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/light_switches/white_wide_switch/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/outlets/simple_white/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/outlets/simple_white/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..9cad808552da712ad8cc34c515c70d5714a383de --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/outlets/simple_white/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..fc9c3d988d56ef00b092fcb033631075bf505e1b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_1/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..fcc4263fc94fd1ffcce3e2604e8177ac05c19d2b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_2/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e1652093ac13e542e3b8f4b14b4ac11d32f4237 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_3/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_4/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_4/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..1b7f9635e7769a7ab2c254d0724beaa0b4a6113d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_4/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_5/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_5/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..e548afbb9224330ba57e092dc74e0ef1fc3d7d5e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/paper_towel_holders/holder_5/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/aloe/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/aloe/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..7f59f52be2bef33f18866248c54b4e787968748b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/aloe/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/dodekaeder/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/dodekaeder/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..534bcfd50b33beec85447eacb536f59a146e8f90 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/dodekaeder/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/senecio/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/senecio/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..ee974108af4dc75e7720ef7770ab09064ac86b7e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/senecio/model.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/spikey_in_white_pot/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/spikey_in_white_pot/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..54d44e27bbff673cdcd943bcaa237af3ae003116 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/plants/spikey_in_white_pot/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/rattan_stool/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/rattan_stool/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..85b536d3178ba0195a07ad3716684b95f6dbb4d4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/rattan_stool/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..b68924ae241a0584513172f9655cf21656a95f68 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_1/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..427b2eef8ba9c2c9bd68b0281c7898c20ff16661 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_2/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..be2125837690a3f983cda4cd47b7d2c971091dde --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_1_3/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..9d653739135ae2e3a48fbf386b20ace5eeaba60b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/stools/stool_2/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..8038e0ca91e148d4b227461d5c63d68be0e8eded --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_1/model.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..238b19bf4fb3755ff02c19e0934ac8514c288d1c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_2/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_3/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_3/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..5ce47311dabd184949619d1286e23dc50c65e428 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_holders/holder_3/model.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/black_plastic/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/black_plastic/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..cf3195d941d0f5ce3be02d6c7561a6129e5d420f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/black_plastic/model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b3441d6dce3260a234f6f321893848a7c915dcf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..448623589304795b25c71139edf30f082f691960 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg/model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..920bc56d319627c2f3edbfcfe136ed0bcfde01ed --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/metal_cg_2/model.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/rack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/rack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..605dfc8cbe678b7529bde6486d21d31d707f9e55 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/accessories/utensil_racks/rack_1/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_hinge.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_hinge.xml new file mode 100644 index 0000000000000000000000000000000000000000..52f11f1c59c8feb65af025ac965ec8280830877a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_hinge.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_housing.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_housing.xml new file mode 100644 index 0000000000000000000000000000000000000000..b848292cf30dc79a9e7df833254c091dd4f564a6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_housing.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_open.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_open.xml new file mode 100644 index 0000000000000000000000000000000000000000..eef1097bc99d341b80847f2f5bc355bdf63930f1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_open.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/divided_window.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/divided_window.xml new file mode 100644 index 0000000000000000000000000000000000000000..e88908536f21c8498175b31bb88d5d1ca827ae7a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/divided_window.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/full_window.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/full_window.xml new file mode 100644 index 0000000000000000000000000000000000000000..784520ef6025c441258df1333f2231e647639ed3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/full_window.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/raised.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/raised.xml new file mode 100644 index 0000000000000000000000000000000000000000..e407488c09a1dfedb37248f9b31351dd8f1d5500 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/raised.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shaker.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shaker.xml new file mode 100644 index 0000000000000000000000000000000000000000..73cd4428ee4ca57ba172c4ac66fb64f16b92b31d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shaker.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shelf.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shelf.xml new file mode 100644 index 0000000000000000000000000000000000000000..3649625e26d30254ab62bec60f1d1e071bb65bda --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/shelf.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/slab.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/slab.xml new file mode 100644 index 0000000000000000000000000000000000000000..696e08782235be3d726985b3f77a58a834c5951f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_panels/slab.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_single.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_single.xml new file mode 100644 index 0000000000000000000000000000000000000000..e4fb19ecd8b5f83367aa3b062ef50a85a2040bb6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/cabinet_single.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/drawer.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/drawer.xml new file mode 100644 index 0000000000000000000000000000000000000000..047fdb356c2cb48da051e4d571b17de88000fa6e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/drawer.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/panel.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/panel.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e41172af77ac29026df162c346ca61f7abb4fa1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/cabinets/panel.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..bbec45fa2e9e9fe9bb17b7ccade56cf579977498 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso/model.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..59713e44a441acff05a4d5bccdce115580d8f14d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/delonghi_espresso_2/model.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/nespresso/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/nespresso/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c663a430487d83b6b4bd3dd6135f0f22ed6c92b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/nespresso/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/white/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/white/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..85b2719b90890f205969c098a2e77a7e02229026 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/coffee_machines/white/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/counters/counter/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/counters/counter/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e98c8d4bb011a687a05ec96cedf7f424243b579 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/counters/counter/model.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/counters/counter_with_opening/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/counters/counter_with_opening/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..85d400630a95209f10e7c837ceddabc3c1ae16e3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/counters/counter_with_opening/model.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/basic_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/basic_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..4aace8e6bc482a1fa30e93c9fe0e2a3200475af9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/basic_stainless/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c26b8d0175c90365fdb7853307d142a1053e2476 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/pack_1/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..49b90a3c1dfe173b70eca8cb60d5879b5abb343e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/dishwashers/pack_2/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/cabinet.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/cabinet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a0f4932a1a1b6689e2e29040734ef6cc8c21b8f6 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/cabinet.yaml @@ -0,0 +1,90 @@ +default: + texture: textures/wood/wood_grain_1.png + handle_type: bar + handle_config: + texture: textures/metals/bright_metal.png + + +#### panel textures #### +white: + texture: textures/flat/white.png +black: + texture: textures/flat/black.png +dark_gray: + texture: textures/flat/dark_gray.png +gray: + texture: textures/flat/gray.png +light_gray: + texture: textures/flat/light_gray.png +lighter_gray: + texture: textures/flat/lighter_gray.png +blue_gray: + texture: textures/flat/blue_gray.png +dark_blue: + texture: textures/flat/dark_blue.png +light_green: + texture: textures/flat/light_green.png +light_blue: + texture: textures/flat/light_blue.png +warm_white: + texture: textures/flat/warm_white.png +dark_wood_parquet: + texture: textures/wood/dark_wood_parquet.png +light_wood_parquet: + texture: textures/wood/light_wood_parquet.png +warm_wood_parquet: + texture: textures/wood/warm_wood_parquet.png +warm_wood_grain: + texture: textures/wood/warm_wood_grain_2.png +walnut_wood_grain: + texture: textures/wood/walnut_wood_grain.png +gray_wood_grain: + texture: textures/wood/gray_wood_grain.png +light_wood_planks_shelves: + texture: textures/wood/light_wood_planks.png +dark_wood_planks_shelves: + texture: textures/wood/dark_wood_planks.png +rustic_wood_shelves: + texture: textures/wood/greenheart_wood_grain.png +wood_grain_shelves: + texture: textures/wood/wood_planks_2.png +wood_grain_shelves_2: + texture: textures/wood/wood_grain_3.png + + +#### panel shapes #### +slab: + panel_type: slab +raised: + panel_type: raised +shaker: + panel_type: shaker +divided_window: + panel_type: divided_window +full_window_blurred: + panel_type: full_window + panel_config: + opacity: 0.4 +full_window_clear: + panel_type: full_window + panel_config: + opacity: 0.1 + + +#### handle shapes #### +handle_boxed: + handle_type: boxed +handle_knob: + handle_type: knob + + +#### handle textures #### +handle_brass: + handle_config: + texture: textures/metals/brass.png +handle_black: + handle_config: + texture: textures/flat/black.png +handle_dark_gray: + handle_config: + texture: textures/flat/dark_gray.png \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/coffee_machine.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/coffee_machine.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0927658a906a3834f448d5076fb37bbfe1a85627 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/coffee_machine.yaml @@ -0,0 +1,17 @@ +default: + name: coffee_machine + size: [null, null, 0.44] + xml: fixtures/coffee_machines/delonghi_espresso + +delonghi_espresso: + size: [null, null, 0.44] + xml: fixtures/coffee_machines/delonghi_espresso + +delonghi_espresso_2: + size: [null, null, 0.38] + xml: fixtures/coffee_machines/delonghi_espresso_2 + +nespresso: + name: coffee_machine + size: [null, null, 0.31] + xml: fixtures/coffee_machines/nespresso \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/counter.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/counter.yaml new file mode 100644 index 0000000000000000000000000000000000000000..179905673898333e07a5e0e0192432a5c21e6811 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/counter.yaml @@ -0,0 +1,92 @@ +# scandanavian +default: + top_texture: textures/wood/light_wood_planks.png + base_texture: textures/flat/white.png + + obj_x_percent: 0.5 + obj_y_percent: 0.5 + overhang: 0.05 +light_wood_base_white_top: + top_texture: textures/flat/white.png + base_texture: textures/wood/light_wood_planks.png + +dark_wood_base_marble_top: + top_texture: textures/marble/marble.png + base_texture: textures/wood/wood_grain_1.png + base_color: [0.3, 0.25, 0.25, 1] + +# coastal +dark_blue_base_marble_top: + top_texture: textures/marble/marble_5.png + base_texture: textures/flat/dark_blue.png + +# industrial +gray_base_tiled_wood_top: + top_texture: textures/wood/varnished_wood_planks.png + base_texture: textures/flat/gray.png +gray_base_marble_top: + top_texture: textures/marble/marble.png + base_texture: textures/flat/gray.png + +# traditional_1 +warm_wood_base_marble_top: + top_texture: textures/marble/marble.png + base_texture: textures/wood/warm_wood_parquet.png +white_base_marble_top: + top_texture: textures/marble/marble.png + base_texture: textures/flat/white.png + +# traditional_2 +warm_wood_base_granite_top: + top_texture: textures/marble/granite.png + base_texture: textures/wood/walnut_wood_grain.png + +# modern_1 +blue_gray_base_white_top: + top_texture: textures/flat/white.png + base_texture: textures/flat/blue_gray.png + +# modern_2 +# white_base_marble_top_2: +# top_texture: textures/flat/marble_3.png +# base_texture: textures/flat/dark_gray.png +white_base_marble_top_3: + top_texture: textures/marble/marble_2.png + base_texture: textures/flat/dark_gray.png + +# farmhouse +gray_wood_base_marble_top: + top_texture: textures/marble/marble_3.png + base_texture: textures/wood/gray_wood_grain.png + +# rustic +green_base_wood_top: + top_texture: textures/wood/greenheart_wood_grain.png + base_texture: textures/flat/light_green.png +green_base_granite_top: + top_texture: textures/marble/granite_2.png + base_texture: textures/flat/light_green.png + +# mediterranean +wood_base_dark_marble_top: + top_texture: textures/marble/dark_marble.png + base_texture: textures/wood/warm_wood_grain_2.png +cream_base_wood_parquet_top: + top_texture: textures/marble/marble_6.png + base_texture: textures/wood/warm_wood_parquet.png + +# transitional_1 +wood_base_marble_top: + top_texture: textures/marble/marble_2.png + base_texture: textures/wood/wood_grain_3.png +white_base_marble_top_2: + top_texture: textures/marble/marble_2.png + base_texture: textures/flat/lighter_gray.png + +# transitional_2 +white_base_marble_island: + top_texture: textures/marble/marble_4.png + base_texture: textures/flat/white.png +gray_base_marble_top_2: + top_texture: textures/marble/marble_4.png + base_texture: textures/flat/light_gray.png diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/dishwasher.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/dishwasher.yaml new file mode 100644 index 0000000000000000000000000000000000000000..552847dc03fb759f53f5b056299d46f0ce958a5a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/dishwasher.yaml @@ -0,0 +1,12 @@ +default: + name: dishwasher + size: [0.65, null, null] + +pack_1: + xml: fixtures/dishwashers/pack_1 + +pack_2: + xml: fixtures/dishwashers/pack_2 + +basic_stainless: + xml: fixtures/dishwashers/basic_stainless \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/floor.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/floor.yaml new file mode 100644 index 0000000000000000000000000000000000000000..99be747ddc5c48b71f7dd4cfd39d0235b5a8f37c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/floor.yaml @@ -0,0 +1,68 @@ +default: + texture: textures/wood/gray_wood_planks.png + +wood: + texture: textures/wood/wood_planks.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" +wood_2: + texture: textures/wood/wood_planks_2.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + +gray_wood: + texture: textures/wood/gray_wood_planks.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + +dark_wood: + texture: textures/wood/dark_wood_planks.png + +light_wood: + texture: textures/wood/light_wood_planks.png +light_wood_2: + texture: textures/wood/light_wood_planks_2.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" +light_wood_long: + texture: textures/wood/light_wood_planks_long.png + rgba: [1, 1, 1, 1] + +warm_wood: + texture: textures/wood/warm_wood_planks.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + +concrete_tiles: + texture: textures/tiles/concrete_tiles.png + mat_attrib: + texrepeat: "0.5 0.5" + texuniform: "true" +flower_ceramic_tiles: + texture: textures/tiles/flower_ceramic.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + +# rustic +wood_3: + texture: textures/wood/wood_planks_3.png + mat_attrib: + texrepeat: "0.75 0.75" + texuniform: "true" + +# mediterranean +orange_tiles: + texture: textures/tiles/orange_tiles.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + +# transitional_1 +dark_wood_planks: + texture: textures/wood/dark_wood_planks_2.png diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/framed_window.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/framed_window.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b9df2491ba66af1fb705aa9cc03d1857822c3d8f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/framed_window.yaml @@ -0,0 +1,3 @@ +default: + texture: textures/wood/dark_wood_planks.png + window_bak: textures/flat/warm_white.png \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/fridge.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/fridge.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bba812f817c33227b33c18bb4995f739a09a77d8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/fridge.yaml @@ -0,0 +1,18 @@ +default: + name: fridge + size: [null, null, 1] + +pack_1: + xml: fixtures/fridges/pack_1 + +pack_2: + xml: fixtures/fridges/pack_2 + +modern: + xml: fixtures/fridges/modern + +full_height_doors: + xml: fixtures/fridges/full_height_doors + +four_doors: + xml: fixtures/fridges/four_doors \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/hood.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/hood.yaml new file mode 100644 index 0000000000000000000000000000000000000000..08de0232778681ba3eff8cca23d6a9b86e060ffc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/hood.yaml @@ -0,0 +1,14 @@ +default: + xml: fixtures/hoods/simple_silver + +simple_silver: + xml: fixtures/hoods/simple_silver + +tall_stainless: + xml: fixtures/hoods/tall_stainless + +pack_1: + xml: fixtures/hoods/pack_1 + +pack_2: + xml: fixtures/hoods/pack_2 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/knife_block.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/knife_block.yaml new file mode 100644 index 0000000000000000000000000000000000000000..30fb53b19efd3dd57714858591c826ba69e57a7b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/knife_block.yaml @@ -0,0 +1,14 @@ +default: + name: knife_block + size: [0.12, null, null] + xml: fixtures/accessories/knife_blocks/light_wood_3 + +light_wood_3: + xml: fixtures/accessories/knife_blocks/light_wood_3 + +light_wood_2: + xml: fixtures/accessories/knife_blocks/light_wood_2 + +knife_block_1: + size: [0.10, null, null] + xml: fixtures/accessories/knife_blocks/knife_block_1 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/microwave.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/microwave.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3bb330bd73aa4d3a3a58d857897cb0fb35c5ea8c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/microwave.yaml @@ -0,0 +1,18 @@ +default: + alignment: bottom_front + size: [0.8, -1, -1] + +standard: + xml: fixtures/microwaves/standard + +gray: + xml: fixtures/microwaves/gray + +hamilton_beach: + xml: fixtures/microwaves/hamilton_beach + +pack_1: + xml: fixtures/microwaves/pack_1 + +pack_2: + xml: fixtures/microwaves/pack_2 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/oven.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/oven.yaml new file mode 100644 index 0000000000000000000000000000000000000000..788f840ebd49b7c46d0a9ea9483a41449c4a6e31 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/oven.yaml @@ -0,0 +1,20 @@ +default: + xml: fixtures/ovens/pack_1 + +pack_1: + xml: fixtures/ovens/pack_1 + +beko: + xml: fixtures/ovens/beko + +gorenje: + xml: fixtures/ovens/gorenje + +westerfeld: + xml: fixtures/ovens/westerfeld + +gorenje_dark: + xml: fixtures/ovens/gorenje_dark + +bosch: + xml: fixtures/ovens/bosch \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/paper_towel.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/paper_towel.yaml new file mode 100644 index 0000000000000000000000000000000000000000..eadd8e3df6631fe546617a7f8bebd8bca1ce64fd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/paper_towel.yaml @@ -0,0 +1,16 @@ +default: + name: paper_towel + size: [null, null, 0.35] + xml: fixtures/accessories/paper_towel_holders/holder_2 + +holder_2: + xml: fixtures/accessories/paper_towel_holders/holder_2 + +holder_3: + xml: fixtures/accessories/paper_towel_holders/holder_3 + +holder_4: + xml: fixtures/accessories/paper_towel_holders/holder_4 + +holder_5: + xml: fixtures/accessories/paper_towel_holders/holder_5 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/plant.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/plant.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7f0073375570612d1ca956c3625b0b43a97118db --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/plant.yaml @@ -0,0 +1,16 @@ +default: + name: plant + scale: 0.3 + xml: fixtures/accessories/plants/aloe + +aloe: + xml: fixtures/accessories/plants/aloe + +spikey_in_white_pot: + xml: fixtures/accessories/plants/spikey_in_white_pot + +senecio: + xml: fixtures/accessories/plants/senecio + +dodakaeder: + xml: fixtures/accessories/plants/dodakaeder \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/sink.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/sink.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a4ba9608298bfc846a8919e7cdb6aed91df6bf81 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/sink.yaml @@ -0,0 +1,29 @@ +default: + size: [null, 0.55, null] + +concrete_sink: + xml: fixtures/sinks/concrete_sink + +white_sink: + xml: fixtures/sinks/white_sink + +1_bin_wide_top_handle: + xml: fixtures/sinks/1_bin_wide_top_handle + +1.5_bins_storage_left_stainless: + xml: fixtures/sinks/1.5_bins_storage_left_stainless + +1_bin_storage_left_white_silver: + xml: fixtures/sinks/1_bin_storage_left_white_silver + +1_bin_storage_right_dark: + xml: fixtures/sinks/1_bin_storage_right_dark + +2_bins_farmhouse: + xml: fixtures/sinks/2_bins_farmhouse + +2_bins_stainless: + xml: fixtures/sinks/2_bins_stainless + +# brown_metal: +# xml: fixtures/sinks/brown_metal_sink \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stool.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4508603fc5beb9876a51c8557fdbb5d17fa37321 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stool.yaml @@ -0,0 +1,19 @@ +default: + name: chair + size: [null, null, 1.0] + +rattan_stool: + xml: fixtures/accessories/stools/rattan_stool + +stool_1_1: + xml: fixtures/accessories/stools/stool_1_1 + +stool_1_2: + xml: fixtures/accessories/stools/stool_1_2 + +stool_1_3: + xml: fixtures/accessories/stools/stool_1_3 + +stool_2: + xml: fixtures/accessories/stools/stool_2 + size: [null, null, 0.7] \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stove.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stove.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b5c7c9402fa1cb6e6867dd2afd1b9f0a5db81867 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stove.yaml @@ -0,0 +1,11 @@ +default: + xml: fixtures/stoves/basic_sleek_induc + +basic_sleek_induc: + xml: fixtures/stoves/basic_sleek_induc + +frigidaire_gas: + xml: fixtures/stoves/frigidaire_gas + +square_gas: + xml: fixtures/stoves/square_gas \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stovetop.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stovetop.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a4bdd3b138bb6b2c86c17ea1d613016221d8abd7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/stovetop.yaml @@ -0,0 +1,17 @@ +default: + size: [null, 0.55, null] + xml: fixtures/stovetops/sleek_silver_top_gas + +sleek_silver_top_gas: + xml: fixtures/stovetops/sleek_silver_top_gas + +alborz_top_gas: + xml: fixtures/stovetops/alborz_top_gas + size: [0.95, 0.55, null] + +pack_1_top_gas: + xml: fixtures/stovetops/pack_1_top_gas + +pack_1_top_induc: + xml: fixtures/stovetops/pack_1_top_induc + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/toaster.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/toaster.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bac9e2e01fc13ad72659c5a7e1bf91dd35fad732 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/toaster.yaml @@ -0,0 +1,19 @@ +default: + name: toaster + size: [null, 0.3, null] + xml: fixtures/toasters/basic_popup + +boxy: + xml: fixtures/toasters/boxy + +vintage: + xml: fixtures/toasters/vintage + +fancy: + xml: fixtures/toasters/fancy + +basic_popup_2: + xml: fixtures/toasters/basic_popup_2 + +basic_popup: + xml: fixtures/toasters/basic_popup \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/utensil_holder.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/utensil_holder.yaml new file mode 100644 index 0000000000000000000000000000000000000000..296434ee267205c9655db2120d7e360434c799e0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/utensil_holder.yaml @@ -0,0 +1,12 @@ +default: + name: utensil_holder + scale: 0.35 + +holder_1: + xml: fixtures/accessories/utensil_holders/holder_1 + +holder_2: + xml: fixtures/accessories/utensil_holders/holder_2 + +holder_3: + xml: fixtures/accessories/utensil_holders/holder_3 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/utensil_rack.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/utensil_rack.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ce3358b909a9fe05ec219eee65381351d8919afe --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/utensil_rack.yaml @@ -0,0 +1,14 @@ +default: + name: utensil_rack + scale: 0.40 + protrusion: 0.08 + +metal: + xml: fixtures/accessories/utensil_racks/metal + +black_plastic: + xml: fixtures/accessories/utensil_racks/black_plastic + +metal_cg_2: + protrusion: 0.054 + xml: fixtures/accessories/utensil_racks/metal_cg_2 \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/wall.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/wall.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2156046a86e1f0df6d7cf76e81784cc9e4f8f5a1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/wall.yaml @@ -0,0 +1,122 @@ +default: + quat: [-0.7071068, 0.7071068, 0, 0] + texture: textures/bricks/white_bricks.png + mat_attrib: + texrepeat: "3 3" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +red_bricks: + texture: textures/bricks/red_bricks.png +white_bricks: + texture: textures/bricks/white_bricks_2.png + mat_attrib: + texrepeat: "1.75 1.75" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" +playground: + texture: textures/albedo.png + mat_attrib: + texrepeat: "2 2" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +white_tiles: + texture: textures/tiles/white_tiles.png + mat_attrib: + texrepeat: "2 2" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" +white_square_tiles: + texture: textures/tiles/white_square_tiles.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# coastal +black_square_tiles: + texture: textures/tiles/black_square_tiles.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# mediterranean +orange_square_tiles: + texture: textures/tiles/orange_square_tiles.png + mat_attrib: + texrepeat: "2 2" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# traditional_2 +diamond_tiles: + texture: textures/tiles/diamond_tiles.png + mat_attrib: + texrepeat: "1.5 1.5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# flat textures +white_plaster: + texture: textures/flat/plaster.png +white: + texture: textures/flat/white.png +warm_white: + texture: textures/flat/warm_white.png + +concrete: + texture: textures/others/concrete.png + +# transitional_1 +diamond_marble_parquet: + texture: textures/tiles/diamond_marble_parquet.png + +# transitional_2 +diamond_white_tiles: + texture: textures/tiles/diamond_white_tiles.png + mat_attrib: + texrepeat: "5 5" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# traditional_1 +varied_marble_tiles: + texture: textures/tiles/varied_marble_tiles.png + +# modern_1 +marble: + texture: textures/marble/marble_2.png + mat_attrib: + texrepeat: "0.75 0.75" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# modern_2 +black_marble_tiles: + texture: textures/tiles/black_marble_tiles.png + mat_attrib: + texrepeat: "0.75 0.75" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" + +# rustic +wood_planks: + texture: textures/wood/wood_planks_wall.png + mat_attrib: + texrepeat: "1 1" + texuniform: "true" + shininess: "0.01" + reflectance: "0.1" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/wall_accessory.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/wall_accessory.yaml new file mode 100644 index 0000000000000000000000000000000000000000..50365025b853716c1a94dbfbbd9f1ba074310dec --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fixture_registry/wall_accessory.yaml @@ -0,0 +1,15 @@ +default: + name: outlet + scale: 0.15 + xml: fixtures/accessories/outlets/simple_white + +light_switch: + name: light_switch + scale: 0.15 + xml: fixtures/accessories/light_switches/white_wide_switch + +pan_rack: + name: pan_rack + protrusion: 0.09 + scale: 0.7 + xml: fixtures/accessories/pan_racks/black_metal diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/four_doors/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/four_doors/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..31881124b1aea94f7e9939f8ea6f5cdc12293497 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/four_doors/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/full_height_doors/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/full_height_doors/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..b018bc0620863e98dfdad9d7d72e835786d6fc2d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/full_height_doors/model.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/modern/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/modern/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..426d1aab0acc1c3af64743c5cd5c04a495cf9bb5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/modern/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6a1940a2f7c7e3c002803b60b628903ebf4d9c1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/pack_1/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..8c44c70907907729ae1fbb4a3990e27390f974a8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/fridges/pack_2/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/bar_handle.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/bar_handle.xml new file mode 100644 index 0000000000000000000000000000000000000000..6120c2eb0187e48f44ae2560aa5c2829888e187c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/bar_handle.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/boxed_handle.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/boxed_handle.xml new file mode 100644 index 0000000000000000000000000000000000000000..d351f4231b453de08f6e6f5f9702ee32fac6eeb4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/boxed_handle.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/knob_handle.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/knob_handle.xml new file mode 100644 index 0000000000000000000000000000000000000000..aba1fc3d09a5eb0fac4c46c87b7b55625baa2f44 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/handles/knob_handle.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..2c3efee529f0219e0de5839274eee255029c389e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/pack_1/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..b628cad0ef5583e021fb29306b2b39ac42a9b93c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/pack_2/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/simple_silver/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/simple_silver/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e6cca2204aa7ebc1506f549060fc342486aa97a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/simple_silver/model.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/tall_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/tall_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..205055b96e7594c57fb754e3615fc8cae8a7085c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/hoods/tall_stainless/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/curved_door/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/curved_door/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..91609e037efff71f1b64019b9b134b5ca8475724 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/curved_door/model.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/gray/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/gray/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..08aa0f613ca6869d856131d7f57eb10a57856f82 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/gray/model.xml @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/hamilton_beach/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/hamilton_beach/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0de090118c20a006740868e82906ebefefd316af --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/hamilton_beach/model.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..28a85784437d230219fac15cfd036624839e4da4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/pack_1/model.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/pack_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/pack_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..626ecd726cc3424ca853a945ec838ed56abca535 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/pack_2/model.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/silver_black_metal/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/silver_black_metal/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..55bcd99639a9d5ba9e3db3b001268c3748678c5f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/silver_black_metal/model.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/square_with_button/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/square_with_button/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b24a755c7d3c462949291f739b6e6a440dcf6f2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/square_with_button/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/standard/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/standard/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..90bb3ff10a7a2bbe27a30b39e93c1f7eaee3199c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/microwaves/standard/model.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/beko/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/beko/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..26005c916247b64fc8a5a419a9971d6cb30cc331 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/beko/model.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/bosch/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/bosch/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..24ef5cfdba17667af3c8cbc4cef5349341382fc7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/bosch/model.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/gorenje/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/gorenje/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..10e42069905ee72716e692cae891ca868174b1e5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/gorenje/model.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/gorenje_dark/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/gorenje_dark/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..11557b9e55672f1247ee5c3b1825ddb2255fecbc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/gorenje_dark/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/pack_1/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/pack_1/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c5d0b69a5371865c20e1c2a9d6efb9d46eac0380 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/pack_1/model.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/westerfeld/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/westerfeld/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..16bd81b116c9a3490330a04e7874907f2fa14f18 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/ovens/westerfeld/model.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1.5_bins_storage_left_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1.5_bins_storage_left_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..017274b85d0af6e7293650cf5bc88a10613859a5 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1.5_bins_storage_left_stainless/model.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_storage_left_white_silver/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_storage_left_white_silver/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..e7eda8d0e6a0dd26b58d5b17a4aea89c24a794f4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_storage_left_white_silver/model.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_storage_right_dark/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_storage_right_dark/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..350a66bfbc3293e9475877ffb44d552a944030c4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_storage_right_dark/model.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_wide_top_handle/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_wide_top_handle/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..1819859ef088bffb8fabc6ca926fe45b3bccea5e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/1_bin_wide_top_handle/model.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_farmhouse/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_farmhouse/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..f25bb4c0c6d99b0cdf6cf885f4cfb65eb6fc4503 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_farmhouse/model.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..52ef7c497f505ab22af9d5475713565d31fb7513 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_stainless/model.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_storage_left_stainless/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_storage_left_stainless/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..50cde576a070a352ab8de313b095d520a627774a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/2_bins_storage_left_stainless/model.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/brown_metal_sink/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/brown_metal_sink/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..2a663f37012e93c57b33d3df94ee7c0637e3ed4d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/brown_metal_sink/model.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/concrete_sink/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/concrete_sink/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..197a99ea6429cb2647bb380cb5f3729d94f93a7d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/concrete_sink/model.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/white_sink/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/white_sink/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..cab35a8b43ad4d1c97f935384be6a5848f07d785 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/sinks/white_sink/model.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/basic_sleek_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/basic_sleek_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..f65c5d6ac459f543e28b6787a377b27cad009b94 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/basic_sleek_induc/model.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/coil_burners_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/coil_burners_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..d6693eedc0e8661ea6576cfa4ce2559571a1ff7b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/coil_burners_induc/model.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/dual_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/dual_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..577a61092f42081bd532c5f686403e35d0385b2f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/dual_gas/model.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/frigidaire_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/frigidaire_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..08aafb2502a1459da00ac2281dce0d9dc7ce73b0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/frigidaire_gas/model.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/simple_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/simple_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..db0473db39bc0c4909cb329d4e6cf586c0c8cfb7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/simple_gas/model.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/square_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/square_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0bf920637cc060cf1bfcfabfd4c8f98c5ba7ab15 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/square_gas/model.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/whirlpool_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/whirlpool_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..bb35220e37d1fc6ccf8e63a33be8e2a345a9775c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/whirlpool_induc/model.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/wolf_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/wolf_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..634f8a01d1a70813f0bba535255ef34ef43af0ba --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/wolf_gas/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/zline_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/zline_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..23e75e6626ae29ef03258300c59b8ea635c77b70 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stoves/zline_gas/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/alborz_top_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/alborz_top_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c51313fe09167b488cb124d815c9510392651103 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/alborz_top_gas/model.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/pack_1_top_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/pack_1_top_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..25a9767f714727f51b0ed1515cb6721937627e0e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/pack_1_top_gas/model.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/pack_1_top_induc/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/pack_1_top_induc/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6bd2372cb3967719ce6babf0e95b9a9217d302f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/pack_1_top_induc/model.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/sleek_silver_top_gas/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/sleek_silver_top_gas/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..409e3283ae93664db1b63c07db0238ac1d16d9cc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/stovetops/sleek_silver_top_gas/model.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/basic_popup/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/basic_popup/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..289860b79c5494d08b177720d333f191fdb29542 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/basic_popup/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/basic_popup_2/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/basic_popup_2/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..0aa1d417682beb4a692f4b459cff7f89578c2a75 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/basic_popup_2/model.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/boxy/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/boxy/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..e5917240b819321db80a299b4284ce9ff3c28363 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/boxy/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/fancy/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/fancy/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..f2126133d4cda53baea7ef8a7e968cb81c0c45e4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/fancy/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/vintage/model.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/vintage/model.xml new file mode 100644 index 0000000000000000000000000000000000000000..d137ea7bf1879d0e91cfd5013cedefacf5166f67 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/fixtures/toasters/vintage/model.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_large.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d19804c3d6b704361a0679c2105a60fe20e22b95 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_large.yaml @@ -0,0 +1,613 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [3.04, 1.5, 0.02] + pos: [3.04, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [3.04, 1.5, 0.1] + pos: [3.04, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [3, 1.5, 0.02] + pos: [0, -3, 1.5] + + - name: wall_left_backing + type: wall + + backing: true + wall_side: left + size: [3, 1.5, 0.1] + pos: [0, -3, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [3, 1.5, 0.02] + pos: [6.08, -3, 1.5] + + - name: wall_right_backing + type: wall + + backing: true + wall_side: right + size: [3, 1.5, 0.1] + pos: [6.08, -3, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + attach_to: wall + pos: [3.0, null, 1.2] + + - name: utensil_rack + type: utensil_rack + attach_to: wall + pos: [1.9, null, 1.15] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -1.8, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -1.9, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_right + pos: [null, -1.0, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_right + pos: [null, -2.5, 1.2] + + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [3.04, 3, 0.02] + pos: [3.04, -3, 0] + + - name: floor_backing + type: floor + + backing: true + size: [3.04, 3, 0.1] + pos: [3.04, -3, 0] + +# fixtures on the main wall +main_group: +# # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_main + type: counter + + size: [3, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_1 + type: counter + interior_obj: stovetop + + size: [1.5, 0.65, 0.92] + align_to: counter_main + side: right + obj_x_percent: 0.33 + obj_y_percent: 0.5 + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.88, 0.65, 0.92] + align_to: counter_1 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + pos: [0.325, -0.2, 1.85] + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: left + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_main + side: right + + - name: shelves_1 + type: open_cabinet + default_config_name: shelves + + size: [0.5, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + - name: shelves_2 + type: open_cabinet + default_config_name: shelves + + size: [0.6, 0.4, 0.92] + align_to: shelves_1 + side: right + offset: [1.1, 0, 0] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + - name: stack_4 + type: stack + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_4 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_1_main_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [0.35, 0.40] + pos: [0.20, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: stove + size: [0.5, 0.35] + pos: ["ref", 1.0] + rotation: [0, 0] + +# Group for island +front_group: + group_origin: [0, 0] + group_pos: [1.975, -4.075] + group_z_rot: 3.1415 + + bottom_row: + - name: counter_1 + type: counter + base_opening: [false, true] + + size: [2.55, 0.65, 0.92] + pos: [0, 0, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 0.40, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.40, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 0.40, 0.5] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.4] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: sink + type: sink + + - name: counter_1 + type: counter + interior_obj: sink + obj_x_percent: 0.5 + obj_y_percent: 0.15 + + size: [3, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: counter_corner_right + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.60, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + # Top row (cabinets and microwave) + top_row: + - name: window_group + type: framed_window + + size: [2, 0.05, 1.25] + num_windows: 3 + pos: [1.1, -0.25, 1.85] + ofs: [0.0, .24, -0.10] + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [2.7, -0.2, 1.85] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_1 + side: right + + counter_accessories: + - name: plant + type: plant + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: sink + loc: left + size: [0.4, 0.4] + pos: [null, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: sink + loc: right + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + +# # fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [5.9, -0.7] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: stack_left + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: left + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: left + + size: [0.5, 0.78, 2.26] + pos: [0.2, -0.21, 1.18] + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.78] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + + pos: [0.92, -0.21, 0.9] + interior_obj: fridge + + - name: fridge_top + type: hinge_cabinet + size: [fridge_housing, 0.78, null] + align_to: fridge_housing + alignment: front + side: top + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + - name: stack_right + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: right + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: right + + size: [0.5, 0.78, 2.26] + align_to: fridge_top + side: right + alignment: top_back + + - name: cab_top_corner + type: box + + size: [0.65, 0.78, 0.92] + align_to: stack_left + side: left + alignment: top_back + + - name: bottom_corner + type: box + + size: [0.05, 0.78, 0.89] + pos: [-0.075, -0.21, 0.445] + + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.78, 0.6] + # pos: [3.47, -0.21, 0.35] + align_to: stack_right + side: right + alignment: bottom_back + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.78, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.78, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.78, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.26 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + - name: side_bottom + type: stack + + levels: ["drawer", "drawer", "hinge_cabinet"] + percentages: [0.1327433628, 0.1327433628, 0.7345132744] + + configs: + hinge_cabinet: + panel_config: + handle_vpos: center + + size: [1, 0.78, 2.26] + align_to: bottom + side: right + alignment: bottom_back diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_small.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..582c3757987f18b965d544e4e5f62d72fba3989c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/G_shaped_small.yaml @@ -0,0 +1,520 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.2, 1.5, 0.02] + pos: [2.2, 0., 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [2.2, 1.5, 0.1] + pos: [2.2, 0., 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.5, 1.5, 0.02] + pos: [0, -2.5, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.5, 1.5, 0.1] + pos: [0, -2.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.5, 1.5, 0.02] + pos: [4.4, -2.5, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.5, 1.5, 0.1] + pos: [4.4, -2.5, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + attach_to: wall + pos: [4, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_left + pos: [null, -0.7, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -2.8, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -2.9, 1.2] + + - name: utensil_rack + type: utensil_rack + attach_to: wall_right + pos: [null, -0.5, 1.15] + + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.2, 2.5, 0.02] + pos: [2.2, -2.5, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.2, 2.5, 0.1] + pos: [2.2, -2.5, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_main + type: counter + + size: [3, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_main + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + pos: [0.325, -0.2, 1.85] + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: left + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: window_group + type: framed_window + + size: [1.45, 0.05, 1.25] + num_windows: 2 + ofs: [0.0, .20, -0.10] + align_to: cab_main + side: right + offset: [0.075, 0, 0] + + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: window_group + side: right + offset: [0.075, 0, 0] + + - name: cab_corner_3 + type: box + + size: [0.65, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + counter_accessories: + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + size: [1.0, 0.4] + pos: [1.0, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_main_main_group + size: [1.0, obj] + pos: [-1.0, 1.0] + rotation: [0, 0] + +# Group for island +front_group: + group_origin: [0, 0] + group_pos: [2.75, -3.15] + group_z_rot: 3.1415 + + bottom_row: + - name: counter_1 + type: counter + base_opening: [false, true] + overhang: 0 + + size: [1.9, 0.65, 0.92] + pos: [0, 0.025, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + - name: plant + type: plant + + placement: + fixture: counter_1_front_group + size: [1.0, 0.40] + pos: [0.0, 0.0] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.35, 0.40, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.40, 0.40, 0.5] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.4] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [0.5, 0.65, 0.92] + pos: [3.45, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_1 + side: left + alignment: top_back + + - name: counter_2 + type: counter + + size: [0.5, 0.65, 0.92] + align_to: stove + side: left + alignment: top_back + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + - name: fridge + type: fridge + + size: [null, null, 1.75] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_2 + side: left + alignment: bottom_back + interior_obj: fridge + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + configs: + single_cabinet: + orientation: left + + size: [0.5, 0.6, 0.84] + align_to: stove + side: left + alignment: top_back + offset: [0, 0.00, -0.03] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0, 0.00, -0.03] + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + pos: [3.45, -0.2, 1.85] + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: left + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + orientation: left + + size: [0.5, 0.4, 0.92] + align_to: microwave + alignment: bottom_back + side: left + + - name: cab_3 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, 0.55, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_left_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_2_left_group + size: [1.0, 0.35] + pos: [null, 1.0] + rotation: [0, 0] + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [4.4, -0.7] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_1 + type: counter + interior_obj: sink + + size: [2.1, 0.65, 0.92] + pos: [1.05, -0.325, 0.46] + # obj_x_percent: 0.476 + obj_x_percent: 0.238 + obj_y_percent: 0.5 + + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_1 + side: right + + - name: counter_corner_2 + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [0.5, -0.3, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_1 + side: right + alignment: top_back + + - name: stack_2 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.45, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0.5, -0.2, 1.85] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + counter_accessories: + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_right_group + sample_region_kwargs: + ref: sink + loc: "right" + size: [1.0, 0.40] + pos: ["ref", 1.0] + rotation: [0, 0] \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_large.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..79f9a8631d57f1a084a0fb63bdc2bf0136586d0e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_large.yaml @@ -0,0 +1,449 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.6, 1.5, 0.02] + pos: [2.6, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, false] + size: [2.6, 1.5, 0.1] + pos: [2.6, 0, 1.5] + + + - name: wall_left + type: wall + + wall_side: left + size: [2.95, 1.5, 0.02] + pos: [0, -2.95, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.95, 1.5, 0.1] + pos: [0, -2.95, 1.5] + + wall_accessories: + + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [2.9, null, 1.2] + + - name: outlet_2 + type: wall_accessory + + attach_to: wall_left + pos: [null, -1.0, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.3, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.4, null, 1.2] + + + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.6, 2.95, 0.02] + pos: [2.6, -2.95, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.6, 2.95, 0.1] + pos: [2.6, -2.95, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner_main + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_main + type: counter + + size: [1, 0.65, 0.92] + align_to: counter_corner_main + side: right + alignment: top_front + + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_1_right + type: counter + interior_obj: stovetop + + size: [2, 0.65, 0.92] + align_to: counter_main + side: right + obj_x_percent: 0.25 + obj_y_percent: 0.5 + + - name: fridge + type: fridge + + size: [null, null, 1.78] + + - name: fridge_housing + type: housing_cabinet + interior_obj: fridge + + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_1_right + side: right + alignment: bottom_back + + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [1.2, -0.2, 1.85] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1, 0.4, 0.92] + align_to: cab_main + side: right + offset: [1, 0, 0] + + - name: fridge_cab + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: toaster + type: toaster + + placement: + fixture: counter_1_right + sample_region_kwargs: + ref: shelves + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, 0.30] + pos: [null, 1.0] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.15] + group_z_rot: 1.5708 + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + orientation: left + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + pos: [0.7, -0.2, 1.85] + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_1 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.075, 0, 0] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: window_group + side: right + offset: [0.075, 0, 0.0] + + - name: cab_corner_3 + type: box + + size: [0.7, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_1_left + type: counter + interior_obj: sink + + size: [3, 0.65, 0.92] + pos: [1.95, -0.325, 0.46] + # positions sink directly underneath shelves + obj_x_percent: 0.5 + obj_y_percent: 0.5 + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1_left + side: right + + - name: island + type: counter + default_config_name: island + base_opening: [true, false] + + size: [2.45, 1.6, 0.92] + pos: [0.9, -2.95, 0.46] + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.6, 0.6] + pos: [0.05, -0.3, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.6, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: single_cabinet + orientation: left + panel_config: + handle_vpos: top + + size: [0.35, 0.6, 0.84] + pos: [0.625, -0.3, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_1 + side: right + alignment: top_back + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_left + sample_region_kwargs: + ref: sink + loc: right + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_left + sample_region_kwargs: + ref: sink + loc: "left" + size: [1.0, 0.30] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_corner_main + size: [0.40, "obj"] + pos: [0.0, 1.0] + # rotation: [-1.57, -1.57] + rotation: [0, 0] + + - name: plant + type: plant + + placement: + fixture: island + size: [1.0, 0.25] + pos: [null, null] + rotation: [0, 0] + +stool_group: + group_origin: [0, 0] + group_z_rot: -1.5708 + group_pos: [2.95, -3.25] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 0.7, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.7, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 0.7, 0.5] diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_small.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3f1a742bbc2b0c0b9894260c62911efa0a70aefb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/L_shaped_small.yaml @@ -0,0 +1,403 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.6, 1.5, 0.02] + pos: [2.6, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [false, true] + size: [2.6, 1.5, 0.1] + pos: [2.6, 0, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.6, 1.5, 0.02] + pos: [5.2, -2.6, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.6, 1.5, 0.1] + pos: [5.2, -2.6, 1.5] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.6, 2.6, 0.02] + pos: [2.6, -2.6, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.6, 2.6, 0.1] + pos: [2.6, -2.6, 0] + + # Wall accessories (e.g. outlets, clocks, paintings) + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [4.55, null, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [1.8, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [1.9, null, 1.2] + + - name: utensil_rack + type: utensil_rack + + attach_to: wall + pos: [4.05, null, 1.2] + + - name: outlet_2 + type: wall_accessory + + attach_to: wall_right + pos: [null, -3, 1.2] + + # - name: pan_rack + # type: wall_accessory + # config_name: pan_rack + + # attach_to: wall_right + # pos: [null, -2.3, 1.2] + +# fixtures on the main wall +main_group: + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [2.05, -0.2, 1.85] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + align_to: cab_main + side: right + alignment: back + + - name: cab_corner_2 + type: box + + size: [0.4, 0.25, 0.92] + align_to: cab_corner + side: front + alignment: right + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_main + type: counter + interior_obj: sink + + size: [3, 0.65, 0.92] + pos: [3.05, -0.325, 0.46] + obj_x_percent: 0.5 + obj_y_percent: 0.50 + + - name: counter_corner_main + type: counter + hollow: [false, false] + overhang: 0 + + size: [0.65, 0.6, 0.92] + align_to: counter_main + side: right + alignment: back + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + pos: [2.05, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + # Decorations on counters + counter_accessories: + - name: plant + type: plant + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_1_main_group + size: [1.0, 0.25] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_corner_main + # sample_region_kwargs: + # ref: cab_main + size: [obj.y, 0.30] + pos: [1.0, -1.0] + rotation: [-1.57, -1.57] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_corner_main + # sample_region_kwargs: + # ref: cab_main + size: [0.40, 0.30] + pos: [-1.0, 1.0] + rotation: [0, 0] + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [5.2, -0.65] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [0.5, 0.65, 0.92] + pos: [0.25, -0.325, 0.46] + + - name: counter_corner_left + type: counter + hollow: [false, false] + + size: [0.05, 0.65, 0.92] + align_to: counter_1 + side: left + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_1 + side: right + alignment: top_back + + - name: counter_2 + type: counter + + size: [1.7, 0.65, 0.92] + align_to: stove + side: right + alignment: top_back + + - name: fridge + type: fridge + + size: [null, null, 1.78] + + - name: fridge_housing + type: housing_cabinet + interior_obj: fridge + + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_2 + side: right + alignment: bottom_back + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + pos: [0.25, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0.0, 0.0, -0.03] + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.7, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + orientation: left + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + pos: [0.25, -0.2, 1.85] + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: right + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_micro + alignment: top_back + side: right + offset: [0.00, 0.0, 0.0] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.2, 0.4, 0.92] + align_to: cab_2 + side: right + + - name: cab_3 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + # Decorations on counters + counter_accessories: + - name: toaster + type: toaster + + placement: + fixture: counter_2 + size: [1.0, 0.40] + pos: [-1.0, 1.0] + rotation: [0, 0] + + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_2 + size: [0.60, 0.52] + pos: [1.0, 1.0] + rotation: [0, 0] + margin: 0.0 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_large.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5c8c6a8b93aca7ed1402b4c73644cc504669cf7f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_large.yaml @@ -0,0 +1,654 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [3.2, 1.5, 0.02] + pos: [3.2, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [3.2, 1.5, 0.1] + pos: [3.2, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.5, 1.5, 0.02] + pos: [0, -2.5, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.5, 1.5, 0.1] + pos: [0, -2.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.5, 1.5, 0.02] + pos: [6.4, -2.5, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.5, 1.5, 0.1] + pos: [6.4, -2.5, 1.5] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [3.2, 2.5, 0.02] + pos: [3.2, -2.5, 0] + + - name: floor_backing + type: floor + + backing: true + size: [3.2, 2.5, 0.1] + pos: [3.2, -2.5, 0] + + wall_accessories: + + - name: utensil_rack + type: utensil_rack + attach_to: wall_right + pos: [null, -2.0, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall + pos: [4.2, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall + pos: [4.1, null, 1.2] + + - name: outlet + type: wall_accessory + attach_to: wall_right + pos: [null, -0.6, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_right + pos: [null, -3.0, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_left + pos: [null, -2.4, 1.2] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: counter_1 + type: counter + + size: [2, 0.65, 0.92] + align_to: counter_corner + side: right + + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_main + type: counter + interior_obj: stovetop + + size: [3, 0.65, 0.92] + align_to: counter_1 + side: right + obj_x_percent: 0.33 + obj_y_percent: 0.5 + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_main + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.65, 0.4, 0.92] + pos: [0.325, -0.2, 1.85] + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: left + + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_1 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.075, 0, 0] + + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [0.95, 0.4, 0.92] + align_to: window_group + side: right + offset: [1.15, 0, 0] + + - name: cab_main + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: shelves + side: right + + - name: cab_corner_3 + type: box + + size: [0.75, 0.4, 0.92] + align_to: cab_main + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_2 + side: right + + - name: stack_4 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet"] + percentages: [1] + + configs: + hinge_cabinet: + open_top: true + panel_config: + handle_vpos: center + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_4 + side: right + + - name: stack_6 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_5 + side: right + + counter_accessories: + + - name: knife_block + type: knife_block + + placement: + fixture: counter_1_main_group + size: [1.0, obj] + pos: [1.0, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_main_group + size: [1.0, 0.40] + pos: [-1.0, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: shelves_main_group + size: [1.0, 0.35] + pos: [null, 1.0] + rotation: [0, 0] + +# Group for island +island_group: + group_origin: [0, 0] + group_pos: [3.2, -2.725] + group_z_rot: 3.1415 + + island: + - name: sink + type: sink + + - name: island + type: counter + default_config_name: island + # base_opening: [false, true] + interior_obj: sink + + size: [2.5, 1.55, 0.92] + pos: [0, 0, 0.46] + obj_x_percent: 0.5 + obj_y_percent: 0.15 + + island_bottom_row: + - name: island_stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.60, 0.84] + pos: [0, -0.425, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: island_stack_1 + side: left + alignment: top_back + + - name: island_panel_cab_right + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.1, 1.45, 0.84] + pos: [1.2, 0, 0.47] + + - name: island_cab_right + type: stack + + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.65, 0.6, 0.84] + align_to: island_stack_1 + side: right + + - name: island_panel_cab_left + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.1, 1.45, 0.84] + pos: [-1.2, 0, 0.47] + + - name: island_base_box + type: box + + size: [2.3, 0.1, 0.89] + pos: [0, 0.2, 0.445] + + island_accessories: + - name: plant + type: plant + + placement: + fixture: island_island_group + size: [0.4, 0.4] + rotation: [0, 0] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 0.70, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.70, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 0.70, 0.5] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -3.5] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [2, 0.65, 0.92] + pos: [1.8, -0.325, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.6, 0.6] + pos: [0.4, -0.3, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.6, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + pos: [1.05, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.5, 0.4, 0.92] + pos: [1.55, -0.2, 1.85] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: shelves + side: right + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [6.4, -0.7] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [2, 0.65, 0.92] + pos: [1, -0.325, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.75] + + - name: fridge_housing + type: housing_cabinet + interior_obj: fridge + + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_1 + side: right + alignment: bottom_back + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [0.5, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0.5, -0.2, 1.85] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: fridge_cab + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, 0.40, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_right_group + size: [1.0, 0.52] + pos: [-1.0, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: toaster + type: toaster + + placement: + fixture: counter_1_right_group + size: [1.0, 0.40] + pos: [1.0, 0] + rotation: [0, 0] + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_small.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..724494bb2276c57c93fca29770d327c1569c55e2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/U_shaped_small.yaml @@ -0,0 +1,483 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [2.2, 1.5, 0.02] + pos: [2.2, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [2.2, 1.5, 0.1] + pos: [2.2, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.25, 1.5, 0.02] + pos: [0, -2.25, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.25, 1.5, 0.1] + pos: [0, -2.25, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.25, 1.5, 0.02] + pos: [4.4, -2.25, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.25, 1.5, 0.1] + pos: [4.4, -2.25, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall_left + pos: [null, -1.0, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + + pos: [3.2, null, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_right + + pos: [null, -0.75, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -3.25, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left + pos: [null, -3.15, 1.2] + + - name: utensil_rack + type: utensil_rack + + attach_to: wall_left + pos: [null, -1.8, 1.2] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.2, 2.25, 0.02] + pos: [2.2, -2.25, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.2, 2.25, 0.1] + pos: [2.2, -2.25, 0] + +# fixtures on the main wall +main_group: + # Top row (cabinets and microwave) + top_row: + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + pos: [1.7, -0.25, 1.85] + num_windows: 3 + ofs: [0.0, .224, -0.10] + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [3.2, -0.2, 1.85] + + - name: cab_corner + type: box + + size: [0.7, 0.4, 0.92] + align_to: cab_main + side: right + alignment: back + + - name: cab_corner_2 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner + side: front + alignment: right + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_corner_left + type: counter + hollow: [false, false] + size: [0.70, 0.65, 0.92] + pos: [0.35, -0.325, 0.46] + + - name: sink + type: sink + + - name: counter_main + type: counter + interior_obj: sink + + size: [3, 0.65, 0.92] + align_to: counter_corner_left + side: right + obj_x_percent: 0.33 + obj_y_percent: 0.50 + + - name: counter_corner_right + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_main + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.84] + pos: [0.95, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [0.85, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + counter_accessories: + + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: plant + type: plant + + placement: + fixture: counter_corner_left_main_group + size: [0.40, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [4.4, -0.65] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [0.5, 0.65, 0.92] + pos: [0.3, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_1 + side: right + alignment: top_back + + - name: counter_2 + type: counter + + size: [0.5, 0.65, 0.92] + align_to: stove + side: right + alignment: top_back + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.78] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_2 + side: right + alignment: bottom_back + interior_obj: fridge + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: left + + # Cabinets built into counters + bottom_row_cabinets: + # - name: stack_1 + # type: stack + # # levels are specified from bottom up + # levels: ["hinge_cabinet", ["drawer", "drawer"]] + # percentages: [0.75, 0.25] + + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + configs: + single_cabinet: + panel_config: + handle_vpos: top + orientation: left + + size: [0.5, 0.6, 0.84] + pos: [0.3, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0.0, 0.00, -0.03] + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + default_config_name: cab_top + + orientation: left + + size: [0.5, 0.4, 0.92] + pos: [0.3, -0.2, 1.85] + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: right + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + + size: [0.5, 0.4, 0.92] + align_to: microwave + alignment: bottom_back + side: right + + - name: cab_3 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, 0.55, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + counter_accessories: + - name: knife_block + type: knife_block + + placement: + fixture: counter_1_right_group + size: [1.0, "obj"] + pos: [null, 1.0] + rotation: [0, 0] + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_2_right_group + size: [1.0, 0.35] + pos: [null, 1.0] + rotation: [0, 0] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -3] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [2.8, 0.65, 0.92] + pos: [0.9, -0.325, 0.46] + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [true, false] + + size: [0.1, 0.65, 0.92] + align_to: counter_1 + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + pos: [-0.1, -0.3, 0.47] + + - name: stack_2 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_2 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0, -0.2, 1.85] + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.3, 0.4, 0.92] + align_to: cab_1 + side: right + + counter_accessories: + + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: cab_1_left_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_left_group + sample_region_kwargs: + ref: shelves_left_group + size: [1.0, 0.40] + pos: [null, 0.5] + rotation: [0, 0] diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/galley.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/galley.yaml new file mode 100644 index 0000000000000000000000000000000000000000..46dfb3c3464ccc66abc65f30ae34fab8304757ee --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/galley.yaml @@ -0,0 +1,384 @@ +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [1.6, 1.5, 0.02] + pos: [1.6, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [1.6, 1.5, 0.1] + pos: [1.6, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.8, 1.5, 0.02] + pos: [0, -2.8, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [2.8, 1.5, 0.1] + pos: [0, -2.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.8, 1.5, 0.02] + pos: [3.2, -2.8, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [2.8, 1.5, 0.1] + pos: [3.2, -2.8, 1.5] + + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall_left + pos: [null, -2.6, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall_right + + pos: [null, -3, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_right + + pos: [null, -1.5, 1.2] + + - name: untensil_rack + type: utensil_rack + attach_to: wall_left + + pos: [null, -3.3, 1.15] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_right + pos: [null, -3.5, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_right + pos: [null, -3.6, 1.2] + + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [1.6, 2.8, 0.02] + pos: [1.6, -2.8, 0] + + - name: floor_backing + type: floor + + backing: true + size: [1.6, 2.8, 0.1] + pos: [1.6, -2.8, 0] + +# fixtures on the left wall +left_group: + group_origin: [0, 0] + group_pos: [0, -4.05] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.78] + pos: [3.58, -0.43, 0.89] + + - name: sink + type: sink + + - name: counter + type: counter + interior_obj: sink + + size: [3.8, 0.65, 0.92] + align_to: fridge + side: left + alignment: bottom_back + # pos: [2.15, -0.325, 0.46] + obj_x_percent: 0.735 + obj_y_percent: 0.5 + + + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [-0.19, -0.2, 1.85] + + - name: cab_2 + type: open_cabinet + default_config_name: shelves + + size: [0.8, 0.4, 0.92] + align_to: cab_1 + side: right + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_2 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.075, 0, 0] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + pos: [-0.27, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [0.85, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + - name: stack_4 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.84] + align_to: stack_3 + side: right + + counter_accesories: + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_left_group + sample_region_kwargs: + ref: sink + size: [0.50, 0.25] + pos: ["ref", 1.0] + rotation: [0, 0] + +# fixtures on the right wall +main_group: + group_origin: [0, 0] + group_pos: [3.2, 0] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_main + type: counter + + size: [2, 0.65, 0.92] + pos: [1.0, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_main + side: right + alignment: top_back + + - name: counter_right + type: counter + + size: [2, 0.65, 0.92] + align_to: stove + alignment: top_back + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [0.50, -0.2, 1.85] + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_main + side: right + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_1 + side: right + alignment: bottom_back + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.4, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: microwave + alignment: bottom_back + side: right + + - name: cab_3 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_2 + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [0.5, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0, 0.0, -0.03] + + - name: stack_4 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_1_main_group + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [1.0, 0.30] + pos: [null, 1.0] + rotation: [0, 0] + + - name: toaster + type: toaster + + placement: + fixture: counter_right_main_group + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_left_group + sample_region_kwargs: + ref: cab_1_left_group + size: [1, obj] + pos: [null, 1.0] + rotation: [0, 0] \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/one_wall_large.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/one_wall_large.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f8309b25936b47b221f6b54d5573104af60ca4c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/one_wall_large.yaml @@ -0,0 +1,424 @@ +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [3.15, 1.5, 0.02] + pos: [2.15, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + # whether backing is extended on the left/right side + backing_extended: [true, true] + size: [3.15, 1.5, 0.1] + pos: [2.15, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [2.5, 1.5, 0.02] + pos: [-1, -2.5, 1.5] + + - name: wall_left_backing + type: wall + + backing: true + wall_side: left + size: [2.5, 1.5, 0.1] + pos: [-1, -2.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.5, 1.5, 0.02] + pos: [5.3, -2.5, 1.5] + + - name: wall_right_backing + type: wall + + backing: true + wall_side: right + size: [2.5, 1.5, 0.1] + pos: [5.3, -2.5, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [3.15, 2.5, 0.02] + pos: [2.15, -2.5, 0] + + - name: floor_backing + type: floor + + backing: true + size: [3.15, 2.5, 0.1] + pos: [2.15, -2.5, 0] + + # Wall accessories (e.g. outlets, clocks, paintings) + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [3.8, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + + pos: [2, null, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.5, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [3.6, null, 1.2] + + - name: utensil_rack + type: utensil_rack + + attach_to: wall + pos: [2.75, null, 1.3] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_main + type: counter + + size: [1, 0.65, 0.92] + pos: [1.75, -0.325, 0.46] + + - name: stovetop + type: stovetop + + - name: counter_1 + type: counter + interior_obj: stovetop + + size: [1, 0.65, 0.92] + align_to: counter_main + side: right + obj_x_percent: 0.5 + obj_y_percent: 0.5 + + - name: counter_2 + type: counter + + size: [1.8, 0.65, 0.92] + align_to: counter_1 + side: right + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.78, 0.6] + pos: [0.85, -0.39, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, 0.68] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.78, 0.70] + padding: [null, [-0.01, null], null] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.78, 0.55] + padding: [null, [-0.01, null], null] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.78, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + - name: fridge + type: fridge + + size: [0.9, 0.8, 1.88] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: micro_housing + side: left + alignment: top_back + interior_obj: fridge + + - name: fridge_top + type: hinge_cabinet + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + alignment: front + side: top + stack_height: 2.6 + stack_fixtures: ["fridge_housing"] + + # Top row (cabinets and microwave) + top_row: + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + pos: [1.75, -0.2, 1.85] + + - name: hood + type: hood + size: [stovetop, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + alignment: back + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [0.8, 0.4, 0.92] + align_to: cab_main + side: right + offset: [1, 0, 0] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + align_to: shelves + side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.75, -0.3, 0.47] + + - name: stack_4 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_4 + side: right + + - name: stack_6 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + align_to: stack_5 + side: right + + # Decorations on counters + counter_accessories: + - name: knife_block + type: knife_block + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, obj] + pos: [null, 1.0] + rotation: [0, 0] + + - name: toaster + type: toaster + + placement: + fixture: counter_2 + sample_region_kwargs: + ref: shelves + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_2 + sample_region_kwargs: + ref: shelves + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_2 + sample_region_kwargs: + ref: cab_2 + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + +island_group: + group_origin: [0, 0] + group_pos: [2.75, -1.65] + group_z_rot: 3.1415 + + island: + - name: sink + type: sink + + - name: island_counter + type: counter + default_config_name: island + # base_opening: [false, true] + interior_obj: sink + + size: [2.75, 1.4, 0.92] + pos: [0, 1.0, 0.46] + obj_x_percent: 0.5 + obj_y_percent: 0.15 + + island_bottom_row: + - name: island_stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.60, 0.84] + pos: [0, 0.63, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: island_stack_1 + side: right + alignment: top_back + + - name: island_panel_cab_right + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.2, 1.35, 0.84] + pos: [1.25, 1.0, 0.47] + + - name: island_cab_left + type: stack + + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.65, 0.6, 0.84] + align_to: island_stack_1 + side: left + + - name: island_panel_cab_left + type: stack + + levels: ["panel_cabinet"] + percentages: [1] + + configs: + panel_cabinet: + solid_body: true + panel_type: "slab" + + size: [0.2, 1.35, 0.84] + pos: [-1.25, 1.0, 0.47] + + - name: island_base_box + type: box + + size: [2.35, 0.1, 0.89] + pos: [0, 1.2, 0.445] + + # island_accessories: + # - name: plant + # type: plant + + # placement: + # fixture: island_counter + # # sample_region_kwargs: + # # ref: cab_1 + # size: [0.40, 0.40] + # # pos: [null, 1.0] + # rotation: [0, 0] + + chairs: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.65, 1.6, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 1.6, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.65, 1.6, 0.5] diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/one_wall_small.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/one_wall_small.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0944a4a7e2ec03e2f5d1b76630916678fc60906d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/one_wall_small.yaml @@ -0,0 +1,305 @@ +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.75, 1.5, 0.02] + pos: [2.75, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [2.75, 1.5, 0.1] + pos: [2.75, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.5, 1.5, 0.02] + pos: [0, -1.5, 1.5] + + - name: wall_left_backing + type: wall + + wall_side: left + backing: true + size: [1.5, 1.5, 0.1] + pos: [0, -1.5, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.5, 1.5, 0.02] + pos: [5.5, -1.5, 1.5] + + - name: wall_right_backing + type: wall + + wall_side: right + backing: true + size: [1.5, 1.5, 0.1] + pos: [5.5, -1.5, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.75, 1.50, 0.02] + pos: [2.75, -1.50, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.75, 1.50, 0.1] + pos: [2.75, -1.50, 0] + + # Wall accessories (e.g. outlets, clocks, paintings) + wall_accessories: + - name: outlet + type: wall_accessory + + attach_to: wall + pos: [4.1, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + + pos: [2, null, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [2.5, null, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + + attach_to: wall + pos: [2.61, null, 1.2] + + # - name: pan_rack + # type: wall_accessory + # config_name: pan_rack + + # attach_to: wall + # pos: [1.25, null, 1.325] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_main + type: counter + interior_obj: sink + + size: [2.5, 0.65, 0.92] + pos: [1.5, -0.325, 0.46] + + obj_x_percent: 0.40 + obj_y_percent: 0.50 + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_main + side: right + alignment: top_back + + - name: counter_right + type: counter + + size: [0.7, 0.65, 0.92] + align_to: stove + alignment: top_back + side: right + + - name: fridge + type: fridge + + size: [null, null, 1.75] + + - name: fridge_housing + type: housing_cabinet + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + align_to: counter_right + side: right + alignment: bottom_back + interior_obj: fridge + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: single_cabinet + orientation: left + default_config_name: cab_top + + size: [0.5, 0.40, 0.92] + pos: [0.5, -0.20, 1.85] + + - name: cab_2 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + align_to: cab_1 + side: right + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.40, 0.92] + align_to: cab_2 + side: right + + - name: microwave + type: microwave + size: [stove, 0.45, null] + + align_to: cab_main + alignment: back_bottom + side: right + + - name: cab_micro + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [microwave, 0.40, null] + align_to: microwave + side: top + alignment: back + stack_height: 0.92 + stack_fixtures: ["microwave"] + + - name: cab_3 + type: open_cabinet + default_config_name: shelves + num_shelves: 3 + + size: [0.7, 0.40, 0.92] + align_to: microwave + side: right + alignment: bottom_back + + - name: cab_4 + type: hinge_cabinet + handle_type: knob + default_config_name: cab_top_small + + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + side: top + alignment: back + stack_height: 2.31 + stack_fixtures: ["fridge_housing"] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.60, 0.84] + pos: [0.5, -0.30, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.60, 0.84] + align_to: stack_1 + side: right + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_2 + side: right + alignment: top_back + + - name: stack_3 + type: stack + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.60, 0.84] + align_to: dishwasher + side: right + alignment: top_back + + - name: stack_4 + type: stack + + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.7, 0.60, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0.0, 0.0, -0.03] + + # Decorations on counters + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_1 + size: [1.0, 0.52] + pos: [null, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: toaster + type: toaster + + placement: + fixture: counter_right + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + + - name: knife_block + type: knife_block + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, obj] + pos: [null, 1.0] + rotation: [0, 0] + + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_main + sample_region_kwargs: + ref: cab_main + size: [1.0, 0.25] + pos: [null, 1.0] + rotation: [0, 0] diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/playground.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/playground.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b9b50003ddcfd9b0977df1cab066681c89ad7a8d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/playground.yaml @@ -0,0 +1,206 @@ +# version of one wall large arena, with integrated stove and microwave + + +# walls, floor +room: + walls: + - name: wall + type: wall + + size: [2.65, 1.5, 0.02] + pos: [2.65, 0, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.8, 1.5, 0.02] + pos: [0, -1.8, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [1.8, 1.5, 0.02] + pos: [5.3, -1.8, 1.5] + + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.65, 1.8, 0.02] + pos: [2.65, -1.8, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: stovetop + type: stovetop + + size: [null, 0.55, null] + + - name: counter_main + type: counter + + size: [4, 0.65, 1] + pos: [3.25, -0.325, 0.5] + obj_x_percent: 0.625 + obj_y_percent: 0.5 + + interior_obj: stovetop + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + + size: [1, 0.45, 1.0] + pos: [1.75, -0.25, 2.10] + + - name: cab_main + type: hinge_cabinet + + size: [1, 0.45, 1.0] + align_to: cab_1 + side: right + + - name: hood + type: hood + size: [stovetop, 0.60, null] + offset: [0, 0, 0.75] + + align_to: stovetop + side: top + + # - name: cab_2 + # type: single_cabinet + + # size: [0.5, 0.45, 0.75] + # align_to: microwave + # alignment: bottom_back + # side: right + + # - name: cab_3 + # type: open_cabinet + # default_config_name: shelves + # num_shelves: 3 + + # size: [1.5, 0.45, 0.75] + # align_to: cab_2 + # side: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.5, 0.6, 0.92] + pos: [1.5, -0.30, 0.51] + + - name: stack_2 + type: stack + levels: ["single_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.5, 0.6, 0.92] + align_to: stack_1 + side: right + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.92] + align_to: stack_2 + side: right + + - name: stack_4 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.92] + align_to: stack_3 + side: right + + - name: stack_5 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.92] + align_to: stack_4 + side: right + + + wall_stack: + - name: bottom + type: stack + # levels are specified from bottom up + levels: ["drawer", "drawer"] + percentages: [0.50, 0.50] + size: [0.8, 0.6, 0.60] + pos: [0.85, -0.30, 0.35] + + - name: oven + type: oven + # default_config_name: integrated + size: [0.75, 0.60, null] + + - name: oven_housing + type: housing_cabinet + size: [0.8, 0.6, 0.70] + align_to: bottom + alignment: front + side: top + interior_obj: oven + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + align_to: oven_housing + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.55 + stack_fixtures: ["bottom", "oven_housing", "micro_housing"] + + + +island_group: + group_origin: [0, 0] + group_pos: [2.65, -1.65] + group_z_rot: 3.1415 + + island: + - name: sink + type: sink + + - name: island + type: counter + default_config_name: island + hollow: [false, false] + interior_obj: sink + + size: [3, 1.2, 1] + pos: [0, 0.75, 0.5] + obj_x_percent: 0.5 + obj_y_percent: 0.15 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/wraparound.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/wraparound.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b77315277170cd9a0ce4cfd6c1cab56641ce9697 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_layouts/wraparound.yaml @@ -0,0 +1,653 @@ +# walls, floor +room: + # Walls + walls: + - name: wall + type: wall + + size: [3.1, 1.5, 0.02] + pos: [2.8, 0, 1.5] + + - name: wall_backing + type: wall + + backing: true + backing_extended: [true, true] + size: [3.1, 1.5, 0.1] + pos: [2.8, 0, 1.5] + + - name: wall_front + type: wall + + wall_side: front + size: [1.15, 1.5, 0.02] + pos: [0.85, -3.4, 1.5] + + - name: wall_front_backing + type: wall + + backing: true + backing_extended: [true, false] + wall_side: front + size: [1.15, 1.5, 0.1] + pos: [0.85, -3.4, 1.5] + + - name: wall_left + type: wall + + wall_side: left + size: [1.7, 1.5, 0.02] + pos: [-0.3, -1.7, 1.5] + + - name: wall_left_backing + type: wall + + backing: true + wall_side: left + size: [1.7, 1.5, 0.1] + pos: [-0.3, -1.7, 1.5] + + - name: wall_left_2 + type: wall + + wall_side: left + size: [0.525, 1.5, 0.02] + pos: [2.075, -3.975, 1.5] + + - name: wall_2_left_backing + type: wall + + backing: true + wall_side: left + size: [0.525, 1.5, 0.1] + pos: [2.075, -3.975, 1.5] + + - name: wall_right + type: wall + + wall_side: right + size: [2.25, 1.5, 0.02] + pos: [5.9, -2.25, 1.5] + + - name: wall_right_backing + type: wall + + backing: true + wall_side: right + size: [2.25, 1.5, 0.1] + pos: [5.9, -2.25, 1.5] + + wall_accessories: + - name: utensil_rack + type: utensil_rack + attach_to: wall + pos: [3.9, null, 1.15] + + - name: outlet + type: wall_accessory + attach_to: wall + pos: [1.9, null, 1.2] + + - name: outlet_2 + type: wall_accessory + attach_to: wall + pos: [5.4, null, 1.2] + + - name: outlet_3 + type: wall_accessory + attach_to: wall_left + pos: [null, -1.6, 1.2] + + - name: light_switch + type: wall_accessory + config_name: light_switch + attach_to: wall_left_2 + pos: [null, -3.8, 1.2] + + - name: light_switch_2 + type: wall_accessory + config_name: light_switch + attach_to: wall_left_2 + pos: [null, -3.7, 1.2] + + # Floor + floor: + - name: floor + type: floor + + # position such that the top left corner is (0, 0) + size: [2.95, 1.425, 0.02] + pos: [2.95, -1.425, 0] + + - name: floor_backing + type: floor + + backing: true + size: [2.95, 1.425, 0.1] + pos: [2.95, -1.425, 0] + + - name: floor_front + type: floor + + # position such that the top left corner is (0, 0) + size: [1.9125, 0.7875, 0.02] + pos: [3.9875, -3.7125, 0] + + - name: floor_front_backing + type: floor + + backing: true + size: [1.9125, 0.7875, 0.1] + pos: [3.9875, -3.7125, 0] + +# fixtures on the main wall +main_group: + # Bottom row (counters and stoves) + bottom_row: + - name: counter_main + type: counter + + size: [3, 0.65, 0.92] + pos: [1.2, -0.325, 0.46] + + - name: stove + type: stove + + size: [null, 0.66, null] + align_to: counter_main + side: right + alignment: top_back + + - name: counter_1 + type: counter + + size: [1.8, 0.65, 0.92] + align_to: stove + side: right + alignment: top_front + + - name: counter_corner_2 + type: counter + hollow: [false, false] + + size: [0.70, 0.65, 0.92] + align_to: counter_1 + side: right + + # Top row (cabinets and microwave) + top_row: + - name: cab_corner + type: box + + size: [0.25, 0.4, 0.92] + pos: [0.525, -0.2, 1.85] + + - name: cab_main + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_corner + side: right + + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + align_to: cab_main + side: right + + - name: hood + type: hood + size: [stove, 0.6, null] + offset: [0, 0, 0.75] + + align_to: stove + side: top + + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [1.65, 0.4, 0.92] + offset: [0.95, 0, 0.0] + align_to: cab_1 + side: right + + - name: cab_corner_3 + type: box + + size: [0.65, 0.4, 0.92] + align_to: shelves + side: right + + - name: cab_corner_4 + type: box + + size: [0.4, 0.3, 0.92] + align_to: cab_corner_3 + side: front + alignment: right + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [1.2, -0.3, 0.47] + + - name: stack_2 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stack_1 + side: right + + - name: right_corner_box + type: box + + size: [0.3, 0.6, 0.84] + align_to: stack_1 + side: left + + - name: stack_3 + type: stack + levels: ["hinge_cabinet", ["drawer", "drawer"]] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + align_to: stove + side: right + alignment: top_back + offset: [0, 0, -0.03] + + - name: stack_4 + type: stack + levels: ["drawer", "drawer", "drawer", "drawer"] + percentages: [0.25, 0.25, 0.25, 0.25] + + size: [0.8, 0.6, 0.84] + align_to: stack_3 + side: right + + counter_accessories: + - name: coffee_machine + type: coffee_machine + + placement: + fixture: counter_1_main_group + size: [1.0, 0.52] + pos: [1.0, 1.0] + rotation: [0, 0] + margin: 0.0 + + - name: utensil_holder + type: utensil_holder + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: stove + size: [0.6, 0.30] + pos: ["ref", 1.0] + rotation: [0, 0] + + - name: plant + type: plant + + placement: + fixture: counter_corner_2_main_group + size: [0.4, 0.4] + pos: [0.0, -1.0] + rotation: [0, 0] + + - name: toaster + type: toaster + + placement: + fixture: counter_main_main_group + sample_region_kwargs: + ref: cab_main_main_group + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + +# fixtures on the left wall +left_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -4.4] + group_z_rot: 1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: fridge + type: fridge + + size: [0.9, 0.72, 1.75] + + - name: fridge_housing + type: housing_cabinet + + pos: [2.7, -0.05, 0.875] + padding: [[0.02, 0.02], [-0.04, 0.02], [0, 0.02]] + interior_obj: fridge + + - name: fridge_top + type: hinge_cabinet + size: [fridge_housing, fridge_housing, null] + align_to: fridge_housing + alignment: front + side: top + stack_height: 2.32 + stack_fixtures: ["fridge_housing"] + + - name: stack_left + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: left + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: left + + size: [0.58, 0.7, 2.32] + align_to: fridge_housing + side: left + alignment: bottom_back + + - name: stack_right + type: stack + levels: ["single_cabinet", "single_cabinet"] + percentages: [0.5, 0.5] + + configs: + single_cabinet_1: + panel_config: + handle_vpos: top + orientation: right + + single_cabinet_2: + panel_config: + handle_vpos: bottom + orientation: right + + size: [0.58, 0.7, 2.32] + align_to: fridge_housing + side: right + alignment: bottom_back + + - name: box_left_top + type: box + size: [0.65, 0.7, 0.92] + + align_to: stack_left + side: left + alignment: top_back + + - name: box_left_bottom + type: box + size: [0.65, 0.7, 0.89] + + align_to: stack_left + side: left + alignment: bottom_back + + - name: box_right_top + type: box + size: [0.65, 0.7, 0.92] + + align_to: stack_right + side: right + alignment: top_back + + - name: box_right_bottom + type: box + size: [0.65, 0.7, 0.89] + + align_to: stack_right + side: right + alignment: bottom_back + + +# fixtures on the right wall +right_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [5.9, 1.55] + group_z_rot: -1.5708 + + # Bottom row (counters and stoves) + bottom_row: + - name: sink + type: sink + + - name: counter_1 + type: counter + interior_obj: sink + + size: [1.99, 0.65, 0.92] + pos: [3.255, -0.325, 0.46] + obj_x_percent: 0.75 + obj_y_percent: 0.15 + + - name: counter_corner + type: counter + hollow: [false, false] + half_top: [false, true] + + size: [0.10, 0.65, 0.92] + align_to: counter_1 + side: left + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", "panel_cabinet"] + percentages: [0.75, 0.25] + + size: [1, 0.6, 0.84] + pos: [3.75, -0.3, 0.47] + + - name: dishwasher + type: dishwasher + + size: [0.65, 0.6, 0.89] + align_to: stack_1 + side: left + alignment: top_back + + - name: stack_2 + type: stack + levels: ["single_cabinet"] + percentages: [1] + + size: [0.35, 0.6, 0.84] + align_to: dishwasher + side: left + alignment: top_back + + # Top row (cabinets and microwave) + top_row: + - name: cab_1 + type: hinge_cabinet + default_config_name: cab_top + + size: [1, 0.4, 0.92] + pos: [3.25, -0.2, 1.85] + + - name: cab_2 + type: single_cabinet + default_config_name: cab_top + orientation: left + + size: [0.5, 0.4, 0.92] + align_to: cab_1 + side: left + + - name: window_group + type: framed_window + + size: [1.85, 0.05, 1.25] + num_windows: 3 + align_to: cab_1 + side: right + ofs: [0.0, .20, -0.10] + offset: [0.225, 0, 0] + + counter_accessories: + - name: paper_towel + type: paper_towel + + placement: + fixture: counter_1_right_group + sample_region_kwargs: + ref: sink + loc: left + size: [1.0, 0.40] + pos: [null, 1.0] + rotation: [0, 0] + +# fixtures on the left wall +front_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [0, -3.4] + group_z_rot: 3.1415 + + # Bottom row (counters and stoves) + bottom_row: + - name: counter_1 + type: counter + + size: [1.575, 0.65, 0.92] + pos: [-0.4875, -0.325, 0.46] + + # Cabinets built into counters + bottom_row_cabinets: + - name: stack_1 + type: stack + levels: ["hinge_cabinet", "drawer"] + percentages: [0.75, 0.25] + + size: [0.875, 0.6, 0.84] + pos: [-0.8375, -0.3, 0.47] + + # Top row (cabinets and microwave) + top_row: + - name: shelves + type: open_cabinet + default_config_name: shelves + + size: [0.9, 0.4, 0.92] + pos: [-0.85, -0.2, 1.85] + + # - name: cab_corner + # type: box + + # size: [0.4, 0.4, 0.92] + # align_to: shelves + # side: right + + # - name: cab_corner_2 + # type: box + + # size: [0.4, 0.3, 0.92] + # align_to: cab_corner + # side: front + # alignment: right + + wall_stack: + - name: bottom + type: stack + levels: ["drawer", "drawer"] + percentages: [0.5, 0.5] + size: [0.8, 0.6, 0.6] + pos: [-1.675, -0.3, 0.35] + + - name: cab_middle + type: hinge_cabinet + size: [0.8, 0.6, 0.60] + align_to: bottom + alignment: front + panel_config: + handle_vpos: center + side: top + + - name: microwave + type: microwave + # default_config_name: integrated + size: [0.75, 0.50, null] + + - name: micro_housing + type: housing_cabinet + size: [0.8, 0.6, 0.55] + padding: [null, [-0.01, null], null] + align_to: cab_middle + alignment: front + side: top + interior_obj: microwave + + - name: top + type: hinge_cabinet + size: [0.8, 0.6, null] + align_to: micro_housing + alignment: front + side: top + stack_height: 2.45 + stack_fixtures: ["bottom", "cab_middle", "micro_housing"] + +island_group: + # rotation and displacement of the group + group_origin: [0, 0] + group_pos: [4, -2.55] + group_z_rot: 3.1415 + + # Bottom row (counters and stoves) + bottom_row: + - name: island + type: counter + default_config_name: island + base_opening: [false, true] + overhang: 0 + + size: [2.25, 1, 0.92] + pos: [-0.8, 0.65, 0.46] + +stool_group: + group_origin: [0, 0] + group_z_rot: 3.1415 + group_pos: [4.8, -3.15] + + stools: + - name: stool_1 + type: stool + + # place flush to ground + pos: [-0.6, 0.5, 0.5] + + - name: stool_2 + type: stool + + # place flush to ground + pos: [0.0, 0.5, 0.5] + + - name: stool_3 + type: stool + + # place flush to ground + pos: [0.6, 0.5, 0.5] diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/coastal.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/coastal.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9ffacaa0e3a3abcbf92fbf0ea4f0940546f1e3c2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/coastal.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [shaker, dark_blue, handle_boxed, handle_brass] + shelves: light_wood_planks_shelves + cab_top: [divided_window, dark_blue, handle_boxed, handle_brass] + cab_top_small: [full_window_clear, dark_blue, handle_brass] +counter: + default: dark_blue_base_marble_top + island: dark_blue_base_marble_top +floor: flower_ceramic_tiles +wall: white_square_tiles + +# fixtures using models +sink: concrete_sink +stove: frigidaire_gas +microwave: hamilton_beach +oven: pack_1 +stovetop: pack_1_top_induc +hood: pack_2 +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +toaster: basic_popup_2 +paper_towel: holder_4 +stool: stool_1_1 +knife_block: knife_block_1 +utensil_rack: black_plastic +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/farmhouse.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/farmhouse.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c7e889b0bb3a98537a8b7449f6a6a06ff457e302 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/farmhouse.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [shaker, gray_wood_grain] + cab_top: [divided_window, gray_wood_grain] + cab_top_small: [full_window_clear, gray_wood_grain] + shelves: warm_white +counter: + default: gray_wood_base_marble_top + island: gray_wood_base_marble_top +floor: gray_wood +wall: white_bricks + +# fixtures using models +sink: concrete_sink +stove: frigidaire_gas +microwave: gray +oven: beko +stovetop: pack_1_top_induc +hood: pack_1 +fridge: full_height_doors +dishwasher: basic_stainless + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup_2 +knife_block: light_wood_2 +paper_towel: holder_4 +stool: rattan_stool +utensil_rack: metal +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/industrial.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/industrial.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7449082482a7d737ef736d89d598af3cedd72be3 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/industrial.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [gray, shaker] + shelves: dark_wood_planks_shelves +counter: + default: gray_base_marble_top + island: gray_base_tiled_wood_top +floor: concrete_tiles +wall: red_bricks +openings_wall: default + +# fixtures using models +sink: concrete_sink +stove: basic_sleek_induc +microwave: pack_1 +oven: pack_1 +stovetop: sleek_silver_top_gas +hood: simple_silver +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +toaster: boxy +paper_towel: holder_2 +utensil_rack: metal +knife_block: light_wood_3 +stool: rattan_stool +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/mediterranean.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/mediterranean.yaml new file mode 100644 index 0000000000000000000000000000000000000000..752022347862fb68be8357fffa56b766bb2cab99 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/mediterranean.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: warm_wood_grain + cab_top: [divided_window, warm_wood_grain] + cab_top_small: [full_window_clear, warm_wood_grain] + shelves: gray +counter: + default: wood_base_dark_marble_top + island: cream_base_wood_parquet_top +floor: orange_tiles +wall: orange_square_tiles + +# fixtures using models +sink: 1_bin_wide_top_handle +stove: square_gas +microwave: hamilton_beach +oven: westerfeld +stovetop: sleek_silver_top_gas +hood: pack_2 +fridge: four_doors +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +toaster: boxy +knife_block: light_wood_2 +paper_towel: holder_4 +stool: rattan_stool +utensil_rack: black_plastic +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/modern_1.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/modern_1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4824d7e234594970533423211845bce2d87d3125 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/modern_1.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [slab, blue_gray, handle_dark_gray] + shelves: light_wood_parquet +counter: + default: blue_gray_base_white_top + island: blue_gray_base_white_top +floor: light_wood_2 +wall: marble + +# fixtures using models +sink: 2_bins_stainless +stove: square_gas +microwave: pack_1 +oven: pack_1 +stovetop: sleek_silver_top_gas +hood: pack_1 +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +paper_towel: holder_2 +stool: rattan_stool +toaster: vintage +knife_block: light_wood_3 +utensil_rack: metal_cg_2 +utensil_holder: holder_2 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/modern_2.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/modern_2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dce03ba708da9ce836c51204f4daba78c6df0fa0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/modern_2.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [dark_gray, handle_brass, handle_boxed] + cab_top: [full_window_blurred, dark_gray, handle_brass, handle_boxed] + cab_top_small: [full_window_blurred, dark_gray, handle_brass, handle_boxed] + shelves: wood_grain_shelves +counter: + default: white_base_marble_top_3 + island: white_base_marble_top_3 +floor: wood +wall: black_marble_tiles + +# fixtures using models +sink: 1_bin_storage_right_dark +stove: basic_sleek_induc +microwave: standard +oven: beko +stovetop: pack_1_top_gas +hood: tall_stainless +fridge: modern +dishwasher: basic_stainless + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +paper_towel: holder_2 +stool: stool_1_1 +toaster: fancy +knife_block: light_wood_2 +utensil_rack: metal_cg_2 +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/playground.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/playground.yaml new file mode 100644 index 0000000000000000000000000000000000000000..90b71d9944e922d60699980fb98724ca24921159 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/playground.yaml @@ -0,0 +1,30 @@ +# fixtures using primitive geoms +cabinet: + default: [gray, shaker] + shelves: dark_wood_planks_shelves +counter: + default: gray_base_marble_top + island: gray_base_tiled_wood_top +floor: concrete_tiles +wall: playground +openings_wall: default + +# fixtures using models +sink: concrete +stove: electric_range +microwave: standard +oven: samsung +stovetop: samsung_top_gas +hood: simple_silver +fridge: pack_2 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: default +paper_towel: default +utensil_rack: default +wall_accessory: default +box: default +window: default +framed_window: default diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/rustic.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/rustic.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e922cb739388c792579d4fe2b339ed8475b31982 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/rustic.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [light_green, shaker] + shelves: rustic_wood_shelves +counter: + default: green_base_wood_top + island: green_base_granite_top +floor: wood_3 +wall: wood_planks + +# fixtures using models +sink: concrete_sink +stove: square_gas +microwave: gray +oven: bosch +stovetop: sleek_silver_top_gas +hood: pack_2 +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup_2 +wall_accessory: default +knife_block: light_wood_3 +paper_towel: holder_2 +stool: stool_1_1 +utensil_rack: metal +utensil_holder: holder_1 +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/scandanavian.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/scandanavian.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6862e43ab0aae57ec789942119b4ec8ce87a2768 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/scandanavian.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [white, slab] + shelves: white +counter: + default: default + island: default +floor: light_wood_long +wall: white_tiles + +# fixtures using models +sink: white_sink +stove: frigidaire_gas +microwave: pack_1 +oven: westerfeld +stovetop: sleek_silver_top_gas +hood: simple_silver +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup +paper_towel: holder_2 +utensil_rack: metal +stool: stool_1_2 +knife_block: light_wood_3 +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/traditional_1.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/traditional_1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..397c56a916d833d04618486ed84e822aff304f85 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/traditional_1.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: [raised, white] + cab_top: [divided_window, white] + cab_top_small: [raised, white] + shelves: warm_wood_parquet +counter: + default: white_base_marble_top + island: warm_wood_base_marble_top +floor: warm_wood +wall: varied_marble_tiles + +# fixtures using models +sink: 1_bin_wide_top_handle +stove: frigidaire_gas +microwave: standard +oven: gorenje +stovetop: pack_1_top_gas +hood: simple_silver +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso +toaster: vintage +knife_block: light_wood_2 +paper_towel: holder_2 +stool: rattan_stool +utensil_rack: metal +utensil_holder: holder_1 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/traditional_2.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/traditional_2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..303a210dad0396e6a127cb53519b873b86778b2d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/traditional_2.yaml @@ -0,0 +1,33 @@ +# fixtures using primitive geoms +cabinet: + default: [raised, walnut_wood_grain, handle_dark_gray] + shelves: warm_wood_parquet +counter: + default: warm_wood_base_granite_top + island: warm_wood_base_granite_top +floor: wood_2 +wall: diamond_tiles + +# fixtures using models +sink: 1_bin_wide_top_handle +stove: frigidaire_gas +microwave: gray +oven: gorenje_dark +stovetop: pack_1_top_induc +hood: pack_2 +fridge: pack_2 +dishwasher: pack_2 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +wall_accessory: default +knife_block: light_wood_3 +paper_towel: holder_4 +stool: stool_1_3 +utensil_rack: metal +utensil_holder: holder_3 +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/transitional_1.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/transitional_1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..46d43bc13e5b4ba6be2f61313decc6b0bb2b979b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/transitional_1.yaml @@ -0,0 +1,34 @@ +# fixtures using primitive geoms +cabinet: + default: [lighter_gray, shaker, handle_black, handle_boxed] + shelves: wood_grain_shelves_2 +counter: + default: white_base_marble_top_2 + island: white_base_marble_top_2 +floor: dark_wood_planks +wall: diamond_marble_parquet + +# fixtures using models +sink: white_sink +stove: basic_sleek_induc +microwave: standard +oven: beko +stovetop: pack_1_top_induc +hood: tall_stainless +fridge: modern +dishwasher: basic_stainless + +# need to implement a system for swapping these out +accessory: default +coffee_machine: nespresso +toaster: basic_popup +wall_accessory: default +knife_block: knife_block_1 +paper_towel: holder_2 +stool: stool_1_2 +utensil_rack: metal_cg_2 +utensil_holder: holder_2 +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/transitional_2.yaml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/transitional_2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..465a1b1921e3a07fb479e5c6fdf1295b72fb1c24 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/assets/scenes/kitchen_styles/transitional_2.yaml @@ -0,0 +1,36 @@ +# fixtures using primitive geoms +cabinet: + default: light_gray + cab_top: [full_window_clear, light_gray] + cab_top_small: [full_window_clear, light_gray] + shelves: dark_wood_planks_shelves +counter: + default: gray_base_marble_top_2 + island: white_base_marble_island +floor: dark_wood +wall: diamond_white_tiles + +# fixtures using models +sink: 1_bin_storage_right_dark +stove: square_gas +microwave: gray +oven: gorenje_dark +stovetop: sleek_silver_top_gas +hood: pack_1 +fridge: pack_1 +dishwasher: pack_1 + +# need to implement a system for swapping these out +accessory: default +coffee_machine: delonghi_espresso_2 +toaster: basic_popup_2 +knife_block: light_wood_3 +paper_towel: holder_4 +stool: stool_1_2 +utensil_rack: metal +utensil_holder: holder_3 +wall_accessory: default +box: default +window: default +framed_window: default + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f7896d3fbdd57a9b0f96b207ed73bb648b2b8207 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/__init__.py @@ -0,0 +1,19 @@ +from robocasa.models.fixtures.fixture import Fixture, FixtureType + +from robocasa.models.fixtures.handles import * +from robocasa.models.fixtures.cabinets import * +from robocasa.models.fixtures.others import * +from robocasa.models.fixtures.accessories import * + +from robocasa.models.fixtures.stove import Stove, Stovetop, Oven +from robocasa.models.fixtures.microwave import Microwave +from robocasa.models.fixtures.sink import Sink +from robocasa.models.fixtures.counter import Counter +from robocasa.models.fixtures.hood import Hood +from robocasa.models.fixtures.fridge import Fridge +from robocasa.models.fixtures.dishwasher import Dishwasher + +from robocasa.models.fixtures.fixture_stack import FixtureStack +from robocasa.models.fixtures.windows import Window, FramedWindow + +from robocasa.models.fixtures.fixture_utils import fixture_is_type diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/accessories.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/accessories.py new file mode 100644 index 0000000000000000000000000000000000000000..dda836b1f8bcd3476e129dedf0050b45e3198fd7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/accessories.py @@ -0,0 +1,231 @@ +import numpy as np +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import string_to_array as s2a + +from robocasa.models.fixtures import Fixture + + +class Accessory(Fixture): + """ + Base class for all accessories/Miscellaneous objects + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + + pos (list): position of the object + """ + + def __init__(self, xml, name, pos=None, *args, **kwargs): + super().__init__( + xml=xml, + name=name, + duplicate_collision_geoms=False, + pos=pos, + *args, + **kwargs + ) + + +class CoffeeMachine(Accessory): + """ + Coffee machine object. Supports turning on coffee machine, and simulated coffee pouring + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._turned_on = False + # site where coffee liquid is poured + self._receptacle_pouring_site = self.worldbody.find( + "./body/body/site[@name='{}{}']".format( + self.naming_prefix, "receptacle_place_site" + ) + ) + + # sites which act as the simulated coffee liquid which pours out when the start button is pressed + self._coffee_liquid_site_names = [] + for postfix in ["coffee_liquid_left", "coffee_liquid_right", "coffee_liquid"]: + name = "{}{}".format(self.naming_prefix, postfix) + site = self.worldbody.find("./body/body/site[@name='{}']".format(name)) + if site is not None: + self._coffee_liquid_site_names.append(name) + + def get_reset_regions(self, *args, **kwargs): + """ + returns dictionary of reset regions, usually used when initialzing a mug under the coffee machine + """ + return { + "bottom": { + "offset": s2a(self._receptacle_pouring_site.get("pos")), + "size": (0.01, 0.01), + } + } + + def get_state(self): + """ + returns whether the coffee machine is turned on or off as a dictionary with the turned_on key + """ + state = dict( + turned_on=self._turned_on, + ) + return state + + def update_state(self, env): + """ + Checks if the gripper is pressing the start button. If this is the first time the gripper pressed the button, + the coffee machine is turned on, and the coffee liquid sites are turned on. + + Args: + env (MujocoEnv): The environment to check the state of the coffee machine in + """ + start_button_pressed = env.check_contact( + env.robots[0].gripper["right"], "{}_start_button".format(self.name) + ) + + if self._turned_on is False and start_button_pressed: + self._turned_on = True + + for site_name in self._coffee_liquid_site_names: + site_id = env.sim.model.site_name2id(site_name) + if self._turned_on: + env.sim.model.site_rgba[site_id][3] = 1.0 + else: + env.sim.model.site_rgba[site_id][3] = 0.0 + + def check_receptacle_placement_for_pouring(self, env, obj_name, xy_thresh=0.04): + """ + check whether receptacle is placed under coffee machine for pouring + + Args: + env (MujocoEnv): The environment to check the state of the coffee machine in + + obj_name (str): name of the object + + xy_thresh (float): threshold for xy distance between object and receptacle + + Returns: + bool: True if object is placed under coffee machine, False otherwise + """ + obj_pos = np.array(env.sim.data.body_xpos[env.obj_body_id[obj_name]]) + pour_site_name = "{}{}".format(self.naming_prefix, "receptacle_place_site") + site_id = env.sim.model.site_name2id(pour_site_name) + pour_site_pos = env.sim.data.site_xpos[site_id] + xy_check = np.linalg.norm(obj_pos[0:2] - pour_site_pos[0:2]) < xy_thresh + z_check = np.abs(obj_pos[2] - pour_site_pos[2]) < 0.10 + return xy_check and z_check + + def gripper_button_far(self, env, th=0.15): + """ + check whether gripper is far from the start button + + Args: + env (MujocoEnv): The environment to check the state of the coffee machine in + + th (float): threshold for distance between gripper and button + + Returns: + bool: True if gripper is far from the button, False otherwise + """ + button_id = env.sim.model.geom_name2id( + "{}{}".format(self.naming_prefix, "start_button") + ) + button_pos = env.sim.data.geom_xpos[button_id] + gripper_site_pos = env.sim.data.site_xpos[env.robots[0].eef_site_id["right"]] + + gripper_button_far = np.linalg.norm(gripper_site_pos - button_pos) > th + + return gripper_button_far + + @property + def nat_lang(self): + return "coffee machine" + + +class Toaster(Accessory): + @property + def nat_lang(self): + return "toaster" + + +class Stool(Accessory): + @property + def nat_lang(self): + return "stool" + + +# For outlets, clocks, paintings, etc. +class WallAccessory(Fixture): + """ + Class for wall accessories. These are objects that are attached to walls, such as outlets, clocks, paintings, etc. + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + + pos (list): position of the object + + attach_to (Wall): The wall to attach the object to + + protrusion (float): How much to protrude out of the wall when placing the object + """ + + def __init__( + self, xml, name, pos, attach_to=None, protrusion=0.02, *args, **kwargs + ): + super().__init__( + xml=xml, + name=name, + duplicate_collision_geoms=False, + pos=pos, + *args, + **kwargs + ) + + # TODO add in error checking for rotated walls + # if (pos[1] is None and attach_to is None) or (pos[1] is not None and attach_to is not None): + # raise ValueError("Exactly one of y-dimension \"pos\" and \"attach_to\" " \ + # "must be specified") + # if pos[0] is None or pos[2] is None: + # raise ValueError("The x and z-dimension position must be specified") + + # the wall to attach accessory to + self.wall = attach_to + # how much to protrude out of wall + if protrusion is not None: + self.protrusion = protrusion + else: + self.protrusion = self.depth / 2 + + self._place_accessory() + + def _place_accessory(self): + """ + Place the accessory on the wall + """ + if self.wall is None: + # absolute position was specified + return + + x, y, z = self.pos + # print(self.wall.wall_side, self.name) + + # update position and rotation of the object based on the wall it attaches to + if self.wall.wall_side == "back": + y = self.wall.pos[1] - self.protrusion + elif self.wall.wall_side == "front": + self.set_euler([0, 0, self.rot + 3.1415]) + y = self.wall.pos[1] + self.protrusion + elif self.wall.wall_side == "right": + x = self.wall.pos[0] - self.protrusion + self.set_euler([0, 0, self.rot - 1.5708]) + elif self.wall.wall_side == "left": + x = self.wall.pos[0] + self.protrusion + self.set_euler([0, 0, self.rot + 1.5708]) + elif self.wall.wall_side == "floor": + raise NotImplementedError() + else: + raise ValueError() + + self.set_pos([x, y, z]) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/cabinet_panels.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/cabinet_panels.py new file mode 100644 index 0000000000000000000000000000000000000000..73d7275aaf52ca40b654965cc00a87f9d7bedd47 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/cabinet_panels.py @@ -0,0 +1,561 @@ +import abc +import xml + +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import find_elements, xml_path_completion + +import robocasa +from robocasa.models.objects import MujocoXMLObject +from robocasa.models.fixtures.fixture import get_texture_name_from_file +from robocasa.models.fixtures.handles import * +from robocasa.utils.object_utils import set_geom_dimensions + + +class CabinetPanel(MujocoXMLObject): + """ + Base class for cabinet panels which are attached to the cabinet body. + + Args: + xml (str): Path to the xml file for the cabinet panel. + + size (list): Size of the cabinet panel in [w, d, h] format. + + name (str): Name of the cabinet panel. + + handle_type (str): Type of handle to attach to the cabinet panel. + + handle_config (dict): Configuration for the handle. + + handle_hpos (str): Horizontal position of the handle. + + handle_vpos (str): Vertical position of the handle. + + texture (str): Path to the texture file for the cabinet panel. + """ + + def __init__( + self, + xml, + size, # format: [w, d, h] + name, + handle_type="bar", + handle_config=None, + handle_hpos=None, + handle_vpos=None, + texture=None, + ): + super().__init__( + xml_path_completion(xml, root=robocasa.models.assets_root), + name=name, + joints=None, + duplicate_collision_geoms=True, + ) + + self.size = size + self.texture = texture + + self.handle_type = handle_type + self.handle_config = handle_config + self.handle_hpos = handle_hpos + self.handle_vpos = handle_vpos + + self._set_texture() + self._create_panel() + self._add_handle() + + @abc.abstractmethod + def _get_components(self): + raise NotImplementedError + + @abc.abstractmethod + def _create_panel(self): + pass + + def exclude_from_prefixing(self, inp): + """ + Exclude all shared materials and their associated names from being prefixed. + + Args: + inp (ET.Element or str): Element or its attribute to check for prefixing. + + Returns: + bool: True if we should exclude the associated name(s) with @inp from being prefixed with naming_prefix + """ + if "tex" in inp: + return True + + if isinstance(inp, xml.etree.ElementTree.Element): + if inp.tag == "texture": + return True + + return False + + def _set_texture(self): + """ + Set the texture for the cabinet panel. + """ + if self.texture is None: + return + + self.texture = xml_path_completion( + self.texture, root=robocasa.models.assets_root + ) + texture = find_elements( + self.root, tags="texture", attribs={"name": "tex"}, return_first=True + ) + tex_is_2d = texture.get("type", None) == "2d" + tex_name = get_texture_name_from_file(self.texture) + if tex_is_2d: + tex_name += "_2d" + texture.set("name", tex_name) + texture.set("file", self.texture) + + material = find_elements( + self.root, + tags="material", + attribs={"name": "{}_mat".format(self.name)}, + return_first=True, + ) + material.set("name", "{}_mat".format(self.name)) + material.set("texture", tex_name) + + def _add_handle(self): + """ + Add a handle to the cabinet panel. Creates the handle object, positions it based off the handle_hpos and handle_vpos, + and appends it to the cabinet panel body. + """ + if self.handle_type is None: + return + elif self.handle_type == "bar": + handle_class = BarHandle + vpad = 0.20 + hpad = 0.05 + elif self.handle_type == "knob": + handle_class = KnobHandle + vpad = 0.05 + hpad = 0.05 + elif self.handle_type == "boxed": + handle_class = BoxedHandle + vpad = 0.20 + hpad = 0.05 + else: + raise NotImplementedError + + panel_w = self.size[0] + panel_h = self.size[2] + + handle = handle_class( + name="{}_handle".format(self.name), + panel_w=panel_w, + panel_h=panel_h, + **self.handle_config, + ) + handle_elem = handle.get_obj() + + if self.handle_vpos == "bottom": + handle_z = -(panel_h / 2 - vpad) + elif self.handle_vpos == "top": + handle_z = panel_h / 2 - vpad + elif self.handle_vpos == "center": + handle_z = 0.0 + else: + raise NotImplementedError + + if self.handle_hpos == "left": + handle_x = -(panel_w / 2 - hpad) + elif self.handle_hpos == "right": + handle_x = panel_w / 2 - hpad + elif self.handle_hpos == "center": + handle_x = 0.0 + else: + raise NotImplementedError + + handle_elem.set("pos", a2s([handle_x, 0, handle_z])) + + parent_body = self.get_obj() + + self.merge_assets(handle) + parent_body.append(handle_elem) + + +class SlabCabinetPanel(CabinetPanel): + """ + Initialize a slab cabinet panel, which is a simple flat panel. + """ + + def __init__(self, *args, **kwargs): + xml = "fixtures/cabinets/cabinet_panels/slab.xml" + super().__init__(xml=xml, *args, **kwargs) + + def _get_components(self): + """ + Gets the geoms for the cabinet panel. + """ + geom_names = ["door"] + return self._get_elements_by_name(geom_names)[0] + + def _create_panel(self): + """ + Creates the cabinet panel. This involves setting the size and position of the panel's geom + """ + geoms = self._get_components() + + # divide by 2 for mujoco convention + x, y, z = [dim / 2 for dim in self.size] + + sizes = {"door": [x, y, z]} + positions = {"door": [0, 0, 0]} + set_geom_dimensions(sizes, positions, geoms, rotated=True) + + +class ShakerCabinetPanel(CabinetPanel): + """ + Initialize a shaker cabinet panel, which is a simple flat panel with a trim. + + Args: + trim_th (float): Thickness of the trim (depth). + + trim_size (float): Size of the trim (width/height). + """ + + def __init__(self, name, trim_th=0.02, trim_size=0.08, *args, **kwargs): + self.trim_th = trim_th + self.trim_size = trim_size + + xml = "fixtures/cabinets/cabinet_panels/shaker.xml" + super().__init__(xml=xml, name=name, *args, **kwargs) + + def _get_components(self): + """ + Gets the geoms for the cabinet panel. This includes the door and the 4 sorrounding trims. + """ + geom_names = ["door", "trim_left", "trim_right", "trim_bottom", "trim_top"] + return self._get_elements_by_name(geom_names)[0] + + def _create_panel(self): + """ + Creates the cabinet panel. This involves setting the size and position of the panel's door and trim geoms + """ + # divide by 2 for mujoco convention + x, y, z = self.size + x, y, z = x / 2, y / 2, z / 2 + trim_th, trim_size = self.trim_th / 2, self.trim_size / 2 + + # position door and trims such that (0, 0, 0) is center + door_th = y - trim_th + door_y = trim_th / 2 + trim_y = -door_th / 2 + + sizes = { + "door": [x - trim_size * 2, door_th, z - trim_size * 2], + "trim_left": [trim_size, trim_th, z], + "trim_right": [trim_size, trim_th, z], + "trim_top": [x - 2 * trim_size, trim_th, trim_size], + "trim_bottom": [x - 2 * trim_size, trim_th, trim_size], + } + positions = { + "door": [0, door_y, 0], + "trim_left": [-x + trim_size, trim_y, 0], + "trim_right": [x - trim_size, trim_y, 0], + "trim_top": [0, trim_y, z - trim_size], + "trim_bottom": [0, trim_y, -z + trim_size], + } + + geoms = self._get_components() + set_geom_dimensions(sizes, positions, geoms, rotated=True) + + +class RaisedCabinetPanel(CabinetPanel): + """ + Initialize a raised cabinet panel, similar to the shaker panel, but with a raised door portion. + + Args: + trim_th (float): Thickness of the trim (depth). + + trim_size (float): Size of the trim (width/height). + + raised_gap (float): Gap between the raised portion and the sorrounding trims + """ + + def __init__( + self, name, trim_th=0.02, trim_size=0.08, raised_gap=0.01, *args, **kwargs + ): + self.trim_th = trim_th + self.trim_size = trim_size + self.raised_gap = raised_gap + + xml = "fixtures/cabinets/cabinet_panels/raised.xml" + super().__init__(xml=xml, name=name, *args, **kwargs) + + def _get_components(self): + """ + Gets the geoms for the cabinet panel. This includes the door, the 4 sorrounding trims, and the raised portion. + """ + geom_names = [ + "door", + "door_raised", + "trim_left", + "trim_right", + "trim_bottom", + "trim_top", + ] + return self._get_elements_by_name(geom_names)[0] + + def _create_panel(self): + """ + Creates the cabinet panel. This involves setting the size and position of the panel's door, trim, and raised portion geoms + """ + + # place the trims accordingly + ShakerCabinetPanel._create_panel(self) + + x, y, z = self.size + x, y, z = x / 2, y / 2, z / 2 + + trim_size, trim_th = self.trim_size / 2, self.trim_th / 2 + raised_gap = self.raised_gap / 2 + + # place and size the raised portion accordingly, + sizes = { + "door_raised": [ + x - 2 * trim_size - 2 * raised_gap, + trim_th, + z - 2 * trim_size - 2 * raised_gap, + ] + } + positions = {"door_raised": [0, -(y - trim_th) / 2, 0]} + + geoms = self._get_components() + set_geom_dimensions(sizes, positions, geoms, rotated=True) + + +class DividedWindowCabinetPanel(CabinetPanel): + """ + Initialize a divided window cabinet panel, which is a panel with a windowed door, trims around, and + a 2 trims running down the middle of the window (horizontally and vertically aligned). + + Args: + name (str): Name of the cabinet panel. + + trim_th (float): Thickness of the trim (depth). + + trim_size (float): Size of the trims (width/height). + """ + + def __init__(self, name, trim_th=0.02, trim_size=0.08, *args, **kwargs): + + self.trim_th = trim_th + self.trim_size = trim_size + + xml = "fixtures/cabinets/cabinet_panels/divided_window.xml" + super().__init__(xml=xml, name=name, *args, **kwargs) + + def _get_components(self): + """ + Gets the geoms for the cabinet panel. This includes the door, the 4 sorrounding trims, + and the 2 trims running down the middle of the window. + """ + geom_names = [ + "door", + "trim_left", + "trim_right", + "trim_bottom", + "trim_top", + "horiz_trim", + "vert_trim", + ] + return self._get_elements_by_name(geom_names)[0] + + def _create_panel(self): + """ + Creates the cabinet panel. This involves setting the size and position of the panel's door, trims, and window trims + """ + # divide by 2 for mujoco convention + x, y, z = self.size + x, y, z = x / 2, y / 2, z / 2 + trim_th, trim_size = self.trim_th / 2, self.trim_size / 2 + + # position door and trims such that (0, 0, 0) is center + door_th = y - trim_th + door_y = trim_th / 2 + trim_y = -door_th / 2 + + sizes = { + "door": [x - trim_size * 2, door_th, z - trim_size * 2], + "trim_left": [trim_size, trim_th, z], + "trim_right": [trim_size, trim_th, z], + "trim_top": [x - 2 * trim_size, trim_th, trim_size], + "trim_bottom": [x - 2 * trim_size, trim_th, trim_size], + "vert_trim": [trim_size / 3.5, trim_th, z], + "horiz_trim": [x - 2 * trim_size, trim_th, trim_size / 3.5], + } + positions = { + "door": [0, door_y, 0], + "trim_left": [-x + trim_size, trim_y, 0], + "trim_right": [x - trim_size, trim_y, 0], + "trim_top": [0, trim_y, z - trim_size], + "trim_bottom": [0, trim_y, -z + trim_size], + "vert_trim": [0, trim_y, 0], + "horiz_trim": [0, trim_y, 0], + } + + geoms = self._get_components() + set_geom_dimensions(sizes, positions, geoms, rotated=True) + + +class FullWindowedCabinetPanel(CabinetPanel): + """ + Initialize a full windowed cabinet panel, which is a panel with a windowed door and trims around. + Same as the divided window panel but without the middle trims running through the window. + + Args: + name (str): Name of the cabinet panel. + + trim_th (float): Thickness of the trim (depth). + + trim_size (float): Size of the trims (width/height). + + opacity (float): Opacity of the window. Defaults to 0.5 to create a "frosted" effect. + """ + + def __init__( + self, name, trim_th=0.02, trim_size=0.08, opacity=0.5, *args, **kwargs + ): + self.trim_th = trim_th + self.trim_size = trim_size + self.opacity = opacity + + xml = "fixtures/cabinets/cabinet_panels/full_window.xml" + super().__init__(xml=xml, name=name, *args, **kwargs) + + def _get_components(self): + """ + Gets the geoms for the cabinet panel. This includes the door and the 4 sorrounding trims. + """ + geom_names = ["door", "trim_left", "trim_right", "trim_bottom", "trim_top"] + return self._get_elements_by_name(geom_names)[0] + + def _create_panel(self): + """ + Creates the cabinet panel. This involves setting the size and position of the panel's door and trim geoms + """ + # place the trims accordingly + ShakerCabinetPanel._create_panel(self) + self._set_opacity() + + def _set_opacity(self): + """ + Set the opacity of the window. + """ + transparent_mat = find_elements( + self.root, + tags="material", + attribs={"name": f"{self.name}_transparent_material"}, + return_first=True, + ) + transparent_mat.set("rgba", f"1 1 1 {self.opacity}") + + +class CabinetShelf(MujocoXMLObject): + """ + Initialize a cabinet shelf, which is a simple flat panel but rotated 90 degrees. + + Args: + size (list): Size of the cabinet shelf in [w, d, h] format. + + texture (str): Path to the texture file for the cabinet shelf. + + name (str): Name of the cabinet shelf. + + pos (list): Position of the cabinet shelf. + """ + + def __init__( + self, + size, # format: [w, d, h] + texture, + name, + pos=None, + ): + super().__init__( + xml_path_completion( + "fixtures/cabinets/cabinet_panels/shelf.xml", + root=robocasa.models.assets_root, + ), + name=name, + joints=None, + duplicate_collision_geoms=True, + ) + + self.size = np.array(size) + self.pos = pos if pos is not None else [0, 0, 0] + self._create_panel() + + self.texture = texture + self._set_texture() + + def exclude_from_prefixing(self, inp): + """ + Exclude all shared materials and their associated names from being prefixed. + + + Args: + inp (ET.Element or str): Element or its attribute to check for prefixing. + + + Returns: + bool: True if we should exclude the associated name(s) with @inp from being prefixed with naming_prefix + """ + if "tex" in inp: + return True + + if isinstance(inp, xml.etree.ElementTree.Element): + if inp.tag == "texture": + return True + + return False + + def _set_texture(self): + """ + Set the texture for the cabinet shelf. + """ + if self.texture is None: + return + + self.texture = xml_path_completion( + self.texture, root=robocasa.models.assets_root + ) + texture = find_elements( + self.root, tags="texture", attribs={"name": "tex"}, return_first=True + ) + tex_is_2d = texture.get("type", None) == "2d" + tex_name = get_texture_name_from_file(self.texture) + if tex_is_2d: + tex_name += "_2d" + texture.set("name", tex_name) + texture.set("file", self.texture) + + material = find_elements( + self.root, + tags="material", + attribs={"name": "{}_mat".format(self.name)}, + return_first=True, + ) + material.set("texture", tex_name) + + def _get_components(self): + """ + Gets the geoms for the cabinet shelf. + """ + geom_names = ["shelf"] + return self._get_elements_by_name(geom_names)[0] + + def _create_panel(self): + """ + Creates the cabinet shelf. This involves setting the size and position of the panel's geom + """ + geoms = self._get_components() + + sizes = {"shelf": self.size / 2} + positions = {"shelf": self.pos} + set_geom_dimensions(sizes, positions, geoms) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/cabinets.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/cabinets.py new file mode 100644 index 0000000000000000000000000000000000000000..376a8defccf7c8fd5e2802dcd8cc6449a331e9e0 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/cabinets.py @@ -0,0 +1,1189 @@ +from copy import deepcopy +from xml.etree import ElementTree as ET + +import numpy as np +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import ( + find_elements, + find_parent, + new_geom, + xml_path_completion, +) + +import robocasa +import robocasa.utils.object_utils as OU +from robocasa.models.fixtures.cabinet_panels import * +from robocasa.models.fixtures.fixture import ( + ProcGenFixture, + get_texture_name_from_file, +) +from robocasa.utils.object_utils import ( + get_fixture_to_point_rel_offset, + set_geom_dimensions, +) + + +class Cabinet(ProcGenFixture): + """ + Cabinet class. Procedurally defined with primitive geoms + + Args: + xml (str): path to xml file + + name (str): name of the cabinet + + size (list): size of the cabinet [w, d, h] + + thickness (float): thickness of the cabinet walls + + door_gap (float): gap for the doors applied to height and width + + handle_type (str): type of handle attached to cabinet + + handle_config (dict): configuration for handle. contains keyword arguments for handle class + + panel_type (str): type of panel used for cabinet + + panel_config (dict): configuration for panel. contains keyword arguments for panel class + + open_top (bool): whether to remove top element + + texture (str): path to texture file + """ + + def __init__( + self, + xml, + name, + size, # format: [w, d, h] + thickness=0.03, + door_gap=0.003, + handle_type="bar", + handle_config=None, + panel_type="raised", # shaker, slab, raised + panel_config=None, + open_top=False, # remove top element + texture=None, + *args, + **kwargs, + ): + if panel_config is None: + panel_config = dict() + self.panel_type = panel_type + self.panel_config = panel_config + + if handle_config is None: + handle_config = dict() + self.handle_type = handle_type + self.handle_config = handle_config + + super().__init__( + xml=xml, + name=name, + *args, + **kwargs, + ) + + # define common variables + self.thickness = thickness + self.door_gap = door_gap + self.size = np.array(size) + self.texture = texture + + # place and size each component + self.geoms = None + self._create_cab() + + # remove top geom if necessary + if self.geoms is not None and "top" in self.geoms and open_top: + for elem in self.geoms["top"]: + self._remove_element(elem) + + self._set_texture() + + def _set_texture(self): + """ + Set the texture for the cabinet + """ + if self.texture is None: + return + + self.texture = xml_path_completion( + self.texture, root=robocasa.models.assets_root + ) + + texture = find_elements( + self.root, tags="texture", attribs={"name": "tex"}, return_first=True + ) + tex_is_2d = texture.get("type", None) == "2d" + tex_name = get_texture_name_from_file(self.texture) + if tex_is_2d: + tex_name += "_2d" + texture.set("name", tex_name) + texture.set("file", self.texture) + + material = find_elements( + self.root, + tags="material", + attribs={"name": "{}_mat".format(self.name)}, + return_first=True, + ) + material.set("texture", tex_name) + + def get_reset_regions(self, env): + """ + Get the reset regions for the cabinet. This is used to reset the object to a specific location. + Reset region is defined as the bottom of the cabinet + """ + p0, px, py, pz = self.get_int_sites() + return { + "bottom": { + "offset": (0, 0, p0[2]), + "size": (px[0] - p0[0], py[1] - p0[1]), + } + } + + def _create_cab(self): + raise NotImplementedError() + + def _add_door( + self, w, h, th, pos, parent_body, handle_hpos, handle_vpos, door_name="door" + ): + """ + Places a door on the cabinet + + Args: + w (float): width of the door + + h (float): height of the door + + th (float): thickness of the door + + pos (list): position of the door + + parent_body (ET.Element): parent body element + + handle_hpos (str): horizontal position of the handle + + handle_vpos (str): vertical position of the handle + + door_name (str): name of the door + + """ + if self.panel_type == "slab" or self.panel_type is None: + panel_class = SlabCabinetPanel + elif self.panel_type == "shaker": + panel_class = ShakerCabinetPanel + elif self.panel_type == "raised": + panel_class = RaisedCabinetPanel + elif self.panel_type == "divided_window": + panel_class = DividedWindowCabinetPanel + elif self.panel_type == "full_window": + panel_class = FullWindowedCabinetPanel + elif self.panel_type == "no_panel": + # Partially implemented - size/pos of body will still assume panel in front + return + else: + raise NotImplementedError() + dg = self.door_gap + + panel_config = deepcopy(self.panel_config) + panel_config["handle_hpos"] = handle_hpos + panel_config["handle_vpos"] = handle_vpos + + door = panel_class( + size=[w - dg, th, h - dg], # apply door gap to width and height + name="{}_{}".format(self.name, door_name), + texture=self.texture, + handle_type=self.handle_type, + handle_config=self.handle_config, + **panel_config, + ) + door_elem = door.get_obj() + door_elem.set("pos", a2s(pos)) + + self.merge_assets(door) + parent_body.append(door_elem) + + def set_door_state(self, min, max, env, rng): + pass + + def get_door_state(self, env): + return {} + + @property + def nat_lang(self): + return "cabinet" + + +class SingleCabinet(Cabinet): + """ + Creates a SingleCabinet object which is a cabinet with a single door that either opens left or right + + Args: + orientation (str): The direction in which the cabinet opens when facing the cabinet. "left" or "right" + + name (str): name of the cabinet + """ + + def __init__( + self, + name="single_cab", + orientation="right", + *args, + **kwargs, + ): + assert orientation in ["left", "right"] + self.orientation = orientation + self.cabinet_type = "single" + + xml = "fixtures/cabinets/cabinet_single.xml" + + super().__init__( + xml=xml, + name=name, + *args, + **kwargs, + ) + + def _get_cab_components(self): + """ + Finds and returns all geoms, bodies, and joints used for single cabinets + + Returns: + dicts for geoms, bodies, and joints, mapping names to elements + """ + geom_names = ["top", "bottom", "back", "right", "left", "shelf", "door"] + body_names = ["hingedoor"] + joint_names = ["doorhinge"] + + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_cab(self): + """ + Creates the full cabinet. This involves setting the sizes and positions for the cabinet and the door, + creating the door class, and determining the handle orientation. This also involves calculating the exterior + and interior bounding boxes. + """ + # divide everything by 2 according to mujoco convention + x, y, z = [dim / 2 for dim in self.size] + th = self.thickness / 2 + + # get geoms, bodies, and joints + # TODO: is adjusting the joint necessary? + self.geoms, bodies, joints = self._get_cab_components() + + # cabinet housing + sizes = { + "top": [x, y - th, th], + "bottom": [x, y - th, th], + "back": [x - 2 * th, th, z - 2 * th], + "left": [th, y - th, z - 2 * th], + "right": [th, y - th, z - 2 * th], + "shelf": [x - 2 * th, y - 0.05, th], + } + positions = { + "top": [0, th, z - th], + "bottom": [0, th, -z + th], + "back": [0, y - th, 0], + "left": [-x + th, th, 0], + "right": [x - th, th, 0], + "shelf": [0, 0.05 - th, 0], + } + set_geom_dimensions(sizes, positions, self.geoms, rotated=True) + + # cabinet door bodies and joints + bodies["hingedoor"].set("pos", a2s([0, 0, 0])) + # set joint position + if self.orientation == "left": + joints["doorhinge"].set("pos", a2s([-x + th, -y, 0])) + joints["doorhinge"].set("range", a2s([-3.00, 0])) + else: + joints["doorhinge"].set("pos", a2s([x - th, -y, 0])) + + # create door + door_pos = [0, -y + th, 0] + # if the door opens right the handle must be on the left side of the door and vice versa + handle_hpos = "right" if self.orientation == "left" else "left" + handle_vpos = self.panel_config.get("handle_vpos", "bottom") + + self._add_door( + w=x * 2, + h=z * 2, + th=th * 2, + pos=door_pos, + parent_body=bodies["hingedoor"], + handle_hpos=handle_hpos, + handle_vpos=handle_vpos, + ) + + # set sites + self.set_bounds_sites( + { + "ext_p0": [-x, -y, -z], + "ext_px": [x, -y, -z], + "ext_py": [-x, y, -z], + "ext_pz": [-x, -y, z], + "int_p0": [-x + th * 2, -y + th * 2, -z + th * 2], + "int_px": [x - th * 2, -y + th * 2, -z + th * 2], + "int_py": [-x + th * 2, y - th * 2, -z + th * 2], + "int_pz": [-x + th * 2, -y + th * 2, z - th * 2], + } + ) + + def set_door_state(self, min, max, env, rng): + """ + Sets how open the door is. Chooses a random amount between min and max. + Min and max are percentages of how open the door is + + Args: + min (float): minimum percentage of how open the door is + + max (float): maximum percentage of how open the door is + + env (MujocoEnv): environment + + rng (np.random.Generator): random number generator + """ + assert 0 <= min <= 1 and 0 <= max <= 1 and min <= max + + joint_min = 0 + joint_max = np.pi / 2 + + desired_min = joint_min + (joint_max - joint_min) * min + desired_max = joint_min + (joint_max - joint_min) * max + + sign = -1 if self.orientation == "left" else 1 + + env.sim.data.set_joint_qpos( + "{}_doorhinge".format(self.name), + sign * rng.uniform(desired_min, desired_max), + ) + + def get_door_state(self, env): + """ + Args: + env (MujocoEnv): environment + + Returns: + dict: maps door name to a percentage of how open the door is + """ + sim = env.sim + hinge_qpos = sim.data.qpos[sim.model.joint_name2id(f"{self.name}_doorhinge")] + sign = -1 if self.orientation == "left" else 1 + hinge_qpos = hinge_qpos * sign + + # convert to percentages + door = OU.normalize_joint_value(hinge_qpos, joint_min=0, joint_max=np.pi / 2) + + return { + "door": door, + } + + @property + def handle_name(self): + return "{}_door_handle_handle".format(self.name) + + @property + def door_name(self): + return "{}_hingedoor".format(self.name) + + +class HingeCabinet(Cabinet): + """ + Creates a HingeCabinet object which is a cabinet with two doors that open outwards + + Args: + name (str): name of the cabinet + """ + + def __init__( + self, + name="hinge_cab", + *args, + **kwargs, + ): + self.cabinet_type = "hinge" + + xml = "fixtures/cabinets/cabinet_hinge.xml" + + super().__init__( + xml=xml, + name=name, + *args, + **kwargs, + ) + + def _get_cab_components(self): + """ + Finds and returns all geoms, bodies, and joints used for single cabinets + + Returns: + dicts for geoms, bodies, and joints, mapping names to elements + """ + + geom_names = [ + "top", + "bottom", + "back", + "right", + "left", + "shelf", + ] + body_names = ["hingeleftdoor", "hingerightdoor"] + joint_names = ["leftdoorhinge", "rightdoorhinge"] + + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_cab(self): + """ + Creates the full cabinet. This involves setting the sizes and positions for the cabinet and the doors, + creating the door classes. This also involves calculating the exterior + and interior bounding boxes. + """ + # divide sizes by two according to mujoco conventions + x, y, z = [dim / 2 if dim is not None else None for dim in self.size] + th = self.thickness / 2 + + self.geoms, bodies, joints = self._get_cab_components() + + # set bodies positions + bodies["hingeleftdoor"].set("pos", a2s([0, 0, 0])) + bodies["hingerightdoor"].set("pos", a2s([0, 0, 0])) + + # set joint positions + joints["leftdoorhinge"].set("pos", a2s([-x + th, -y, 0])) + joints["rightdoorhinge"].set("pos", a2s([x - th, -y, 0])) + + # positions + positions = { + "top": [0, th, z - th], + "bottom": [0, th, -z + th], + "back": [0, y - th, 0], + "left": [-x + th, th, 0], + "right": [x - th, th, 0], + "shelf": [0, 0.05 - th, 0], + } + sizes = { + "top": [x, y - th, th], + "bottom": [x, y - th, th], + "back": [x - 2 * th, th, z - 2 * th], + "left": [th, y - th, z - 2 * th], + "right": [th, y - th, z - 2 * th], + "shelf": [x - 2 * th, y - 0.05, th], + } + set_geom_dimensions(sizes, positions, self.geoms, rotated=True) + + # add doors + door_x_positions = {"left": -x / 2, "right": x / 2} + handle_vpos = self.panel_config.get("handle_vpos", "bottom") + + for side in ["left", "right"]: + self._add_door( + w=x, + h=z * 2, + th=th * 2, + pos=[door_x_positions[side], -y + th, 0], + parent_body=bodies["hinge{}door".format(side)], + handle_hpos="left" if side == "right" else "right", + handle_vpos=handle_vpos, + door_name=side + "_door", + ) + + # set sites + self.set_bounds_sites( + { + "ext_p0": [-x, -y, -z], + "ext_px": [x, -y, -z], + "ext_py": [-x, y, -z], + "ext_pz": [-x, -y, z], + "int_p0": [-x + th * 2, -y + th * 2, -z + th * 2], + "int_px": [x - th * 2, -y + th * 2, -z + th * 2], + "int_py": [-x + th * 2, y - th * 2, -z + th * 2], + "int_pz": [-x + th * 2, -y + th * 2, z - th * 2], + } + ) + + def get_state(self, sim): + """ + Args: + env (MujocoEnv): environment + + Returns: + dict: maps joint names to joint values + """ + # angle of two door joints + state = dict() + for j in self._joints: + name = "{}_{}".format(self.name, j) + addr = sim.model.get_joint_qpos_addr(name) + state[name] = sim.data.qpos[addr] + return state + + def set_door_state(self, min, max, env, rng): + """ + Sets how open the doors are. Chooses a random amount between min and max. + Min and max are percentages of how open the doors are + + Args: + min (float): minimum percentage of how open the door is + + max (float): maximum percentage of how open the door is + + env (MujocoEnv): environment + + rng (np.random.Generator): random number generator + """ + assert 0 <= min <= 1 and 0 <= max <= 1 and min <= max + + joint_min = 0 + joint_max = np.pi / 2 + + desired_min = joint_min + (joint_max - joint_min) * min + desired_max = joint_min + (joint_max - joint_min) * max + + env.sim.data.set_joint_qpos( + "{}_rightdoorhinge".format(self.name), rng.uniform(desired_min, desired_max) + ) + + env.sim.data.set_joint_qpos( + "{}_leftdoorhinge".format(self.name), -rng.uniform(desired_min, desired_max) + ) + + def get_door_state(self, env): + """ + Args: + env (MujocoEnv): environment + + Returns: + dict: maps door names to a percentage of how open they are + """ + sim = env.sim + right_hinge_qpos = sim.data.qpos[ + sim.model.joint_name2id(f"{self.name}_rightdoorhinge") + ] + left_hinge_qpos = -sim.data.qpos[ + sim.model.joint_name2id(f"{self.name}_leftdoorhinge") + ] + + # convert to percentages + left_door = OU.normalize_joint_value( + left_hinge_qpos, joint_min=0, joint_max=np.pi / 2 + ) + right_door = OU.normalize_joint_value( + right_hinge_qpos, joint_min=0, joint_max=np.pi / 2 + ) + + return { + "left_door": left_door, + "right_door": right_door, + } + + @property + def left_handle_name(self): + return "{}_left_door_handle_handle".format(self.name) + + @property + def right_handle_name(self): + return "{}_right_door_handle_handle".format(self.name) + + +class OpenCabinet(Cabinet): + """ + Creates a OpenCabinet object which is a cabinet with open shelves + + Args: + name (str): name of the cabinet + + num_shelves (int): number of shelves in the cabinet + """ + + def __init__( + self, + name="shelves", + num_shelves=2, + *args, + **kwargs, + ): + self.num_shelves = num_shelves + self.shelves = list() + super().__init__( + xml="fixtures/cabinets/cabinet_open.xml", + name=name, + *args, + **kwargs, + ) + + def _get_cab_components(self): + """ + Finds and returns all geoms, bodies, and joints used for open cabinets + + Returns: + dicts for geoms, bodies, and joints, mapping names to elements + """ + geom_names = ["top", "bottom"] + return self._get_elements_by_name(geom_names)[0] + + def _create_cab(self): + """ + Creates the full cabinet. This involves setting the sizes and positions for each shelf. + This also involves calculating the exterior and interior bounding boxes. + """ + # no need to divide size here + x, y, z = self.size + th = self.thickness + + shelf_size = [x, y, th] + # evenly spaced, taking thickness into account + shelf_z_positions = ( + np.linspace( + start=th / 2, stop=z - th / 2, num=self.num_shelves, endpoint=False + ) + - z / 2 + ) + + # create and position shelves + for i in range(self.num_shelves): + shelf_pos = [0, 0, shelf_z_positions[i]] + shelf = CabinetShelf( + size=shelf_size, + pos=shelf_pos, + name="{}_shelf_{}".format(self.name, i), + texture=self.texture, + ) + self.shelves.append(shelf) + + # merge shelves + self.merge_assets(shelf) + shelf_elem = shelf.get_obj() + self.get_obj().append(shelf_elem) + + self.set_bounds_sites( + { + "ext_p0": [-x, -y, -z], + "ext_px": [x, -y, -z], + "ext_py": [-x, y, -z], + "ext_pz": [-x, -y, z], + "int_p0": [-x + th * 2, -y + th * 2, -z + th * 2], + "int_px": [x - th * 2, -y + th * 2, -z + th * 2], + "int_py": [-x + th * 2, y - th * 2, -z + th * 2], + "int_pz": [-x + th * 2, -y + th * 2, z - th * 2], + } + ) + + @property + def nat_lang(self): + return "shelves" + + +class Drawer(Cabinet): + """ + Creates a Drawer + + Args: + name (str): name of the cabinet + + handle_config (dict): configuration for handle. contains keyword arguments for handle class + """ + + def __init__( + self, + name="drawer", + handle_config=None, + *args, + **kwargs, + ): + self.cabinet_type = "drawer" + + xml = "fixtures/cabinets/drawer.xml" + + if handle_config is None: + handle_config = dict() + handle_config["orientation"] = "horizontal" + + super().__init__( + xml=xml, + name=name, + handle_config=handle_config, + *args, + **kwargs, + ) + + def _get_cab_components(self): + """ + Finds and returns all geoms, bodies, and joints used for drawers + returns: + dicts for geoms, bodies, and joints, mapping names to elements + """ + geom_names = [ + "top", + "bottom", + "back", + "right", + "left", + "inner_bottom", + "inner_back", + "inner_right", + "inner_left", + ] + body_names = ["inner_box"] + joint_names = ["slidejoint"] + + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_cab(self): + """ + Creates the full cabinet. This involves setting the sizes and positions for the cabinet and the door, + creating the door class. This also involves calculating the exterior and interior bounding boxes. + """ + # divide everything by 2 according to mujoco convention + x, y, z = [dim / 2 for dim in self.size] + th = self.thickness / 2 + + self.geoms, bodies, joints = self._get_cab_components() + + """ + core cabinet housing + """ + + ix = x - 2 * th - 0.001 # inner box x + iy = y - 2 * th + iz = z - 2 * th - 0.001 # inner box z + + sizes = { + "top": [x, y - th, th], + "bottom": [x, y - th, th], + "back": [x - 2 * th, th, z - 2 * th], + "left": [th, y - th, z - 2 * th], + "right": [th, y - th, z - 2 * th], + "inner_bottom": [ix, iy, th], + "inner_back": [ix - 2 * th, th, iz - 2 * th], + "inner_left": [th, iy, iz - 2 * th], + "inner_right": [th, iy, iz - 2 * th], + } + positions = { + "top": [0, th, z - th], + "bottom": [0, th, -z + th], + "back": [0, y - th, 0], + "left": [-x + th, th, 0], + "right": [x - th, th, 0], + "inner_bottom": [0, 0, -iz + th], + "inner_back": [0, iy - th, 0], + "inner_left": [-ix + th, 0, 0], + "inner_right": [ix - th, 0, 0], + } + set_geom_dimensions(sizes, positions, self.geoms, rotated=True) + + # door body and joints + bodies["inner_box"].set("pos", a2s([0, 0, 0])) + # set joint position + joints["slidejoint"].set("pos", a2s([0, -y, 0])) + joints["slidejoint"].set("range", a2s([-y * 2, 0])) + + # create door + door_w, door_h, door_th = x * 2, z * 2, th * 2 # multiply by 2 to set full size + door_pos = [0, -y + th, 0] + self._add_door( + w=door_w, + h=door_h, + th=door_th, + pos=door_pos, + parent_body=bodies["inner_box"], + handle_hpos="center", + handle_vpos="center", + ) + + self.set_bounds_sites( + { + "ext_p0": [-x, -y, -z], + "ext_px": [x, -y, -z], + "ext_py": [-x, y, -z], + "ext_pz": [-x, -y, z], + "int_p0": [-ix + 2 * th, -iy, -iz + 2 * th], + "int_px": [ix - 2 * th, -iy, -iz + 2 * th], + "int_py": [-ix + 2 * th, iy - 2 * th, -iz + 2 * th], + "int_pz": [-ix + 2 * th, -iy, iz], + } + ) + + @property + def nat_lang(self): + return "drawer" + + def update_state(self, env): + """ + Updates the interior bounding boxes of the drawer to be matched with + how open the drawer is. This is needed when determining if an object + is inside the drawer or when placing an object inside an open drawer. + + Args: + env (MujocoEnv): environment + """ + int_sites = {} + for site in ["int_p0", "int_px", "int_py", "int_pz"]: + int_sites[site] = get_fixture_to_point_rel_offset( + self, np.array(env.sim.data.get_site_xpos(self.naming_prefix + site)) + ) + self.set_bounds_sites(int_sites) + + def set_door_state(self, min, max, env, rng): + """ + Sets how open the drawer is. Chooses a random amount between min and max. + Min and max are percentages of how open the drawer is. + + Args: + min (float): minimum percentage of how open the drawer is + + max (float): maximum percentage of how open the drawer is + + env (MujocoEnv): environment + + rng (np.random.Generator): random number generator + """ + assert 0 <= min <= 1 and 0 <= max <= 1 and min <= max + + joint_min = 0 + joint_max = self.size[1] * 0.55 # dont want it to fully open up + + desired_min = joint_min + (joint_max - joint_min) * min + desired_max = joint_min + (joint_max - joint_min) * max + + sign = -1 + + env.sim.data.set_joint_qpos( + "{}_slidejoint".format(self.name), + sign * rng.uniform(desired_min, desired_max), + ) + + def get_door_state(self, env): + """ + Args: + env (MujocoEnv): environment + + Returns: + dict: maps door name to a percentage of how open the door is + """ + sim = env.sim + hinge_qpos = sim.data.qpos[sim.model.joint_name2id(f"{self.name}_slidejoint")] + sign = -1 + hinge_qpos = hinge_qpos * sign + + # convert to percentages + door = OU.normalize_joint_value( + hinge_qpos, joint_min=0, joint_max=self.size[1] * 0.55 + ) + + return { + "door": door, + } + + @property + def handle_name(self): + return "{}_door_handle_handle".format(self.name) + + +class PanelCabinet(Cabinet): + """ + Creates a PanelCabinet object which is a cabinet with a panel door but no handle. + This is mainly used in a fixture stack where there is an unopenable cabinet/drawer + + Args: + name (str): name of the cabinet + + solid_body (bool): whether to create a solid body for the cabinet behind the panel + """ + + def __init__( + self, + name="panel_cab", + solid_body=False, + *args, + **kwargs, + ): + self.cabinet_type = "panel" + + xml = "fixtures/cabinets/panel.xml" + + kwargs["handle_type"] = None + self.solid_body = solid_body + + super().__init__( + xml=xml, + name=name, + *args, + **kwargs, + ) + + def _get_cab_components(self): + geom_names = [] + body_names = [] + joint_names = [] + + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_cab(self): + """ + Creates the panel cabinet. This involves setting the sizes and positions for door, and + if solid_body is True, creating a solid body for the cabinet behind the panel. + """ + x, y, z = [dim / 2 for dim in self.size] + th = self.thickness / 2 + + if self.solid_body: + geom_name = self._name + "_body" + size = [x, y - th, z] + pos = [0, th, 0] + g = new_geom( + name=geom_name, + type="box", + size=size, + pos=pos, + group=0, + density=10, + rgba="0.5 0 0 1", + ) + g_vis = new_geom( + name=geom_name + "_visual", + type="box", + size=size, + pos=pos, + group=1, + material=self._name + "_mat", + density=10, + conaffinity=0, + contype=0, + mass=1e-8, + ) + self._obj.append(g) + self._obj.append(g_vis) + + ### make a door and merge in ### + door_w, door_h, door_th = x * 2, z * 2, th * 2 # multiply by 2 to set full size + door_pos = [0, -y + th, 0] + self._add_door( + w=door_w, + h=door_h, + th=door_th, + pos=door_pos, + parent_body=self.get_obj(), + handle_hpos="center", + handle_vpos="center", + ) + + def get_state(self, sim): + # angle of two door joints + state = dict() + for j in self._joints: + name = "{}_{}".format(self.name, j) + addr = sim.model.get_joint_qpos_addr(name) + state[name] = sim.data.qpos[addr] + return state + + +class HousingCabinet(Cabinet): + """ + Creates a HousingCabinet object which is a cabinet which is hollowed out to contain another object + + Args: + interior_obj (Fixture): Fixture to be placed inside the cabinet + + size (list): Size of the cabinet in [x, y, z] + + padding (list): Thickness of the cabinet walls in [[-x, x], [-y, y], [-z, z]]. For each dimension, if size is specified, + + padding is optional and vice versa. + + name (str): Name of the cabinet + """ + + def __init__( + self, + interior_obj, + size=None, + padding=None, # padding amount in [[-x, x], [-y, y], [-z, z]] directions + name="housing_cab", + *args, + **kwargs, + ): + self.cabinet_type = "housing" + + xml = "fixtures/cabinets/cabinet_housing.xml" + + self.interior_obj = ( + None # initially set to None for superclass initialization, set later + ) + + # Parse size and padding input + if size is None and padding is None: + raise ValueError("Must specify size or padding for housing cabinet") + elif size is None: + size = [None] * 3 + elif padding is None: + padding = [[None] * 2 for _ in range(3)] + + padding = [[None, None] if p is None else p for p in padding] + + for d in range(3): + if size[d] is None: + if padding[d][0] is None or padding[d][1] is None: + raise ValueError( + "If size is not specified for a dimension, both padding values must be" + ) + else: + size[d] = sum(padding[d]) + interior_obj.size[d] + elif padding[d][0] is None and padding[d][1] is None: + padding[d][0] = padding[d][1] = (size[d] - interior_obj.size[d]) / 2 + elif padding[d][0] is None: + padding[d][0] = size[d] - interior_obj.size[d] - padding[d][1] + elif padding[d][1] is None: + padding[d][1] = size[d] - interior_obj.size[d] - padding[d][0] + else: + # Everything is specified, so check that sizes match exactly + assert size[d] == sum(padding[d]) + interior_obj.size[d] + + # Round small fp errors to 0 + padding[d] = [i if abs(i) > 0.000001 else 0 for i in padding[d]] + + # Allow negative front padding for object to stick out further + if size[d] < 0 or padding[d][1] < 0 or (d != 1 and padding[d][0] < 0): + raise ValueError("Negative cab size or padding") + + self.padding = padding + super().__init__( + xml=xml, + name=name, + size=np.array(size), + *args, + **kwargs, + ) + + self.interior_obj = interior_obj + self._place_interior_obj() + + def set_pos(self, pos): + """ + Sets the position of the cabinet and the interior object + + Args: + pos (list): position of the cabinet + """ + super().set_pos(pos) + # we have to set the postion of the interior object as well + if self.interior_obj is not None: + self._place_interior_obj() + + def _place_interior_obj(self): + """ + calculates and sets the position of the interior object + """ + + # calculate and set the position of sink + interior_origin = np.array( + [ + self.pos[0] + (self.padding[0][0] - self.padding[0][1]) / 2, + self.pos[1] + (self.padding[1][0] - self.padding[1][1]) / 2, + self.pos[2] + (self.padding[2][0] - self.padding[2][1]) / 2, + ] + ) + + self.interior_obj.set_origin(interior_origin) + + def _create_cab(self): + """ + Creates the housing cabinet. This involves setting the sizes and positions for the sourrounding walls of the + housing cabinet, and setting exterior and interior bounding box sites. + """ + # divide sizes by two according to mujoco conventions + x, y, z = [dim / 2 for dim in self.size] + + # positions of 5 walls according to padding + positions = { + "top": [0, -self.padding[1][1] / 2, z - self.padding[2][1] / 2], + "bottom": [0, -self.padding[1][1] / 2, -z + self.padding[2][0] / 2], + "back": [0, y - self.padding[1][1] / 2, 0], + "left": [-x + self.padding[0][0] / 2, -self.padding[1][1] / 2, 0], + "right": [x - self.padding[0][1] / 2, -self.padding[1][1] / 2, 0], + } + # sizes of 5 walls according to padding + sizes = { + "top": [x, y - self.padding[1][1] / 2, self.padding[2][1] / 2], + "bottom": [x, y - self.padding[1][1] / 2, self.padding[2][0] / 2], + "back": [x, self.padding[1][1] / 2, z], + "left": [ + self.padding[0][0] / 2, + y - self.padding[1][1] / 2, + z - sum(self.padding[2]) / 2, + ], + "right": [ + self.padding[0][1] / 2, + y - self.padding[1][1] / 2, + z - sum(self.padding[2]) / 2, + ], + } + + # remove walls with size <= 0 + sizes = { + geom: np.array(size) + for geom, size in sizes.items() + if all([d > 0 for d in size]) + } + positions = { + geom: np.array(pos) for geom, pos in positions.items() if geom in sizes + } + + # Add geoms to xml + for geom in sizes.keys(): + geom_name = self._name + "_" + geom + g = new_geom( + name=geom_name, + type="box", + size=sizes[geom], + pos=positions[geom], + group=0, + density=10, + rgba="0.5 0 0 1", + ) + g_vis = new_geom( + name=geom_name + "_visual", + type="box", + size=sizes[geom], + pos=positions[geom], + group=1, + material=self._name + "_mat", + density=10, + conaffinity=0, + contype=0, + mass=1e-8, + ) + self._obj.append(g) + self._obj.append(g_vis) + + # set sites + self.set_bounds_sites( + { + "ext_p0": [-x, -y, -z], + "ext_px": [x, -y, -z], + "ext_py": [-x, y, -z], + "ext_pz": [-x, -y, z], + "int_p0": [ + -x + self.padding[0][0], + -y + self.padding[1][0], + -z + self.padding[2][0], + ], + "int_px": [ + x - self.padding[0][1], + -y + self.padding[1][0], + -z + self.padding[2][0], + ], + "int_py": [ + -x + self.padding[0][0], + y - self.padding[1][1], + -z + self.padding[2][0], + ], + "int_pz": [ + -x + self.padding[0][0], + -y + self.padding[1][0], + z - self.padding[2][1], + ], + } + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/counter.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/counter.py new file mode 100644 index 0000000000000000000000000000000000000000..4e0365ed8d8ab95e6ed5d223a16a197db512d319 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/counter.py @@ -0,0 +1,675 @@ +import math +import random +from copy import deepcopy + +import numpy as np +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import find_elements, new_geom +from robosuite.utils.mjcf_utils import string_to_array as s2a +from robosuite.utils.mjcf_utils import xml_path_completion + +import robocasa +from robocasa.models.fixtures.fixture import ( + ProcGenFixture, + get_texture_name_from_file, +) +from robocasa.utils.object_utils import ( + get_fixture_to_point_rel_offset, + get_pos_after_rel_offset, + get_rel_transform, +) + +SIDES = ["left", "right", "front", "back"] + + +class Counter(ProcGenFixture): + """ + Initializes a counter fixture. + + Args: + name (str): name of the counter + + size (tuple): size of the counter (width, depth, height) + + overhang (float): amount which the top of the counter overhangs the base + + top_texture (str): path to the texture file for the top of the counter + + top_thickness (float): thickness of the top of the counter + + half_top (list): list of booleans to specify if the counter is half-sized and extends right or left + + base_texture (str): path to the texture file for the base of the counter + + base_color (list): list of 4 floats specifying the color of the base + + base_opening (list): list of booleans to specify if the counter has an opening in the front or back + + hollow (list): list of booleans to specify if the should exclude the front, back, or the whole the base. + Both hollow and base_opening cannot be set at the same time if they are, base_opening takes precedence. + + interior_obj (ProcGenFixture): object to be placed inside the counter + + obj_y_percent (float): Percentage of the counter's depth taken up by the interior object + + obj_x_percent (float): Percentage of the counter's width taken up by the interior object + """ + + def __init__( + self, + name="counter", + size=(0.72, 0.60, 0.60), + overhang=0, + # top + top_texture=None, + top_thickness=0.03, + half_top=[False, False], # for aligning corner counters + # base, can use both + base_texture=None, + base_color=None, + base_opening=[False, False], + # to add bottom row cabinets inside + # [back, front] + hollow=[False, True], + # for sinks, cooktops + interior_obj=None, + obj_y_percent=0.5, + obj_x_percent=0.5, + *args, + **kwargs, + ): + self.has_opening = interior_obj is not None + if self.has_opening: + xml = "fixtures/counters/counter_with_opening" + else: + xml = "fixtures/counters/counter" + self.interior_obj = None + + self.size = size + self.th = top_thickness + self.overhang = overhang + self.half_top = half_top + + super().__init__( + xml=xml, + name=name, + *args, + **kwargs, + ) + + assert len(hollow) == 2 + self.hollow = hollow + + if len(base_opening) != 2 or sum(base_opening) > 1: + raise ValueError("Invalid value for `base_opening`:", base_opening) + self.base_opening = base_opening + if sum(self.base_opening) == 1: + # overwrites hollow parameter + self.hollow = [False, False] + + if interior_obj is None: + self._make_counter() + else: + if type(interior_obj) == str: + raise ValueError("Sink must be initialized before CounterSink") + self.interior_obj = interior_obj + self.obj_x_percent = obj_x_percent + self.obj_y_percent = obj_y_percent + + top_padding = self._place_interior_obj() + self._make_counter_with_opening(top_padding) + + # set top texture + self._set_texture(top_texture, base_texture, base_color) + + # set sites + x, y, z = np.array(self.size) / 2 + self.set_bounds_sites( + { + "ext_p0": [-x, -y + self.overhang, -z], + "ext_px": [x, -y + self.overhang, -z], + "ext_py": [-x, y, -z], + "ext_pz": [-x, -y + self.overhang, z], + } + ) + + def _set_texture(self, top_texture, base_texture, base_color): + # set top and bottom textures + self.top_texture = xml_path_completion( + top_texture, root=robocasa.models.assets_root + ) + self.base_texture = xml_path_completion( + base_texture, root=robocasa.models.assets_root + ) + + # set top texture and materials + texture = find_elements( + self.root, tags="texture", attribs={"name": "tex_top_2d"}, return_first=True + ) + tex_name = get_texture_name_from_file(self.top_texture) + "_2d" + texture.set("name", tex_name) + texture.set("file", self.top_texture) + material = find_elements( + self.root, + tags="material", + attribs={"name": "{}_counter_top".format(self.name)}, + return_first=True, + ) + material.set("texture", tex_name) + + texture = find_elements( + self.root, tags="texture", attribs={"name": "tex_base"}, return_first=True + ) + tex_name = get_texture_name_from_file(self.base_texture) + texture.set("name", tex_name) + texture.set("file", self.base_texture) + material = find_elements( + self.root, + tags="material", + attribs={"name": "{}_counter_base".format(self.name)}, + return_first=True, + ) + material.set("texture", tex_name) + + # need to look at this later, not sure why + prefix = self.naming_prefix if self.name != "counter" else "" + + # set base color + if base_color is not None: + self.base_color = base_color + base_material = find_elements( + self.root, + "material", + attribs={"name": prefix + "counter_base"}, + return_first=True, + ) + + if len(self.base_color) == 3: + self.base_color.append(1) + base_material.set("rgba", a2s(self.base_color)) + + def _get_counter_geoms(self): + """ + searches for geoms corresponding to each of the four components of the counter. + Currently does not return collision geoms for top because does not account for the chunking! + """ + + geoms = dict() + for side in SIDES: + geoms["base" + "_" + side] = list() + + if self.has_opening: + for side in SIDES: + geoms["top" + "_" + side] = list() + else: + geoms["top"] = list() + + for geom_name in geoms.keys(): + for postfix in ["", "_visual"]: + g = find_elements( + root=self._obj, + tags="geom", + attribs={"name": "{}_{}{}".format(self.name, geom_name, postfix)}, + return_first=True, + ) + geoms[geom_name].append(g) + return geoms + + def _place_interior_obj(self): + """ + calculates and sets the position of the sink, + calculates and returns the sizes of padding around the sink. + + x_percent/y_percent specifies at what percent of the fixture's entire width/depth + the center of the sink should be placed. + + Returns: + list: list of padding values [left, right, front, back], + which are distance between the edge of the counter and (the edge of the interior object + gap) + """ + + x_percent, y_percent = self.obj_x_percent, self.obj_y_percent + + # remove overhang from consideration for placement + top_size = [ + self.size[0], + self.size[1] - self.overhang, + self.size[2], + ] # remove the overhang + + # respect boundaires: limit range of x_percent and y_percent so interior object doesn't overflow + gap = 0.02 + max_x_percent = (top_size[0] - gap - self.interior_obj.width / 2) / top_size[0] + x_percent = np.clip(x_percent, 1 - max_x_percent, max_x_percent) + max_y_percent = (top_size[1] - gap - self.interior_obj.depth / 2) / top_size[1] + y_percent = np.clip(y_percent, 1 - max_y_percent, max_y_percent) + + # calculate and set the position of sink + interior_origin = [ + self.pos[0] + (x_percent - 0.50) * top_size[0], + self.pos[1] + self.overhang / 2 + (y_percent - 0.50) * top_size[1], + self.pos[2] + top_size[2] / 2 - self.interior_obj.height / 2, + ] + + self.interior_obj.set_origin(interior_origin) + + # calculate the size of padding around the sink + left_pad = x_percent * top_size[0] - self.interior_obj.width / 2 + right_pad = (1 - x_percent) * top_size[0] - self.interior_obj.width / 2 + front_pad = ( + y_percent * top_size[1] - self.interior_obj.depth / 2 + self.overhang + ) # add the overhang to the front + back_pad = (1 - y_percent) * top_size[1] - self.interior_obj.depth / 2 + + return [left_pad, right_pad, front_pad, back_pad] + + def _get_chunks(self, pos, size, chunk_size=0.5): + """ + Breaks the top width into chunks of size `chunk_size` + + Args: + pos (np.array): position of the center of the top + + size (np.array): size of the top + + chunk_size (float): size of each chunk + """ + top_x_sizes = np.array(math.ceil(size[0] / chunk_size) * [chunk_size]) + top_x_sizes[-1] = size[0] - np.sum(top_x_sizes[:-1]) + + chunk_sizes = [np.array([x_size, size[1], size[2]]) for x_size in top_x_sizes] + left_pos = pos - np.array([size[0] / 2, 0, 0]) + chunk_positions = [] + for i in range(len(top_x_sizes)): + chunk_positions.append( + np.array( + [ + left_pos[0] + + np.sum(top_x_sizes[: max(0, i)]) + + top_x_sizes[i] / 2, + pos[1], + pos[2], + ] + ) + ) + return chunk_positions, chunk_sizes + + def _make_counter(self): + """ + Creates a contigious counter with a top and possibly a base. + """ + w, d, h = np.array(self.size) + th = self.th + + geoms = dict() + + # get the base geoms + for side in SIDES: + geoms["base" + "_" + side] = list() + for geom_name in geoms.keys(): + for postfix in ["", "_visual"]: + g = find_elements( + root=self._obj, + tags="geom", + attribs={"name": "{}_{}{}".format(self.name, geom_name, postfix)}, + return_first=True, + ) + geoms[geom_name].append(g) + + # counters with half-top can only either be right or left + assert sum(self.half_top) < 2 + if sum(self.half_top) == 0: + pos = np.array([0, 0, h / 2 - th / 2]) + size = np.array([w, d, th]) + else: + # used for aligning corner counters + size = np.array([w / 2, d, th]) + if self.half_top[1]: + # keep right half + pos = np.array([w / 4, 0, h / 2 - th / 2]) + else: + # keep left half + pos = np.array([-w / 4, 0, h / 2 - th / 2]) + + half_size = size / 2 + + geom_name = self._name + "_top" + g_vis = new_geom( + name=geom_name + "_visual", + type="box", + size=half_size, + pos=pos, + group=1, + material=self._name + "_counter_top", + density=10, + conaffinity=0, + contype=0, + mass=1e-8, + ) + self._obj.append(g_vis) + # manually update visual geoms registry + self._visual_geoms.append("top_visual") + + # break the top width into chunks + chunk_positions, chunk_sizes = self._get_chunks(pos, size, chunk_size=0.5) + for i in range(len(chunk_sizes)): + g = new_geom( + name=geom_name + "_{}".format(i), + type="box", + size=chunk_sizes[i] / 2, + pos=chunk_positions[i], + group=0, + density=10, + rgba="0.5 0 0 1", + ) + self._obj.append(g) + # manually update contact geoms registry + self._contact_geoms.append("top_{}".format(i)) + + base_size, base_pos = self._get_base_dimensions() + + for side in SIDES: + for elem in geoms["base_{}".format(side)]: + # remove appropriate part of the base if based on hollow specification + if side == "front" and self.hollow[1]: + self._remove_element(elem) + elif side == "back" and self.hollow[0]: + self._remove_element(elem) + # houses bottom row cabinets + # remove right and left base geoms if any of hollow is True + elif sum(self.base_opening) == 0 and sum(self.hollow) > 0: + self._remove_element(elem) + else: + elem.set("pos", a2s(base_pos[side])) + elem.set("size", a2s(base_size[side])) + + def _make_counter_with_opening(self, padding): + """ + calculates and set the size and position of each component in the counter + + coordinate system change may or may not be necessary. currently all other fixtures + use Mujoco's center-based coordinate system + + Args: + padding (list): list of padding values [left, right, front, back], + + which are distance between the edge of the counter and (the edge of the interior object + gap) + """ + w, d, h = self.size + th = self.th + side_th = 0.2 if sum(self.base_opening) == 1 else 0.0002 + left_pad, right_pad, front_pad, back_pad = padding + + if front_pad < self.overhang: + raise ValueError( + "Overhang value is too large, must be lower " + "than front padding ({:.2f})".format(front_pad) + ) + + # calculate the (full) size of each component + top_size = dict( + back=[self.interior_obj.width, back_pad, h - th], + front=[self.interior_obj.width, front_pad - self.overhang, h - th], + left=[left_pad, d - self.overhang, h - th], + right=[right_pad, d - self.overhang, h - th], + ) + + # all coordinates are the bottom-left corners + # the origin is the bottom-left corner of the entire fixture + top_pos = dict( + back=[left_pad, front_pad + self.interior_obj.depth, -th], + front=[left_pad, self.overhang, -th], + left=[0, self.overhang, -th], + right=[left_pad + self.interior_obj.width, self.overhang, -th], + ) + + base_size = dict( + back=[w, 0.0002, h - th], + front=[w, 0.0002, h - th], + left=[side_th, d - self.overhang, h - th], + right=[side_th, d - self.overhang, h - th], + ) + base_pos = dict( + back=[0.0, d, -th], + front=[0.0, -d + 2 * self.overhang, -th], + left=[-w + side_th, self.overhang, -th], + right=[w - side_th, self.overhang, -th], + ) + + # move panel to middle of the island this will create an opening under the counter in the front/back + if self.base_opening[0]: + base_pos["front"] = [0, 0, -th] + elif self.base_opening[1]: + base_pos["back"] = [0, 0, -th] + + geoms = dict() + # get the base geoms + for side in SIDES: + geoms["base" + "_" + side] = list() + for geom_name in geoms.keys(): + for postfix in ["", "_visual"]: + g = find_elements( + root=self._obj, + tags="geom", + attribs={"name": "{}_{}{}".format(self.name, geom_name, postfix)}, + return_first=True, + ) + geoms[geom_name].append(g) + + for side in SIDES: + # convert coordinate of bottom-left corner to coordinate of center + # the origin is now the center of the entire fixture + top_pos[side][0] = top_pos[side][0] + top_size[side][0] / 2 - w / 2 + top_pos[side][1] = top_pos[side][1] + top_size[side][1] / 2 - d / 2 + top_pos[side][2] /= 2 + + base_pos[side] = np.array(base_pos[side]) / 2 + + for elem in geoms["base_{}".format(side)]: + # remove appropriate part of the base, based on hollow specification + if side == "front" and self.hollow[1]: + self._remove_element(elem) + elif side == "back" and self.hollow[0]: + self._remove_element(elem) + elif sum(self.base_opening) == 0 and sum(self.hollow) > 0: + self._remove_element(elem) + else: + elem.set("pos", a2s(base_pos[side])) + # divide sizes by 2 according to mujoco convention + elem.set("size", a2s(np.array(base_size[side]) / 2)) + + # for elem in geoms["top_{}".format(side)]: + pos = np.array(top_pos[side]) + size = np.array(top_size[side]) + pos[2] = (h - th) / 2 + size[2] = th + + # account for overhang + if side != "back": + size[1] += self.overhang + pos[1] -= self.overhang / 2 + + geom_name = self._name + "_top_{}".format(side) + + half_size = size / 2 + + g_vis = new_geom( + name=geom_name + "_visual", + type="box", + size=half_size, + pos=pos, + group=1, + material=self._name + "_counter_top", + density=10, + conaffinity=0, + contype=0, + mass=1e-8, + ) + self._obj.append(g_vis) + # manually update visual geoms registry + self._visual_geoms.append("top_{}_visual".format(side)) + + chunk_positions, chunk_sizes = self._get_chunks(pos, size, chunk_size=0.5) + for i in range(len(chunk_sizes)): + g = new_geom( + name=geom_name + "_{}".format(i), + type="box", + size=chunk_sizes[i] / 2, + pos=chunk_positions[i], + group=0, + density=10, + rgba="0.5 0 0 1", + ) + self._obj.append(g) + self._contact_geoms.append("top_{}_{}".format(side, i)) + + def _get_base_dimensions(self): + """ + Returns the size and position of the base components. Considers the base opening specifications + + Returns: + tuple: tuple of dictionaries containing the size and position of each base component + """ + # divide everything by 2 per mujoco convention + x, y, z = np.array(self.size) / 2 + overhang = self.overhang / 2 + th = self.th / 2 + side_th = 0.1 if sum(self.base_opening) == 1 else 0.0001 + + base_size = dict( + back=[x - side_th * 2, th, z - th], + front=[x - side_th * 2, th, z - th], + left=[side_th, y - overhang, z - th], + right=[side_th, y - overhang, z - th], + ) + base_pos = dict( + back=[0, y - th, -th], + front=[0, -y + 2 * overhang + th, -th], + left=[-x + side_th, overhang, -th], + right=[x - side_th, overhang, -th], + ) + + if self.base_opening[0]: + # move panel to middle of the island + base_pos["front"] = [0, 0, -th] + elif self.base_opening[1]: + base_pos["back"] = [0, 0, -th] + + return base_size, base_pos + + # to overwrite Fixture class default + @property + def width(self): + return self.size[0] + + @property + def depth(self): + return self.size[1] + + @property + def height(self): + return self.size[2] + + def set_pos(self, pos): + super().set_pos(pos) + # we have to set the postion of the interior object as well + if self.interior_obj is not None: + self._place_interior_obj() + + def get_reset_regions(self, env, ref=None, loc="nn", top_size=(0.4, 0.4)): + """ + returns dictionary of reset regions, each region defined as offsets and size + + Args: + env (Kitchen): the kitchen environment which contains this counter + + ref (str): reference fixture used in determining sampling location + + loc (str): sampling method, one of ["nn", "left", "right", "left_right", "any"] + nn: chooses the closest top geom to the reference fixture + left: chooses the any top geom within 0.3 distance of the left side of the reference fixture + right: chooses the any top geom within 0.3 distance of the right side of the reference fixture + left_right: chooses the any top geom within 0.3 distance of the left or right side of the reference fixture + any: chooses any top geom + + top_size (tuple): minimum size of the top region to return + + + Returns: + dict: dictionary of reset regions + """ + all_geoms = [] + for (k, v) in self._get_counter_geoms().items(): + # only reset on top geoms + if not k.startswith("top"): + continue + geom = v[-1] + top_pos = s2a(geom.get("pos")) + this_top_size = s2a(geom.get("size")) * 2 + # make sure region is sufficiently large + if this_top_size[0] >= top_size[0] and this_top_size[1] >= top_size[1]: + all_geoms.append(geom) + + reset_regions = {} + + if ref is None: + geom_i = 0 + for g in all_geoms: + top_pos = s2a(g.get("pos")) + top_half_size = s2a(g.get("size")) + offset = (top_pos[0], top_pos[1], self.size[2] / 2) + size = (top_half_size[0] * 2, top_half_size[1] * 2) + reset_regions[f"geom_{geom_i}"] = dict(size=size, offset=offset) + geom_i += 1 + else: + ref_fixture = env.get_fixture(ref) + + ### find an appropriate geom to sample ### + fixture_to_geom_offsets = [] + for g in all_geoms: + g_pos = get_pos_after_rel_offset(self, s2a(g.get("pos"))) + rel_offset = get_fixture_to_point_rel_offset(ref_fixture, g_pos) + fixture_to_geom_offsets.append(rel_offset) + + valid_geoms = [] + + if loc == "nn": + dists = [np.linalg.norm(offset) for offset in fixture_to_geom_offsets] + chosen_top = all_geoms[np.argmin(dists)] + valid_geoms.append(chosen_top) + elif loc == "right": + for offset, g in zip(fixture_to_geom_offsets, all_geoms): + if offset[0] > 0.30: + valid_geoms.append(g) + elif loc == "left": + for offset, g in zip(fixture_to_geom_offsets, all_geoms): + if offset[0] < -0.30: + valid_geoms.append(g) + elif loc == "left_right": + for offset, g in zip(fixture_to_geom_offsets, all_geoms): + if np.abs(offset[0]) > 0.30: + valid_geoms.append(g) + elif loc == "any": + valid_geoms = all_geoms + else: + raise ValueError + + geom_i = 0 + for g in valid_geoms: + top_pos = s2a(g.get("pos")) + top_half_size = s2a(g.get("size")) + offset = [top_pos[0], top_pos[1], self.size[2] / 2] + size = [top_half_size[0] * 2, top_half_size[1] * 2] + + min_x = top_pos[0] - top_half_size[0] + max_x = top_pos[0] + top_half_size[0] + + ref_pos, _ = get_rel_transform(self, ref_fixture) + if min_x <= ref_pos[0] <= max_x: + # restrict sample region to be below fixture + offset[0] = ref_pos[0] + size[0] = min(ref_pos[0] - min_x, max_x - ref_pos[0]) * 2 + + reset_regions[f"geom_{geom_i}"] = dict(size=size, offset=offset) + geom_i += 1 + return reset_regions diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/dishwasher.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/dishwasher.py new file mode 100644 index 0000000000000000000000000000000000000000..c9cad4396e88509f50201dcde66224e0b0141168 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/dishwasher.py @@ -0,0 +1,22 @@ +from robocasa.models.fixtures import Fixture + + +class Dishwasher(Fixture): + """ + Dishwasher fixture class + """ + + def __init__( + self, + xml="fixtures/appliances/dishwashers/pack_1/model.xml", + name="dishwasher", + *args, + **kwargs + ): + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + + @property + def nat_lang(self): + return "dishwasher" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture.py new file mode 100644 index 0000000000000000000000000000000000000000..73caa58b9982c647879e932b4d6ad43022ee3caa --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture.py @@ -0,0 +1,455 @@ +import abc +import os +import random +import xml.etree.ElementTree as ET +from copy import deepcopy +from enum import IntEnum + +import numpy as np +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import ( + array_to_string, + find_elements, + find_parent, + string_to_array, + xml_path_completion, +) + +import robocasa +import robocasa.macros as macros +from robocasa.models.objects import MujocoXMLObject +from robocasa.utils.object_utils import get_pos_after_rel_offset + + +def site_pos(site): + return string_to_array(site.get("pos")) + + +def get_texture_name_from_file(file): + """ + Extract texture name from filename. + eg: ../robosuite/models/assets/textures/flat/gray.png -> flat/gray + """ + suffix_path = file.split("textures/")[1] + name = suffix_path.split(".")[0] + return name + + +class FixtureType(IntEnum): + """ + Enum for fixture types in robosuite kitchen environments. + """ + + COUNTER = 1 + MICROWAVE = 2 + STOVE = 3 + SINK = 4 + CABINET = 5 + DRAWER = 6 + SHELF = 7 + COFFEE_MACHINE = 8 + DOOR = 9 + DOOR_HINGE = 10 + DOOR_HINGE_SINGLE = 11 + DOOR_HINGE_DOUBLE = 12 + DOOR_TOP_HINGE = 13 + DOOR_TOP_HINGE_SINGLE = 14 + DOOR_TOP_HINGE_DOUBLE = 15 + CABINET_TOP = 16 + TOASTER = 17 + DINING_COUNTER = 18 + TOP_DRAWER = 19 + STOOL = 20 + ISLAND = 21 + COUNTER_NON_CORNER = 22 + + +class Fixture(MujocoXMLObject): + """ + Base class for fixtures in robosuite kitchen environments. + + Args: + xml (str): Path to the MJCF xml file to load the fixture from + + name (str): Name of the fixture + + duplicate_collision_geoms (bool): If set, will guarantee that each collision geom has a visual geom copy + + pos (3-tuple): (x, y, z) position of the fixture + + scale (float): 3D Scaling factor for the fixture + + size (3-tuple): desired (width, depth, height) of the fixture + """ + + def __init__( + self, + xml, + name, + duplicate_collision_geoms=True, + pos=None, + scale=1, + size=None, + placement=None, + rng=None, + ): + if not xml.endswith(".xml"): + xml = os.path.join(xml, "model.xml") + + super().__init__( + xml_path_completion(xml, root=robocasa.models.assets_root), + name=name, + joints=None, + duplicate_collision_geoms=duplicate_collision_geoms, + scale=scale, + ) + if pos is not None: + self.set_pos(pos) + + # set up exterior and interior sites + self._bounds_sites = dict() + for postfix in [ + "ext_p0", + "ext_px", + "ext_py", + "ext_pz", + "int_p0", + "int_px", + "int_py", + "int_pz", + ]: + site = find_elements( + self.worldbody, + tags="site", + attribs={"name": "{}{}".format(self.naming_prefix, postfix)}, + return_first=True, + ) + if site is None: + continue + rgba = string_to_array(site.get("rgba")) + if macros.SHOW_SITES: + rgba[-1] = 1.0 + else: + rgba[-1] = 0.0 + site.set("rgba", array_to_string(rgba)) + self._bounds_sites[postfix] = site + + # scale based on specified max dimension + if size is not None: + self.set_scale_from_size(size) + + # based on exterior points, overwritten by subclasses (e.g. Counter) that do not have such sites + self.size = np.array([self.width, self.depth, self.height]) + + # set offset between center of object and center of exterior bounding boxes + if self.width is not None: + try: + # calculate based on bounding points + p0 = site_pos(self._bounds_sites["ext_p0"]) + px = site_pos(self._bounds_sites["ext_px"]) + py = site_pos(self._bounds_sites["ext_py"]) + pz = site_pos(self._bounds_sites["ext_pz"]) + self.origin_offset = np.array( + [ + np.mean((p0[0], px[0])), + np.mean((p0[1], py[1])), + np.mean((p0[2], pz[2])), + ] + ) + except KeyError: + self.origin_offset = [0, 0, 0] + else: + self.origin_offset = [0, 0, 0] + self.origin_offset = np.array(self.origin_offset) + + # placement config, for determining where to place fixture (most fixture will not use this) + self._placement = placement + + if rng is not None: + self.rng = rng + else: + self.rng = np.random.default_rng() + + def set_origin(self, origin): + """ + Set the origin of the fixture to a specified position + + Args: + origin (3-tuple): new (x, y, z) position of the fixture + """ + # compute new position + fixture_rot = np.array([0, 0, self.rot]) + fixture_mat = T.euler2mat(fixture_rot) + + pos = origin + np.dot(fixture_mat, -self.origin_offset) + self.set_pos(pos) + + def set_scale_from_size(self, size): + """ + Set the scale of the fixture based on the desired size. If any of the dimensions are None, + the scaling factor will be the same as one of the other two dimensions + + Args: + size (3-tuple): (width, depth, height) of the fixture + """ + # check that the argument is valid + assert len(size) == 3 + + # calculate and set scale according to specification + scale = [None, None, None] + cur_size = [self.width, self.depth, self.height] + for (i, t) in enumerate(size): + if t is not None: + scale[i] = t / cur_size[i] + + scale[0] = scale[0] or scale[2] or scale[1] + scale[1] = scale[1] or scale[0] or scale[2] + scale[2] = scale[2] or scale[0] or scale[1] + self.set_scale(scale) + + def get_reset_regions(self, *args, **kwargs): + """ + returns dictionary of reset regions, each region defined as position, x_bounds, y_bounds + """ + p0, px, py, pz = self.get_int_sites() + return { + "bottom": { + "offset": (np.mean((p0[0], px[0])), np.mean((p0[1], py[1])), p0[2]), + "size": (px[0] - p0[0], py[1] - p0[1]), + } + } + + def sample_reset_region(self, *args, **kwargs): + regions = self.get_reset_regions(*args, **kwargs) + return self.rng.choice(list(regions.values())) + + def get_site_info(self, sim): + """ + returns user defined sites (eg. the table top, door handle sites, handle sites, shelf sites, etc) + requires sim as position of sites can change during simulation. + """ + info = {} + for s in self._sites: + name = "{}{}".format(self.naming_prefix, s) + info[name] = sim.data.get_site_xpos(name) + return info + + @abc.abstractmethod + def get_state(self): + """ + get the current state of the fixture + """ + return + + @abc.abstractmethod + def update_state(self, env): + """ + update internal state of fixture + """ + return + + @property + def pos(self): + return string_to_array(self._obj.get("pos")) + + @property + def quat(self): + quat = self._obj.get("quat") + if quat is None: + # no rotation applied + quat = "0 0 0 0" + return string_to_array(quat) + + @property + def euler(self): + euler = self._obj.get("euler") + if euler is None: + # no rotation applied + euler = "0 0 0" + return np.array(string_to_array(euler)) + + @property + def horizontal_radius(self): + """ + override the default behavior of only looking at first dimension for radius + """ + horizontal_radius_site = self.worldbody.find( + "./body/site[@name='{}horizontal_radius_site']".format(self.naming_prefix) + ) + site_values = string_to_array(horizontal_radius_site.get("pos")) + return np.linalg.norm(site_values[0:2]) + + @property + def bottom_offset(self): + return site_pos(self._bounds_sites["ext_p0"]) + + @property + def width(self): + """ + for getting the width of an object as defined by its exterior sites. + takes scaling into account + """ + if "ext_px" in self._bounds_sites: + ext_p0 = site_pos(self._bounds_sites["ext_p0"]) + ext_px = site_pos(self._bounds_sites["ext_px"]) + w = ext_px[0] - ext_p0[0] + return w + else: + return None + + @property + def depth(self): + """ + for getting the depth of an object as defined by its exterior sites. + takes scaling into account + """ + if "ext_py" in self._bounds_sites: + ext_p0 = site_pos(self._bounds_sites["ext_p0"]) + ext_py = site_pos(self._bounds_sites["ext_py"]) + d = ext_py[1] - ext_p0[1] + return d + else: + return None + + @property + def height(self): + """ + for getting the height of an object as defined by its exterior sites. + takes scaling into account + """ + if "ext_pz" in self._bounds_sites: + ext_p0 = site_pos(self._bounds_sites["ext_p0"]) + ext_pz = site_pos(self._bounds_sites["ext_pz"]) + h = ext_pz[2] - ext_p0[2] + return h + else: + return None + + def set_bounds_sites(self, pos_dict): + """ + Set the positions of the exterior and interior bounding box sites of the object + + Args: + pos_dict (dict): Dictionary of sites and their new positions + """ + for (name, pos) in pos_dict.items(): + self._bounds_sites[name].set("pos", array_to_string(pos)) + + def get_ext_sites(self, all_points=False, relative=True): + """ + Get the exterior bounding box points of the object + + Args: + all_points (bool): If True, will return all 8 points of the bounding box + + relative (bool): If True, will return the points relative to the object's position + + Returns: + list: 4 or 8 points + """ + sites = [ + site_pos(self._bounds_sites["ext_p0"]), + site_pos(self._bounds_sites["ext_px"]), + site_pos(self._bounds_sites["ext_py"]), + site_pos(self._bounds_sites["ext_pz"]), + ] + + if all_points: + p0, px, py, pz = sites + sites += [ + np.array([p0[0], py[1], pz[2]]), + np.array([px[0], py[1], pz[2]]), + np.array([px[0], py[1], p0[2]]), + np.array([px[0], p0[1], pz[2]]), + ] + + if relative is False: + sites = [get_pos_after_rel_offset(self, offset) for offset in sites] + + return sites + + def get_int_sites(self, all_points=False, relative=True): + """ + Get the interior bounding box points of the object + + Args: + all_points (bool): If True, will return all 8 points of the bounding box + + relative (bool): If True, will return the points relative to the object's position + + Returns: + list: 4 or 8 points + """ + sites = [ + site_pos(self._bounds_sites["int_p0"]), + site_pos(self._bounds_sites["int_px"]), + site_pos(self._bounds_sites["int_py"]), + site_pos(self._bounds_sites["int_pz"]), + ] + + if all_points: + p0, px, py, pz = sites + sites += [ + np.array([p0[0], py[1], pz[2]]), + np.array([px[0], py[1], pz[2]]), + np.array([px[0], py[1], p0[2]]), + np.array([px[0], p0[1], pz[2]]), + ] + + if relative is False: + sites = [get_pos_after_rel_offset(self, offset) for offset in sites] + + return sites + + def get_bbox_points(self, trans=None, rot=None): + """ + Get the full set of bounding box points of the object + rot: a rotation matrix + """ + bbox_offsets = self.get_ext_sites(all_points=True, relative=True) + + if trans is None: + trans = self.pos + if rot is not None: + rot = T.quat2mat(rot) + else: + rot = np.array([0, 0, self.rot]) + rot = T.euler2mat(rot) + + points = [(np.matmul(rot, p) + trans) for p in bbox_offsets] + return points + + def _remove_element(self, elem): + # # This method not currently working + # parent_elem = find_parent(self._obj, elem) + # parent_elem.remove(elem) + + # TODO: actually delete element? + # Below might actually be faster than searching for/deleting element + elem.set("rgba", "0 0 0 0") + elem.set("pos", "0 0 10") + elem.set("size", "0.01 0.01 0.01") + + @property + def nat_lang(self): + return self.name + + +class ProcGenFixture(Fixture): + def exclude_from_prefixing(self, inp): + """ + Exclude all shared materials and their associated names from being prefixed. + + Args: + inp (ET.Element or str): Element or its attribute to check for prefixing. + + Returns: + bool: True if we should exclude the associated name(s) with @inp from being prefixed with naming_prefix + """ + if "tex" in inp: + return True + + if isinstance(inp, ET.Element): + return inp.tag in ["texture"] + + return False diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture_stack.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture_stack.py new file mode 100644 index 0000000000000000000000000000000000000000..bbf0be645104b6905129ed513715e9251f7cde01 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture_stack.py @@ -0,0 +1,216 @@ +import numpy as np + +from robocasa.models.scenes.scene_utils import * +from robocasa.models.fixtures.cabinets import * +from robocasa.models.fixtures.others import Box + +# fixtures that can be used to form a stack +STACKABLE = { + "single_cabinet": SingleCabinet, + "hinge_cabinet": HingeCabinet, + "drawer": Drawer, + "panel_cabinet": PanelCabinet, + "box": Box, +} + + +class FixtureStack: + """ + Class for encapsulating a stack of stackable fixtures + + Args: + config (dict): configuration for the stack. Contains at least the following keys: + - size (list): [width, depth, height] of the stack + - levels (list): list of fixtures to stack on top of each other + - percentages (list): list of percentages of the height of each level + + scene_fixtures (dict): dictionary of fixtures in the scene + + scene_configs (dict): dictionary of configurations for fixtures in the scene + + scene_style (dict): dictionary of style information for fixtures in the scene + + base_height (float): height of the base of the stack + + base_overhang (float): how much the stack should overhang the base + """ + + def __init__( + self, + config, + scene_fixtures, + scene_configs, + scene_style, + base_height=0.05, + base_overhang=0.07, + default_texture=None, + rng=None, + ): + self._check_config_syntax(config) + self.config = config + + # for relative positioning purposes + self.origin_offset = np.array([0, 0, 0]) + self._scale = 1 + + # for base + self.base_height = base_height + self.base_overhang = base_overhang + + self.scene_style = scene_style + self.scene_configs = scene_configs + self.scene_fixtures = scene_fixtures + self.default_texture = default_texture + self.fixtures = list() + + if rng is not None: + self.rng = rng + else: + self.rng = np.random.default_rng() + + self._create_stack() + + def _create_stack(self): + """ + Creates the stack of fixtures by updating the scene fixtures and configs and placing their positions on top of each other + and next to each other if a level has two fixtures + """ + self.size = self.config["size"] + width_stack, depth, height_stack = self.size + + if "pos" in self.config: + self.pos = self.config["pos"] + else: + self.pos = get_relative_position( + self, + self.config, + self.scene_fixtures[self.config["align_to"]], + self.scene_configs[self.config["align_to"]], + ) + + x_stack, y, z_stack = self.pos + # incremented as levels are stacked + z_current = z_stack - height_stack / 2 + fxtr_count = 0 + + # add base for stack + if self.base_height > 0: + depth_base = depth - self.base_overhang + z_base = z_stack - height_stack / 2 - self.base_height / 2 + base_name = self.config["name"] + "_base" + + base_config = load_style_config(self.scene_style, {"type": "box"}) + base_config["pos"] = [x_stack, y + self.base_overhang / 2, z_base] + base_config["size"] = [width_stack, depth_base, self.base_height] + base_config["name"] = base_name + base_config["type"] = STACKABLE["box"] + for k in ["group_origin", "group_pos", "group_z_rot"]: + if k in self.config: + base_config[k] = self.config[k] + + if self.default_texture is not None: + base_config["texture"] = self.default_texture + base_config["rng"] = self.rng + base = initialize_fixture(base_config, self.scene_fixtures) + self.scene_fixtures[base_name] = base + self.scene_configs[base_name] = base_config + self.fixtures.append(base) + + # initialize layers, going from bottom to top + for i, level in enumerate(self.config["levels"]): + if type(level) == list: + # two fixtures in this level + fixtures = [ + [level[0], [x_stack - width_stack / 4, width_stack / 2]], + [level[1], [x_stack + width_stack / 4, width_stack / 2]], + ] + else: + fixtures = [[level, [x_stack, width_stack]]] + + for fixture, (x, width) in fixtures: + if fixture not in STACKABLE: + raise ValueError( + '"{}" is not a stackable fixture type'.format(fixture) + ) + + # find size and position of fixture + height = height_stack * self.config["percentages"][i] + z = z_current + height / 2 + + # get fixture config for fixture + fxtr_config = load_style_config(self.scene_style, {"type": fixture}) + fxtr_config["pos"] = [x, y, z] + fxtr_config["size"] = [width, depth, height] + + if "cabinet" in fixture: + fxtr_config["panel_config"] = fxtr_config.get("panel_config", {}) + fxtr_config["panel_config"]["handle_vpos"] = "top" + + fxtr_count += 1 + fxtr_name = self.config["name"] + "_" + str(fxtr_count) + fxtr_config["name"] = fxtr_name + fxtr_config["type"] = STACKABLE[fixture] + + # add in additional configurations as specified + if "configs" in self.config: + cfg_fixture = None + if fixture in self.config["configs"]: + cfg_fixture = fixture + elif f"{fixture}_{i + 1}" in self.config["configs"]: + cfg_fixture = f"{fixture}_{i + 1}" + + if cfg_fixture is not None: + for k, v in self.config["configs"][cfg_fixture].items(): + fxtr_config[k] = v + + # account for group rotations + for k in ["group_origin", "group_pos", "group_z_rot"]: + if k in self.config: + fxtr_config[k] = self.config[k] + + # for texture randomization, ensures all cabinets have the same color + if self.default_texture is not None and "texture" in fxtr_config: + fxtr_config["texture"] = self.default_texture + + # initialize fixture and add to scene fixtures and configs + fixture = initialize_fixture( + fxtr_config, self.scene_fixtures, rng=self.rng + ) + self.scene_fixtures[fxtr_name] = fixture + self.scene_configs[fxtr_name] = fxtr_config + self.fixtures.append(fixture) + + # increment z to move up a level + z_current += height + + @staticmethod + def _check_config_syntax(config): + """ + Checks the syntax of the config dictionary for the stack by making sure all required keys are present + and the values are well-formed + + Args: + config (dict): configuration for the stack + + Raises: + ValueError: [description] + """ + if "size" not in config or None in config["size"]: + raise ValueError( + "Size for stacks must be specified explicitely, " "received:", + config["size"], + ) + if "levels" not in config or "percentages" not in config: + raise ValueError( + 'Both "levels" and "percentages" ' "must be specified for fixture stack" + ) + if len(config["levels"]) != len(config["percentages"]): + raise ValueError( + '"levels" and "percentages" must have ' + "the same length for fixture stacks" + ) + for level in config["levels"]: + if type(level) == list and len(level) != 2: + raise ValueError( + "There can be at most 2 fixtures per level " "in fixture stacks" + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0b24a85788bf037ba42831061debafec875db15d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fixture_utils.py @@ -0,0 +1,106 @@ +from robocasa.models.fixtures import * + + +def fixture_is_type(fixture, fixture_type): + """ + Check if a fixture is of a certain type + + Args: + fixture (Fixture): The fixture to check + + fixture_type (FixtureType): The type to check against + """ + if fixture_type == FixtureType.COUNTER: + return isinstance(fixture, Counter) + elif fixture_type == FixtureType.DINING_COUNTER: + cls_check = any([isinstance(fixture, cls) for cls in [Counter]]) + if not cls_check: + return False + return fixture.width >= 2 or fixture.depth >= 2 + elif fixture_type == FixtureType.CABINET: + return isinstance(fixture, Cabinet) + elif fixture_type == FixtureType.DRAWER: + return isinstance(fixture, Drawer) + elif fixture_type == FixtureType.SINK: + return isinstance(fixture, Sink) + elif fixture_type == FixtureType.STOVE: + return isinstance(fixture, Stove) + elif fixture_type == FixtureType.CABINET_TOP: + cls_check = any( + [ + isinstance(fixture, cls) + for cls in [SingleCabinet, HingeCabinet, OpenCabinet] + ] + ) + if not cls_check: + return False + if "stack" in fixture.name: # wall stack cabinets not valid + return False + # check the height of the cabinet to see if it is a top cabinet + fxtr_bottom_z = fixture.pos[2] + fixture.bottom_offset[2] + height_check = 1.0 <= fxtr_bottom_z <= 1.60 + return height_check + elif fixture_type == FixtureType.MICROWAVE: + return isinstance(fixture, Microwave) + elif fixture_type in [FixtureType.DOOR_HINGE, FixtureType.DOOR_TOP_HINGE]: + cls_check = any( + [ + isinstance(fixture, cls) + for cls in [SingleCabinet, HingeCabinet, Microwave] + ] + ) + if not cls_check: + return False + if fixture_type == FixtureType.DOOR_TOP_HINGE: + if "stack" in fixture.name: # wall stack cabinets not valid + return False + fxtr_bottom_z = fixture.pos[2] + fixture.bottom_offset[2] + height_check = 1.0 <= fxtr_bottom_z <= 1.60 + if not height_check: + return False + return True + elif fixture_type in [ + FixtureType.DOOR_HINGE_SINGLE, + FixtureType.DOOR_TOP_HINGE_SINGLE, + ]: + cls_check = any( + [isinstance(fixture, cls) for cls in [SingleCabinet, Microwave]] + ) + if not cls_check: + return False + if fixture_type == FixtureType.DOOR_TOP_HINGE_SINGLE: + if "stack" in fixture.name: # wall stack cabinets not valid + return False + fxtr_bottom_z = fixture.pos[2] + fixture.bottom_offset[2] + height_check = 1.0 <= fxtr_bottom_z <= 1.60 + if not height_check: + return False + return True + elif fixture_type in [ + FixtureType.DOOR_HINGE_DOUBLE, + FixtureType.DOOR_TOP_HINGE_DOUBLE, + ]: + cls_check = any([isinstance(fixture, cls) for cls in [HingeCabinet]]) + if not cls_check: + return False + if fixture_type == FixtureType.DOOR_TOP_HINGE_DOUBLE: + if "stack" in fixture.name: # wall stack cabinets not valid + return False + fxtr_bottom_z = fixture.pos[2] + fixture.bottom_offset[2] + height_check = 1.0 <= fxtr_bottom_z <= 1.60 + if not height_check: + return False + return True + elif fixture_type == FixtureType.TOASTER: + return isinstance(fixture, Toaster) + elif fixture_type == FixtureType.TOP_DRAWER: + height_check = 0.7 <= fixture.pos[2] <= 0.9 + return height_check and isinstance(fixture, Drawer) + elif fixture_type == FixtureType.STOOL: + return isinstance(fixture, Stool) + elif fixture_type == FixtureType.ISLAND: + return isinstance(fixture, Counter) and "island" in fixture.name + elif fixture_type == FixtureType.COUNTER_NON_CORNER: + return isinstance(fixture, Counter) and "corner" not in fixture.name + else: + raise ValueError diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fridge.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fridge.py new file mode 100644 index 0000000000000000000000000000000000000000..a12b61325422255a72a45b747c4d26e16322f61a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/fridge.py @@ -0,0 +1,22 @@ +from robocasa.models.fixtures import Fixture + + +class Fridge(Fixture): + """ + Fridge fixture class + """ + + def __init__( + self, + xml="fixtures/appliances/fridges/pack_1/model.xml", + name="fridge", + *args, + **kwargs + ): + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + + @property + def nat_lang(self): + return "fridge" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/handles.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/handles.py new file mode 100644 index 0000000000000000000000000000000000000000..78fdf3763e4724df050b24ab78d437c5f6bd2646 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/handles.py @@ -0,0 +1,316 @@ +import abc +import os +from xml.etree import ElementTree as ET + +import numpy as np +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import find_elements, xml_path_completion + +import robocasa +from robocasa.models.objects import MujocoXMLObject +from robocasa.models.fixtures.fixture import get_texture_name_from_file + + +class Handle(MujocoXMLObject): + """ + Base class for all handles attached to cabinet/drawer panels + + Args: + name (str): Name of the handle + + xml (str): Path to the xml file of the handle + + panel_w (float): Width of the panel to attach the handle to + + panel_h (float): Height of the panel to attach the handle to + + texture (str): Path to the texture file of the handle + + orientation (str): Orientation of the handle. Can be either "horizontal" (for drawers) or "vertical" + + length (float): Length of the handle + """ + + def __init__( + self, + name, + xml, + panel_w, + panel_h, + texture="textures/metals/bright_metal.png", + orientation="vertical", + length=None, + ): + super().__init__( + xml_path_completion(xml, root=robocasa.models.assets_root), + name=name, + joints=None, + duplicate_collision_geoms=True, + ) + + self.length = length + self.orientation = orientation + self.texture = xml_path_completion(texture, root=robocasa.models.assets_root) + self.panel_w = panel_w + self.panel_h = panel_h + + # for hinge cabinets + self.side = None + + self._create_handle() + self._set_texture() + + @abc.abstractmethod + def _get_components(self): + raise NotImplementedError + + @abc.abstractmethod + def _create_handle(self, positions, sizes): + raise NotImplementedError + + def exclude_from_prefixing(self, inp): + """ + Exclude all shared materials and their associated names from being prefixed. + + Args: + inp (ET.Element or str): Element or its attribute to check for prefixing. + + Returns: + bool: True if we should exclude the associated name(s) with @inp from being prefixed with naming_prefix + """ + if "tex" in inp: + return True + + if isinstance(inp, ET.Element): + return inp.tag in ["texture"] + + return False + + def _set_texture(self): + """ + Set the texture of the handle + """ + # set texture + texture = find_elements( + self.root, tags="texture", attribs={"name": "tex"}, return_first=True + ) + tex_name = get_texture_name_from_file(self.texture) + texture.set("file", self.texture) + texture.set("name", tex_name) + + material = find_elements( + self.root, + tags="material", + attribs={"name": "{}_mat".format(self.name)}, + return_first=True, + ) + material.set("texture", tex_name) + + +class BarHandle(Handle): + """ + Creates a bar handle + + Args: + length (float): Length of the handle + + handle_pad (float): A minimum difference between handle length and cabinet panel height + """ + + def __init__( + self, + length=0.24, + # connector_pad=0.05, + handle_pad=0.04, + *args, + **kwargs + ): + # z-direction padding for top and bottom connectors + # self.connector_pad = connector_pad + # assert length > connector_pad * 2 + # z-direction padding for handle from sides of cabinet + self.handle_pad = handle_pad + + super().__init__( + xml="fixtures/handles/bar_handle.xml", length=length, *args, **kwargs + ) + + def _get_components(self): + """ + Get the geoms of the handle + """ + geom_names = ["handle", "handle_connector_top", "handle_connector_bottom"] + body_names = [] + joint_names = [] + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_handle(self): + """ + Calculates and sets and positions and sizes of each component of the handles + Treats the three types of cabinets separately + """ + + # adjust handle size if necessary + if self.panel_h < self.length + 2 * self.handle_pad: + self.length = self.panel_h - 2 * self.handle_pad + # if self.length < 3 * self.connector_pad: + # raise ValueError("Cabinet size {:.3f} is too small for " \ + # "bar handles.".format(self.panel_h)) + + offset = self.length / 2 * 0.60 # - self.connector_pad + # distance between main handle and door + conn_len = 0.05 + + # calculate positions for each component + positions = { + "handle": np.array([0, -conn_len, 0]), + "handle_connector_top": np.array([0, -conn_len / 2, offset]), + "handle_connector_bottom": np.array([0, -conn_len / 2, -offset]), + } + sizes = { + "handle": [0.013, self.length / 2], + "handle_connector_top": [0.008, conn_len / 2], + "handle_connector_bottom": [0.008, conn_len / 2], + } + eulers = {} + + if self.orientation == "horizontal": + positions["handle_connector_top"][[0, 2]] = positions[ + "handle_connector_top" + ][[2, 0]] + positions["handle_connector_bottom"][[0, 2]] = positions[ + "handle_connector_bottom" + ][[2, 0]] + eulers["handle"] = [0, 1.5708, 0] + + geoms, bodies, joints = self._get_components() + for side in positions.keys(): + for geom in geoms[side]: + if geom is None: + continue + geom.set("pos", a2s(positions[side])) + geom.set("size", a2s(sizes[side])) + + if eulers.get(side) is not None: + geom.set("euler", a2s(eulers[side])) + + +class BoxedHandle(Handle): + """ + Creates a boxed handle + + Args: + length (float): Length of the handle + + handle_pad (float): A minimum difference between handle length and cabinet panel height + """ + + def __init__(self, length=0.24, handle_pad=0.04, *args, **kwargs): + self.handle_pad = handle_pad + super().__init__( + xml="fixtures/handles/boxed_handle.xml", length=length, *args, **kwargs + ) + + def _get_components(self): + """ + Get the geoms of the handle + """ + geom_names = ["handle", "handle_connector_top", "handle_connector_bottom"] + body_names = [] + joint_names = [] + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_handle(self): + """ + Calculates and sets and positions and sizes of each component of the handles + Treats the three types of cabinets separately + """ + + # adjust handle size if necessary + if self.panel_h < self.length + 2 * self.handle_pad: + self.length = self.panel_h - 2 * self.handle_pad + + conn_len = 0.05 + connector_depth = (conn_len / 2) - 0.01 + connector_zpos = (self.length / 2) - 0.01 + + # calculate positions for each component + positions = { + "handle": np.array([0, -conn_len, 0]), + "handle_connector_top": np.array([0, -conn_len / 2, connector_zpos]), + "handle_connector_bottom": np.array([0, -conn_len / 2, -connector_zpos]), + } + sizes = { + "handle": [0.01, 0.01, self.length / 2], + "handle_connector_top": [0.01, 0.01, connector_depth], + "handle_connector_bottom": [0.01, 0.01, connector_depth], + } + eulers = {} + + if self.orientation == "horizontal": + positions["handle_connector_top"][[0, 2]] = positions[ + "handle_connector_top" + ][[2, 0]] + positions["handle_connector_bottom"][[0, 2]] = positions[ + "handle_connector_bottom" + ][[2, 0]] + eulers["handle"] = [0, 1.5708, 0] + + geoms, bodies, joints = self._get_components() + for side in positions.keys(): + for geom in geoms[side]: + if geom is None: + continue + geom.set("pos", a2s(positions[side])) + geom.set("size", a2s(sizes[side])) + + if eulers.get(side) is not None: + geom.set("euler", a2s(eulers[side])) + + +class KnobHandle(Handle): + """ + Creates a knob handle + """ + + def __init__(self, handle_pad=0.07, *args, **kwargs): + super().__init__( + xml="fixtures/handles/knob_handle.xml", + # length=length, + *args, + **kwargs + ) + + # z-direction padding for handle from sides of cabinet + self.handle_pad = handle_pad + + def _get_components(self): + """ + Get the geoms of the handle + """ + geom_names = ["handle"] + body_names = [] + joint_names = [] + return self._get_elements_by_name(geom_names, body_names, joint_names) + + def _create_handle(self): + """ + Calculates and sets and positions and sizes of each component of the handles + """ + + # calculate positions for each component + positions = { + "handle": np.array([0, -0.017, 0]), + } + # radius, depth + sizes = { + "handle": [0.015, 0.017], + } + + geoms, bodies, joints = self._get_components() + for side in positions.keys(): + for geom in geoms[side]: + if geom is None: + continue + geom.set("pos", a2s(positions[side])) + geom.set("size", a2s(sizes[side])) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/hood.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/hood.py new file mode 100644 index 0000000000000000000000000000000000000000..ff4cfc536036225f9ad638780990f643fcc4df6f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/hood.py @@ -0,0 +1,22 @@ +from copy import deepcopy + +import numpy as np + +from robocasa.models.fixtures import Fixture + + +class Hood(Fixture): + """ + Hood fixture class + """ + + def __init__( + self, xml="fixtures/hoods/basic_silver.xml", name="hood", *args, **kwargs + ): + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + + @property + def nat_lang(self): + return "range hood" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/microwave.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/microwave.py new file mode 100644 index 0000000000000000000000000000000000000000..30a74ec1730fc968230101402a7278f991b026fd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/microwave.py @@ -0,0 +1,151 @@ +import numpy as np + +import robocasa.utils.object_utils as OU +from robocasa.models.fixtures import Fixture + + +class Microwave(Fixture): + """ + Microwave fixture class. Supports turning on and off the microwave, and opening and closing the door + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + """ + + def __init__( + self, + xml="fixtures/microwaves/orig_microwave", + name="microwave", + *args, + **kwargs, + ): + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + self._turned_on = False + + def set_door_state(self, min, max, env, rng): + """ + Sets how open the door is. Chooses a random amount between min and max. + Min and max are percentages of how open the door is + + Args: + min (float): minimum percentage of how open the door is + + max (float): maximum percentage of how open the door is + + env (MujocoEnv): environment + + rng (np.random.Generator): random number generator + + """ + assert 0 <= min <= 1 and 0 <= max <= 1 and min <= max + + joint_min = 0 + joint_max = np.pi / 2 + + desired_min = joint_min + (joint_max - joint_min) * min + desired_max = joint_min + (joint_max - joint_min) * max + + sign = -1 + + env.sim.data.set_joint_qpos( + "{}_microjoint".format(self.name), + sign * rng.uniform(desired_min, desired_max), + ) + + def get_door_state(self, env): + """ + Args: + env (MujocoEnv): environment + + Returns: + dict: maps door name to a percentage of how open the door is + """ + sim = env.sim + hinge_qpos = sim.data.qpos[sim.model.joint_name2id(f"{self.name}_microjoint")] + hinge_qpos = -hinge_qpos # negate as micro joints are left door hinges + + # convert to percentages + door = OU.normalize_joint_value(hinge_qpos, joint_min=0, joint_max=np.pi / 2) + + return { + "door": door, + } + + def get_state(self): + """ + Returns: + dict: maps turned_on to whether the microwave is turned on + """ + state = dict( + turned_on=self._turned_on, + ) + return state + + @property + def handle_name(self): + return "{}_door_handle".format(self.name) + + @property + def door_name(self): + return "{}_door".format(self.name) + + def update_state(self, env): + """ + If the microwave is open, the state is set to off. Otherwise, if the gripper + is pressing the start button, the microwave will stay/turn on. If the gripper is + pressing the stop button, the microwave will stay/turn off. + + Args: + env (MujocoEnv): The environment to check the state of the microwave in + + """ + start_button_pressed = env.check_contact( + env.robots[0].gripper["right"], "{}_start_button".format(self.name) + ) + stop_button_pressed = env.check_contact( + env.robots[0].gripper["right"], "{}_stop_button".format(self.name) + ) + + door_state = self.get_door_state(env)["door"] + door_open = door_state > 0.005 + + if door_open: + self._turned_on = False + else: + if self._turned_on is True and stop_button_pressed: + self._turned_on = False + elif self._turned_on is False and start_button_pressed: + self._turned_on = True + + def gripper_button_far(self, env, button, th=0.15): + """ + check whether gripper is far from the start button + + Args: + env (MujocoEnv): The environment to check the state of the microwave in + + button (str): button to check + + th (float): threshold for distance between gripper and button + + Returns: + bool: True if gripper is far from the button, False otherwise + """ + assert button in ["start_button", "stop_button"] + button_id = env.sim.model.geom_name2id( + "{}{}".format(self.naming_prefix, button) + ) + button_pos = env.sim.data.geom_xpos[button_id] + gripper_site_pos = env.sim.data.site_xpos[env.robots[0].eef_site_id["right"]] + + gripper_button_far = np.linalg.norm(gripper_site_pos - button_pos) > th + + return gripper_button_far + + @property + def nat_lang(self): + return "microwave" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/others.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/others.py new file mode 100644 index 0000000000000000000000000000000000000000..5397a03c54507b570029ccc3879f760f68d2877f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/others.py @@ -0,0 +1,287 @@ +import xml.etree.ElementTree as ET +from copy import deepcopy + +import numpy as np +from robosuite.models.objects import BoxObject +from robosuite.utils.mjcf_utils import CustomMaterial +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import string_to_array as s2a +from robosuite.utils.mjcf_utils import xml_path_completion + +import robocasa +from robocasa.models.fixtures import Fixture + + +class Box(BoxObject): + """ + Initializes a box object. Mainly used for filling in gaps in the environment like in corners or beneath bottom cabinets + + Args: + pos (list): position of the object + + size (list): size of the object + + name (str): name of the object + + texture (str): path to texture file + + mat_attrib (dict): material attributes + + tex_attrib (dict): texture attributes + """ + + def __init__( + self, + pos, + size, + name="box", + texture="textures/wood/dark_wood_parquet.png", + mat_attrib={"shininess": "0.1"}, + tex_attrib={"type": "cube"}, + rng=None, + *args, + **kwargs + ): + texture = xml_path_completion(texture, root=robocasa.models.assets_root) + material = CustomMaterial( + texture=texture, + tex_name="box", + mat_name="box_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + shared=True, + ) + + super().__init__( + name=name, + material=material, + joints=None, + # divide by 2 per mujoco convention + size=[x / 2 for x in size], + ) + + self.size = size + self.pos = pos + if pos is not None: + self._obj.set("pos", a2s(pos)) + + # for relative positioning + self.origin_offset = np.array([0, 0, 0]) + self.scale = 1 + + if rng is not None: + self.rng = rng + else: + self.rng = np.random.default_rng() + + def set_pos(self, pos): + """ + Set the position of the object + + Args: + pos (list): position of the object + """ + self.pos = pos + self._obj.set("pos", a2s(pos)) + + def update_state(self, env): + pass + + @property + def rot(self): + """ + Returns the rotation of the object only on the z-axis + + Returns: + float: rotation + """ + rot = s2a(self._obj.get("euler", "0.0 0.0 0.0")) + return rot[2] + + +class Wall(BoxObject): + """ + Initializes a wall object. Used for creating walls in the environment + + Args: + name (str): name of the object + + texture (str): path to texture file + + pos (list): position of the object + + quat (list): quaternion of the object + + size (list): size of the object + + wall_side (str): which side the wall is on (back, front, left, right, floor) + + mat_attrib (dict): material attributes + + tex_attrib (dict): texture attributes + + backing (bool): whether this is a backing wall + + backing_extended (list): whether the backing is extended on the left and right + + default_wall_th (float): default thickness of the wall + + default_backing_th (float): default thickness of the backing + """ + + def __init__( + self, + name="wall", + texture="textures/bricks/white_bricks.png", + pos=None, + quat=None, + size=None, + wall_side="back", + mat_attrib={ + "texrepeat": "3 3", + "reflectance": "0.1", + "shininess": "0.1", + "texuniform": "true", + }, + tex_attrib={"type": "2d"}, + # parameters used for alignment + backing=False, + backing_extended=[False, False], + default_wall_th=0.02, + default_backing_th=0.1, + rng=None, + *args, + **kwargs + ): + # change texture if used for backing + if backing: + texture = "textures/flat/light_gray.png" + texture = xml_path_completion(texture, root=robocasa.models.assets_root) + material = CustomMaterial( + texture=texture, + tex_name="wall", + mat_name="wall_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + ) + + self.wall_side = wall_side + # set the rotation according to which side the wall is on + if self.wall_side is not None: + quat = self.get_quat() + + # align everything to account for thickness & backing + if self.wall_side == "floor": + size[0] += default_wall_th * 2 + size[1] += default_wall_th * 2 + pos[2] -= size[2] + if backing: + pos[2] -= default_wall_th * 2 + else: + size[0] += default_wall_th * 2 + shift = size[2] if not backing else size[2] + default_wall_th * 2 + if self.wall_side == "left": + pos[0] -= shift + elif self.wall_side == "right": + pos[0] += shift + elif self.wall_side == "back": + pos[1] += shift + elif self.wall_side == "front": + pos[1] -= shift + + if backing: + size[1] += default_wall_th + default_backing_th + pos[2] -= default_wall_th + default_backing_th + + # extend left/right side to form a perfect box + if backing_extended[0]: + size[0] += default_backing_th + if self.wall_side in ["left", "right"]: + pos[1] += default_backing_th + else: + pos[0] -= default_backing_th + if backing_extended[1]: + size[0] += default_backing_th + if self.wall_side in ["left", "right"]: + pos[1] -= default_backing_th + else: + pos[0] += default_backing_th + + super().__init__( + name=name, material=material, joints=None, size=size, *args, **kwargs + ) + + self.pos = pos + if pos is not None: + self._obj.set("pos", a2s(pos)) + if quat is not None: + self._obj.set("quat", a2s(quat)) + + if rng is not None: + self.rng = rng + else: + self.rng = np.random.default_rng() + + def set_pos(self, pos): + """ + Set the position of the object + + Args: + pos (list): position of the object + """ + self.pos = pos + self._obj.set("pos", a2s(pos)) + + def get_quat(self): + """ + Returns the quaternion of the object based on the wall side + + Returns: + list: quaternion + """ + side_rots = { + "back": [-0.707, 0.707, 0, 0], + "front": [0, 0, 0.707, -0.707], + "left": [0.5, 0.5, -0.5, -0.5], + "right": [0.5, -0.5, -0.5, 0.5], + "floor": [0.707, 0, 0, 0.707], + } + if self.wall_side not in side_rots: + raise ValueError() + return side_rots[self.wall_side] + + def update_state(self, env): + pass + + +class Floor(Wall): + def __init__( + self, + size, + name="wall", + texture="textures/bricks/red_bricks.png", + mat_attrib={ + "texrepeat": "2 2", + "texuniform": "true", + "reflectance": "0.1", + "shininess": "0.1", + }, + *args, + **kwargs + ): + # swap x, y axes due to rotation + size = [size[1], size[0], size[2]] + + texture = xml_path_completion(texture, root=robocasa.models.assets_root) + + # everything is the same except the plane is rotated to be horizontal + super().__init__( + name, + texture, + # horizontal plane + wall_side="floor", + size=size, + mat_attrib=mat_attrib, + *args, + **kwargs + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/sink.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/sink.py new file mode 100644 index 0000000000000000000000000000000000000000..36341b971585119729552f383636529d32d36c9d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/sink.py @@ -0,0 +1,138 @@ +from copy import deepcopy + +import numpy as np + +from robocasa.models.fixtures import Fixture + + +class Sink(Fixture): + """ + Sink fixture class. The sink has a handle_joint that can be turned on and off to simulate water flow + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + """ + + def __init__(self, xml="fixtures/sink.xml", name="sink", *args, **kwargs): + self._handle_joint = None + self._water_site = None + + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + + def update_state(self, env): + """ + Updates the water flowing of the sink based on the handle_joint position + + Args: + env (MujocoEnv): environment + """ + state = self.get_handle_state(env) + water_on = state["water_on"] + + site_id = env.sim.model.site_name2id("{}water".format(self.naming_prefix)) + + if water_on: + env.sim.model.site_rgba[site_id][3] = 0.5 + else: + env.sim.model.site_rgba[site_id][3] = 0.0 + + def set_handle_state(self, env, rng, mode="on"): + """ + Sets the state of the handle_joint based on the mode parameter + + Args: + env (MujocoEnv): environment + + rng (np.random.Generator): random number generator + + mode (str): "on", "off", or "random" + """ + assert mode in ["on", "off", "random"] + if mode == "random": + mode = rng.choice(["on", "off"]) + + if mode == "off": + joint_val = 0.0 + elif mode == "on": + joint_val = rng.uniform(0.40, 0.50) + + env.sim.data.set_joint_qpos( + "{}handle_joint".format(self.naming_prefix), joint_val + ) + + def get_handle_state(self, env): + """ + Gets the state of the handle_joint + + Args: + env (MujocoEnv): environment + + Returns: + dict: maps handle_joint to the angle of the handle_joint, water_on to whether the water is flowing, + spout_joint to the angle of the spout_joint, and spout_ori to the orientation of the spout (left, right, center) + """ + handle_state = {} + if self.handle_joint is None: + return handle_state + + handle_joint_id = env.sim.model.joint_name2id( + "{}handle_joint".format(self.naming_prefix) + ) + handle_joint_qpos = deepcopy(env.sim.data.qpos[handle_joint_id]) + handle_joint_qpos = handle_joint_qpos % (2 * np.pi) + if handle_joint_qpos < 0: + handle_joint_qpos += 2 * np.pi + handle_state["handle_joint"] = handle_joint_qpos + handle_state["water_on"] = 0.40 < handle_joint_qpos < np.pi + + spout_joint_id = env.sim.model.joint_name2id( + "{}spout_joint".format(self.naming_prefix) + ) + spout_joint_qpos = deepcopy(env.sim.data.qpos[spout_joint_id]) + spout_joint_qpos = spout_joint_qpos % (2 * np.pi) + if spout_joint_qpos < 0: + spout_joint_qpos += 2 * np.pi + handle_state["spout_joint"] = spout_joint_qpos + if np.pi <= spout_joint_qpos <= 2 * np.pi - np.pi / 6: + spout_ori = "left" + elif np.pi / 6 <= spout_joint_qpos <= np.pi: + spout_ori = "right" + else: + spout_ori = "center" + handle_state["spout_ori"] = spout_ori + + return handle_state + + @property + def handle_joint(self): + """ + Returns the joint element which represents the handle_joint of the sink + """ + if self._handle_joint is None: + self._handle_joint = self.worldbody.find( + "./body/body/body/joint[@name='{}handle_joint']".format( + self.naming_prefix + ) + ) + + return self._handle_joint + + @property + def water_site(self): + """ + Returns the site element which represents the water flow of the sink + """ + if self._water_site is None: + self._water_site = self.worldbody.find( + "./body/body/body/site[@name='{}water']".format(self.naming_prefix) + ) + + return self._water_site + + @property + def nat_lang(self): + return "sink" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/stove.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/stove.py new file mode 100644 index 0000000000000000000000000000000000000000..ebca650803b65c3725be2250127e560a1420e045 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/stove.py @@ -0,0 +1,236 @@ +from copy import deepcopy + +import numpy as np + +from robocasa.models.fixtures import Fixture + +STOVE_LOCATIONS = [ + "rear_left", + "rear_center", + "rear_right", + "front_left", + "front_center", + "front_right", + "center", +] + + +class Stove(Fixture): + """ + Stove fixture class. The stove has knob joints that can be turned on and off to simulate burner flames + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + """ + + def __init__(self, xml="fixtures/stoves/stove_orig", name="stove", *args, **kwargs): + + self._knob_joints = None + self._burner_sites = None + + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + + def get_reset_regions(self, env, locs=None): + """ + Returns dictionary of reset regions, usually used when initializing a receptacle on the stove. + The regions are the sites where the burner flames are located. + + Args: + env (MujocoEnv): environment + + locs (list): list of locations to get reset regions for. If None, uses all locations + + Returns: + dict: dictionary of reset regions + """ + regions = dict() + + if locs is None: + locs = STOVE_LOCATIONS + for location in locs: + site = self.worldbody.find( + "./body/body/site[@name='{}burner_{}_place_site']".format( + self.naming_prefix, location + ) + ) + if site is None: + site = self.worldbody.find( + "./body/body/site[@name='{}burner_on_{}']".format( + self.naming_prefix, location + ) + ) + if site is None: + continue + burner_pos = [float(x) for x in site.get("pos").split()] + regions[location] = { + "offset": burner_pos, + "size": [0.10, 0.10], + } + + return regions + + def update_state(self, env): + """ + Updates the burner flames of the stove based on the knob joint positions + + Args: + env (MujocoEnv): environment + """ + for location in STOVE_LOCATIONS: + site = self.burner_sites[location] + if site is None: + continue + site_id = env.sim.model.site_name2id( + "{}burner_on_{}".format(self.naming_prefix, location) + ) + + joint = self.knob_joints[location] + if joint is None: + env.sim.model.site_rgba[site_id][3] = 0.0 + continue + joint_id = env.sim.model.joint_name2id( + "{}knob_{}_joint".format(self.naming_prefix, location) + ) + + joint_qpos = deepcopy(env.sim.data.qpos[joint_id]) + joint_qpos = joint_qpos % (2 * np.pi) + if joint_qpos < 0: + joint_qpos += 2 * np.pi + + if 0.35 <= np.abs(joint_qpos) <= 2 * np.pi - 0.35: + env.sim.model.site_rgba[site_id][3] = 0.5 + else: + env.sim.model.site_rgba[site_id][3] = 0.0 + + def set_knob_state(self, env, rng, knob, mode="on"): + """ + Sets the state of the knob joint based on the mode parameter + + Args: + env (MujocoEnv): environment + + rng (np.random.RandomState): random number generator + + knob (str): location of the knob + + mode (str): "on" or "off" + """ + assert mode in ["on", "off"] + if mode == "off": + joint_val = 0.0 + else: + if self.rng.uniform() < 0.5: + joint_val = rng.uniform(0.50, np.pi / 2) + else: + joint_val = rng.uniform(2 * np.pi - np.pi / 2, 2 * np.pi - 0.50) + + env.sim.data.set_joint_qpos( + "{}knob_{}_joint".format(self.naming_prefix, knob), joint_val + ) + + def get_knobs_state(self, env): + """ + Gets the angle of which knob joints are turned + + Args: + env (MujocoEnv): environment + + Returns: + dict: maps location of knob to the angle of the knob joint + """ + knobs_state = {} + for location in STOVE_LOCATIONS: + joint = self.knob_joints[location] + if joint is None: + continue + site = self.burner_sites[location] + if site is None: + continue + + joint_id = env.sim.model.joint_name2id( + "{}knob_{}_joint".format(self.naming_prefix, location) + ) + + joint_qpos = deepcopy(env.sim.data.qpos[joint_id]) + joint_qpos = joint_qpos % (2 * np.pi) + if joint_qpos < 0: + joint_qpos += 2 * np.pi + + knobs_state[location] = joint_qpos + return knobs_state + + @property + def knob_joints(self): + """ + Returns the knob joints of the stove + """ + if self._knob_joints is None: + self._knob_joints = {} + for location in STOVE_LOCATIONS: + joint = self.worldbody.find( + "./body/body/body/joint[@name='{}knob_{}_joint']".format( + self.naming_prefix, location + ) + ) + self._knob_joints[location] = joint + + return self._knob_joints + + @property + def burner_sites(self): + """ + Returns the burner sites of the stove + """ + if self._burner_sites is None: + self._burner_sites = {} + for location in STOVE_LOCATIONS: + site = self.worldbody.find( + "./body/body/site[@name='{}burner_on_{}']".format( + self.naming_prefix, location + ) + ) + self._burner_sites[location] = site + + return self._burner_sites + + @property + def nat_lang(self): + return "stove" + + +class Stovetop(Stove): + """ + Stovetop fixture class. The stovetop has knob joints that can be turned on and off to simulate burner flames + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + """ + + def __init__(self, xml="fixtures/stoves/stove_orig", name="stove", *args, **kwargs): + super().__init__(xml=xml, name=name, *args, **kwargs) + + +class Oven(Fixture): + """ + Oven fixture class + + Args: + xml (str): path to mjcf xml file + + name (str): name of the object + """ + + def __init__(self, xml="fixtures/ovens/samsung", name="oven", *args, **kwargs): + super().__init__( + xml=xml, name=name, duplicate_collision_geoms=False, *args, **kwargs + ) + + @property + def nat_lang(self): + return "oven" diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/windows.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/windows.py new file mode 100644 index 0000000000000000000000000000000000000000..46f17b1532673ed2e976823c83a12849a7b24b95 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/fixtures/windows.py @@ -0,0 +1,334 @@ +import numpy as np +from robosuite.models.objects import BoxObject, CompositeBodyObject +from robosuite.utils.mjcf_utils import CustomMaterial +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import string_to_array as s2a +from robosuite.utils.mjcf_utils import xml_path_completion + +import robocasa + + +class Window(CompositeBodyObject): + """ + Window object. Supports creating windows with trim and glass. Proceduraly generated object (no xml needed) + + Args: + name (str): name of the object + + size (list): size of the window(s) (considers multiple windows in the x-direction) + + ofs (list): offset of the window + + pos (list): position of the window + + quat (list): quaternion of the window + + window_bak (str): path to the window background texture + + texture (str): path to the window pane texture + + trim_th (float): thickness of the trim (depth/protrusion of the trim from the window pane) + + trim_size (float): size of the trim + + num_windows (int): number of windows placed side-by-side + """ + + def __init__( + self, + name, + size, + ofs=None, + pos=None, + quat=None, + window_bak="textures/others/bk7.png", + texture="textures/flat/white.png", + trim_th=0.02, + trim_size=0.015, + num_windows=1, + rng=None, + ): + self.size = size + self.origin_offset = [0, 0, 0] + self.window_size = [size[0] / num_windows, size[1], size[2]] + self.texture = xml_path_completion(texture, robocasa.models.assets_root) + self.window_bak = xml_path_completion(window_bak, robocasa.models.assets_root) + self.num_windows = num_windows + self.pos = [0, 0, 0] if pos is None else pos + tex_attrib = {"type": "2d"} + # now do not consider passed in quat bc havent combined + # wanted quat with the rotation applied to the window + # self.quats = quat + self.quats = [] + self.trim_size = trim_size + self.trim_th = trim_th + trim_mat_attrib = { + "texrepeat": "4 4", + "specular": "0.1", + "shininess": "0.1", + "texuniform": "true", + } + + mat_attrib = { + "texrepeat": "1 1", + "specular": "0.1", + "shininess": "0.1", + "texuniform": "true", + } + self.trim_mat = CustomMaterial( + texture=self.texture, + tex_name="panel_tex", + mat_name="panel_mat", + tex_attrib=tex_attrib, + mat_attrib=trim_mat_attrib, + shared=True, + ) + self.window_mat = CustomMaterial( + texture=self.window_bak, + tex_name="blurred_bak", + mat_name="window_mat", + tex_attrib=tex_attrib, + mat_attrib=mat_attrib, + shared=True, + ) + + self.center = np.array([0, 0, 0]) + self.scale = 1.0 + self.num_windows = num_windows + self.ofs = ofs if ofs is not None else [0.0, 0.0, 0.0] + self.ofs = np.array(self.ofs) + + self.create_window() + + super().__init__( + name=name, + objects=self.objects, + object_locations=self.positions, + object_quats=self.quats, + joints=None, + ) + + if rng is not None: + self.rng = rng + else: + self.rng = np.random.default_rng() + # change to create objects then create positions + + def create_window(self): + """ + Creates the window object with trim and glass by setting the relevant sizes and positions of the geoms in the window. + This is very similar to the create panel functions in the cabinet panel classes + """ + x, y, z = self.window_size + x, y, z = x / 2, y / 2, z / 2 + # should change door to panel + door_th = y - self.trim_th + sizes = [ + [self.trim_size, self.trim_th, z], + [self.trim_size, self.trim_th, z], + [x - 2 * self.trim_size, self.trim_th, self.trim_size], + [x - 2 * self.trim_size, self.trim_th, self.trim_size], + [self.trim_size / 2, self.trim_th, z], + [x - 2 * self.trim_size, self.trim_th, self.trim_size / 2], + ] * self.num_windows + + # switch y and z sizes because we will rotate + # we are doing this because textures are only displayed on the z-parallel part of the box + sizes.append([x * self.num_windows, z, door_th]) + + base_names = [ + "trim_left", + "trim_right", + "trim_top", + "trim_bottom", + "vert_trim", + "horiz_trim", + ] + names = [f"{name}_{i}" for i in range(self.num_windows) for name in base_names] + names.append("door") + + offsets = self._get_window_offsets() + positions = [] + + for offset in offsets: + positions.extend( + [ + np.array([-x + self.trim_size + offset, -0.0045, 0]), + np.array([x - self.trim_size + offset, -0.0045, 0]), + np.array([offset, -0.0045, z - self.trim_size]), + np.array([offset, -0.0045, -z + self.trim_size]), + np.array([offset, -0.0045, 0]), + np.array([offset, -0.0045, 0]), + ] + ) + positions.append(np.array([0, 0, 0])) + + objects = [] + for obj_name, size in zip(names, sizes): + if "door" in obj_name: + new_obj = BoxObject( + name=obj_name, size=np.array(size), material=self.window_mat + ) + else: + new_obj = BoxObject( + name=obj_name, size=np.array(size), material=self.trim_mat + ) + objects.append(new_obj) + + self.objects = objects + self.positions = [position + self.ofs for position in positions] + self.quats = [None] * (len(objects) - 1) + self.quats.append([0, 0, 0.7071081, 0.7071055]) + + def _get_window_offsets(self): + """ + Gets x-direction offsets for the windows. This is relevant when creating multiple individual windows + which are placed side-by-side + """ + x = self.window_size[0] / 2 + start = (-self.size[0] / 2) + x + end = self.size[0] / 2 - x + offsets = np.linspace(start, end, self.num_windows) + return offsets + + def set_pos(self, pos): + """ + Set the position of the window + + Args: + pos (list): position of the window + """ + self.pos = pos + self._obj.set("pos", a2s(pos)) + + def update_state(self, env): + return + + @property + def nat_lang(self): + return "windows" + + @property + def rot(self): + rot = s2a(self._obj.get("euler", "0.0 0.0 0.0")) + return rot[2] + + +class FramedWindow(Window): + """ + Window object with a frame around it + + Args: + name (str): name of the object + + size (list): size of the window(s) (considers multiple windows in the x-direction) + + ofs (list): offset of the window + + pos (list): position of the window + + quat (list): quaternion of the window + + window_bak (str): path to the window background texture + + texture (str): path to the window pane texture + + trim_th (float): thickness of the trim (depth/protrusion of the trim from the window pane) + + trim_size (float): size of the trim + + num_windows (int): number of windows placed side-by-side + + frame_width (float): width of the frame around the window + """ + + def __init__( + self, + name, + size, + ofs=None, + pos=None, + quat=None, + window_bak="textures/others/bk7.png", + texture="textures/flat/white.png", + trim_th=0.02, + trim_size=0.015, + num_windows=1, + frame_width=0.05, + rng=None, + ): + + self.frame_width = frame_width + super().__init__( + name=name, + size=size, + ofs=ofs, + pos=pos, + quat=quat, + window_bak=window_bak, + texture=texture, + trim_th=trim_th, + trim_size=trim_size, + num_windows=num_windows, + rng=rng, + ) + + def create_window(self): + """ + Creates the window object with trim and glass and frame by setting the relevant sizes and positions of the geoms in the window. + """ + self.window_size = [ + (self.size[0] - self.frame_width) / self.num_windows, + self.size[1], + self.size[2] - self.frame_width, + ] + super().create_window() + + # created the window now add the frame! + x, y, z = self.window_size + x, y, z = x / 2, y / 2, z / 2 + sizes = [ + [self.size[0] / 2, y, self.frame_width / 4], + [self.size[0] / 2, y, self.frame_width / 4], + [self.frame_width / 4, y, z], + [self.frame_width / 4, y, z], + ] + + names = ["frame_top", "frame_bot", "frame_right", "frame_left"] + val = (self.size[0] - self.frame_width) / 2 + frame_positions = [ + np.array([0, 0.00145, z + self.frame_width / 4]), + np.array([0, 0.00145, -z - self.frame_width / 4]), + np.array([val + self.frame_width / 4, 0.00145, 0]), + np.array([-val - self.frame_width / 4, 0.00145, 0]), + ] + new_positions = [frame_pos + self.ofs for frame_pos in frame_positions] + self.positions.extend(new_positions) + self.quats.extend([None] * len(new_positions)) + + for obj_name, size in zip(names, sizes): + self.objects.append( + BoxObject(name=obj_name, size=np.array(size), material=self.trim_mat) + ) + + def _get_window_offsets(self): + """ + Gets x-direction offsets for the windows. This is relevant when creating multiple individual windows + which are placed side-by-side. This is different than the super class because we need to account for the frame width + """ + x = self.window_size[0] / 2 + start = ((self.frame_width - self.size[0]) / 2) + x + end = ((self.size[0] - self.frame_width) / 2) - x + offsets = np.linspace(start, end, self.num_windows) + return offsets + + def set_pos(self, pos): + """ + Set the position of the window + + Args: + pos (list): position of the window + + """ + self.pos = pos + self._obj.set("pos", a2s(pos)) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ed1f45df300dbe505d959942927074c81d5f28f4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/__init__.py @@ -0,0 +1,2 @@ +from robosuite.models.objects import * +from robosuite.utils import * diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/kitchen_object_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/kitchen_object_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..ff9f85d7242c15b4a734907ea56911f746b5a66d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/kitchen_object_utils.py @@ -0,0 +1,428 @@ +import math +import os +import xml.etree.ElementTree as ET +from copy import deepcopy + +import numpy as np +from robosuite.utils.mjcf_utils import find_elements, string_to_array + +import robocasa +from robocasa.models.objects.kitchen_objects import OBJ_CATEGORIES, OBJ_GROUPS + +BASE_ASSET_ZOO_PATH = os.path.join(robocasa.models.assets_root, "objects") + + +class ObjCat: + """ + Class that encapsulates data for an object category. + + Args: + name (str): name of the object category + + types (tuple) or (str): type(s)/categories the object belongs to. Examples include meat, sweets, fruit, etc. + + model_folders (list): list of folders containing the MJCF models for the object category + + exclude (list): list of model names to exclude + + graspable (bool): whether the object is graspable + + washable (bool): whether the object is washable + + microwavable (bool): whether the object is microwavable + + cookable (bool): whether the object is cookable + + freezable (bool): whether the object is freezable + + scale (float): scale of the object meshes/geoms + + solimp (tuple): solimp values for the object meshes/geoms + + solref (tuple): solref values for the object meshes/geoms + + density (float): density of the object meshes/geoms + + friction (tuple): friction values for the object meshes/geoms + + priority: priority of the object + + aigen_cat (bool): True if the object is an AI-generated object otherwise its an objaverse object + """ + + def __init__( + self, + name, + types, + model_folders=None, + exclude=None, + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + scale=1.0, + solimp=(0.998, 0.998, 0.001), + solref=(0.001, 2), + density=100, + friction=(0.95, 0.3, 0.1), + priority=None, + aigen_cat=False, + ): + self.name = name + if not isinstance(types, tuple): + types = (types,) + self.types = types + + self.aigen_cat = aigen_cat + + self.graspable = graspable + self.washable = washable + self.microwavable = microwavable + self.cookable = cookable + self.freezable = freezable + + self.scale = scale + self.solimp = solimp + self.solref = solref + self.density = density + self.friction = friction + self.priority = priority + self.exclude = exclude or [] + + if model_folders is None: + subf = "aigen_objs" if self.aigen_cat else "objaverse" + model_folders = ["{}/{}".format(subf, name)] + cat_mjcf_paths = [] + for folder in model_folders: + cat_path = os.path.join(BASE_ASSET_ZOO_PATH, folder) + for root, _, files in os.walk(cat_path): + if "model.xml" in files: + model_name = os.path.basename(root) + if model_name in self.exclude: + continue + cat_mjcf_paths.append(os.path.join(root, "model.xml")) + self.mjcf_paths = sorted(cat_mjcf_paths) + + def get_mjcf_kwargs(self): + """ + returns relevant data to apply to the MJCF model for the object category + """ + return deepcopy( + dict( + scale=self.scale, + solimp=self.solimp, + solref=self.solref, + density=self.density, + friction=self.friction, + priority=self.priority, + ) + ) + + +# update OBJ_CATEGORIES with ObjCat instances. Maps name to the different registries it can belong to +# and then maps the registry to the ObjCat instance +for (name, kwargs) in OBJ_CATEGORIES.items(): + + # get the properties that are common to both registries + common_properties = deepcopy(kwargs) + for k in common_properties.keys(): + assert k in [ + "graspable", + "washable", + "microwavable", + "cookable", + "freezable", + "types", + "aigen", + "objaverse", + ] + objaverse_kwargs = common_properties.pop("objaverse", None) + aigen_kwargs = common_properties.pop("aigen", None) + assert "scale" not in kwargs + OBJ_CATEGORIES[name] = {} + + # create instances + if objaverse_kwargs is not None: + objaverse_kwargs.update(common_properties) + OBJ_CATEGORIES[name]["objaverse"] = ObjCat(name=name, **objaverse_kwargs) + if aigen_kwargs is not None: + aigen_kwargs.update(common_properties) + OBJ_CATEGORIES[name]["aigen"] = ObjCat( + name=name, aigen_cat=True, **aigen_kwargs + ) + + +def sample_kitchen_object( + groups, + exclude_groups=None, + graspable=None, + washable=None, + microwavable=None, + cookable=None, + freezable=None, + rng=None, + obj_registries=("objaverse",), + split=None, + max_size=(None, None, None), + object_scale=None, +): + """ + Sample a kitchen object from the specified groups and within max_size bounds. + + Args: + groups (list or str): groups to sample from or the exact xml path of the object to spawn + + exclude_groups (str or list): groups to exclude + + graspable (bool): whether the sampled object must be graspable + + washable (bool): whether the sampled object must be washable + + microwavable (bool): whether the sampled object must be microwavable + + cookable (bool): whether whether the sampled object must be cookable + + freezable (bool): whether whether the sampled object must be freezable + + rng (np.random.Generator): random number object + + obj_registries (tuple): registries to sample from + + split (str): split to sample from. Split "A" specifies all but the last 3 object instances + (or the first half - whichever is larger), "B" specifies the rest, and None specifies all. + + max_size (tuple): max size of the object. If the sampled object is not within bounds of max size, function will resample + + object_scale (float): scale of the object. If set will multiply the scale of the sampled object by this value + + + Returns: + dict: kwargs to apply to the MJCF model for the sampled object + + dict: info about the sampled object - the path of the mjcf, groups which the object's category belongs to, the category of the object + the sampling split the object came from, and the groups the object was sampled from + """ + valid_object_sampled = False + while valid_object_sampled is False: + mjcf_kwargs, info = sample_kitchen_object_helper( + groups=groups, + exclude_groups=exclude_groups, + graspable=graspable, + washable=washable, + microwavable=microwavable, + cookable=cookable, + freezable=freezable, + rng=rng, + obj_registries=obj_registries, + split=split, + object_scale=object_scale, + ) + + # check if object size is within bounds + mjcf_path = info["mjcf_path"] + tree = ET.parse(mjcf_path) + root = tree.getroot() + bottom = string_to_array( + find_elements(root=root, tags="site", attribs={"name": "bottom_site"}).get( + "pos" + ) + ) + top = string_to_array( + find_elements(root=root, tags="site", attribs={"name": "top_site"}).get( + "pos" + ) + ) + horizontal_radius = string_to_array( + find_elements( + root=root, tags="site", attribs={"name": "horizontal_radius_site"} + ).get("pos") + ) + scale = mjcf_kwargs["scale"] + obj_size = ( + np.array( + [horizontal_radius[0] * 2, horizontal_radius[1] * 2, top[2] - bottom[2]] + ) + * scale + ) + valid_object_sampled = True + for i in range(3): + if max_size[i] is not None and obj_size[i] > max_size[i]: + valid_object_sampled = False + + return mjcf_kwargs, info + + +def sample_kitchen_object_helper( + groups, + exclude_groups=None, + graspable=None, + washable=None, + microwavable=None, + cookable=None, + freezable=None, + rng=None, + obj_registries=("objaverse",), + split=None, + object_scale=None, +): + """ + Helper function to sample a kitchen object. + + Args: + groups (list or str): groups to sample from or the exact xml path of the object to spawn + + exclude_groups (str or list): groups to exclude + + graspable (bool): whether the sampled object must be graspable + + washable (bool): whether the sampled object must be washable + + microwavable (bool): whether the sampled object must be microwavable + + cookable (bool): whether whether the sampled object must be cookable + + freezable (bool): whether whether the sampled object must be freezable + + rng (np.random.Generator): random number object + + obj_registries (tuple): registries to sample from + + split (str): split to sample from. Split "A" specifies all but the last 3 object instances + (or the first half - whichever is larger), "B" specifies the rest, and None specifies all. + + object_scale (float): scale of the object. If set will multiply the scale of the sampled object by this value + + + Returns: + dict: kwargs to apply to the MJCF model for the sampled object + + dict: info about the sampled object - the path of the mjcf, groups which the object's category belongs to, the category of the object + the sampling split the object came from, and the groups the object was sampled from + """ + if rng is None: + rng = np.random.default_rng() + + # option to spawn specific object instead of sampling from a group + if isinstance(groups, str) and groups.endswith(".xml"): + mjcf_path = groups + # reverse look up mjcf_path to category + mjcf_kwargs = dict() + cat = None + obj_found = False + for cand_cat in OBJ_CATEGORIES: + for reg in obj_registries: + if ( + reg in OBJ_CATEGORIES[cand_cat] + and mjcf_path in OBJ_CATEGORIES[cand_cat][reg].mjcf_paths + ): + mjcf_kwargs = OBJ_CATEGORIES[cand_cat][reg].get_mjcf_kwargs() + cat = cand_cat + obj_found = True + break + if obj_found: + break + if obj_found is False: + raise ValueError + mjcf_kwargs["mjcf_path"] = mjcf_path + else: + if not isinstance(groups, tuple) and not isinstance(groups, list): + groups = [groups] + + if exclude_groups is None: + exclude_groups = [] + if not isinstance(exclude_groups, tuple) and not isinstance( + exclude_groups, list + ): + exclude_groups = [exclude_groups] + + invalid_categories = [] + for g in exclude_groups: + for cat in OBJ_GROUPS[g]: + invalid_categories.append(cat) + + valid_categories = [] + for g in groups: + for cat in OBJ_GROUPS[g]: + # don't repeat if already added + if cat in valid_categories: + continue + if cat in invalid_categories: + continue + + # don't include if category not represented in any registry + cat_in_any_reg = np.any( + [reg in OBJ_CATEGORIES[cat] for reg in obj_registries] + ) + if not cat_in_any_reg: + continue + + invalid = False + for reg in obj_registries: + if reg not in OBJ_CATEGORIES[cat]: + continue + cat_meta = OBJ_CATEGORIES[cat][reg] + if graspable is True and cat_meta.graspable is not True: + invalid = True + if washable is True and cat_meta.washable is not True: + invalid = True + if microwavable is True and cat_meta.microwavable is not True: + invalid = True + if cookable is True and cat_meta.cookable is not True: + invalid = True + if freezable is True and cat_meta.freezable is not True: + invalid = True + + if invalid: + continue + + valid_categories.append(cat) + + cat = rng.choice(valid_categories) + + choices = {reg: [] for reg in obj_registries} + + for reg in obj_registries: + if reg not in OBJ_CATEGORIES[cat]: + choices[reg] = [] + continue + reg_choices = deepcopy(OBJ_CATEGORIES[cat][reg].mjcf_paths) + + # exclude out objects based on split + if split is not None: + split_th = max(len(choices) - 3, int(math.ceil(len(reg_choices) / 2))) + if split == "A": + reg_choices = reg_choices[:split_th] + elif split == "B": + reg_choices = reg_choices[split_th:] + else: + raise ValueError + choices[reg] = reg_choices + + chosen_reg = rng.choice( + obj_registries, + p=np.array([len(choices[reg]) for reg in obj_registries]) + / sum(len(choices[reg]) for reg in obj_registries), + ) + + mjcf_path = rng.choice(choices[chosen_reg]) + mjcf_kwargs = OBJ_CATEGORIES[cat][chosen_reg].get_mjcf_kwargs() + mjcf_kwargs["mjcf_path"] = mjcf_path + + if object_scale is not None: + mjcf_kwargs["scale"] *= object_scale + + groups_containing_sampled_obj = [] + for group, group_cats in OBJ_GROUPS.items(): + if cat in group_cats: + groups_containing_sampled_obj.append(group) + + info = { + "groups_containing_sampled_obj": groups_containing_sampled_obj, + "groups": groups, + "cat": cat, + "split": split, + "mjcf_path": mjcf_path, + } + + return mjcf_kwargs, info diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/kitchen_objects.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/kitchen_objects.py new file mode 100644 index 0000000000000000000000000000000000000000..b5689d340dad1ccfcf5822e43b3f9ec198a6e22b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/kitchen_objects.py @@ -0,0 +1,2114 @@ +import os +import robocasa + +BASE_ASSET_ZOO_PATH = os.path.join(robocasa.models.assets_root, "objects") + + +# Constant that contains information about each object category. These will be used to generate the ObjCat classes for each category +OBJ_CATEGORIES = dict( + liquor=dict( + types=("drink", "alcohol"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + model_folders=["aigen_objs/alcohol"], + scale=1.50, + ), + objaverse=dict( + model_folders=["objaverse/alcohol"], + scale=1.35, + ), + ), + apple=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=False, + aigen=dict( + scale=1.0, + ), + objaverse=dict( + scale=0.90, + ), + ), + avocado=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=0.90, + ), + objaverse=dict( + scale=0.90, + ), + ), + bagel=dict( + types=("bread_food"), + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.2, + ), + objaverse=dict( + exclude=[ + "bagel_8", + ], + ), + ), + bagged_food=dict( + types=("packaged_food"), + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.1, + ), + objaverse=dict( + exclude=[ + "bagged_food_12", + ], + ), + ), + baguette=dict( + types=("bread_food"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + exclude=[ + "baguette_3", # small holes on ends + ], + ), + ), + banana=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.10, + ), + objaverse=dict( + scale=0.95, + ), + ), + bar=dict( + types=("packaged_food"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=[1.25, 1.25, 1.75], + ), + objaverse=dict( + scale=[0.75, 0.75, 1.2], + exclude=[ + "bar_1", # small holes scattered + ], + ), + ), + bar_soap=dict( + types=("cleaner"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=[1.25, 1.25, 1.40], + ), + objaverse=dict( + scale=[0.95, 0.95, 1.05], + exclude=["bar_soap_2"], + ), + ), + beer=dict( + types=("drink", "alcohol"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.30, + ), + objaverse=dict(scale=1.15), + ), + bell_pepper=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.0, + ), + objaverse=dict( + scale=0.75, + ), + ), + bottled_drink=dict( + types=("drink"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.25, + ), + objaverse=dict(), + ), + bottled_water=dict( + types=("drink"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.30, + ), + objaverse=dict( + scale=1.10, + exclude=[ + "bottled_water_0", # minor hole at top + "bottled_water_5", # causing error. eigenvalues of mesh inertia violate A + B >= C + ], + ), + ), + bowl=dict( + types=("receptacle", "stackable"), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=False, + aigen=dict( + scale=1.75, + ), + objaverse=dict( + scale=2.0, + exclude=[ + "bowl_21", # can see through from bottom of bowl + ], + ), + ), + boxed_drink=dict( + types=("drink"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.1, + ), + objaverse=dict( + scale=0.80, + exclude=[ + "boxed_drink_9", # hole on bottom + "boxed_drink_6", # hole on bottom + "boxed_drink_8", # hole on bottom + ], + ), + ), + boxed_food=dict( + types=("packaged_food"), + graspable=True, + washable=False, + microwavable=True, + cookable=False, + freezable=True, + aigen=dict( + scale=1.25, + ), + objaverse=dict( + scale=1.1, + exclude=[ + "boxed_food_5", # causing error. eigenvalues of mesh inertia violate A + B >= C + ], + # exclude=[ + # "boxed_food_5", + # "boxed_food_3", "boxed_food_1", "boxed_food_6", "boxed_food_11", "boxed_food_10", "boxed_food_8", "boxed_food_9", "boxed_food_7", "boxed_food_2", # self turning due to single collision geom + # ], + ), + ), + bread=dict( + types=("bread_food"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=[0.80, 0.80, 1.0], + ), + objaverse=dict(scale=[0.70, 0.70, 1.0], exclude=["bread_22"]), # hole on bottom + ), + broccoli=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + scale=1.25, + exclude=[ + "broccoli_2", # holes on one part + ], + ), + ), + cake=dict( + types=("sweets"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=0.8, + ), + objaverse=dict( + scale=0.8, + ), + ), + can=dict( + types=("drink"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict(), + objaverse=dict( + exclude=[ + "can_10", # hole on bottom + "can_5", # causing error: faces of mesh have inconsistent orientation. + ], + ), + ), + candle=dict( + types=("decoration"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.5, + ), + objaverse=dict( + exclude=[ + "candle_11", # hole at bottom + # "candle_2", # can't see from bottom view angle + # "candle_15", # can't see from bottom view angle + ], + ), + ), + canned_food=dict( + types=("packaged_food"), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=True, + aigen=dict( + scale=1.15, + ), + objaverse=dict( + scale=0.90, + exclude=[ + "canned_food_7", # holes at top and bottom + ], + ), + ), + carrot=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.25, + ), + objaverse=dict(), + ), + cereal=dict( + types=("packaged_food"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.15, + ), + objaverse=dict( + # exclude=[ + # "cereal_2", "cereal_5", "cereal_13", "cereal_3", "cereal_9", "cereal_0", "cereal_7", "cereal_4", "cereal_8", "cereal_12", "cereal_11", "cereal_1", "cereal_6", "cereal_10", # self turning due to single collision geom + # ] + ), + ), + cheese=dict( + types=("dairy"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.0, + ), + objaverse=dict( + scale=0.85, + ), + ), + chips=dict( + types=("packaged_food"), + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.5, + ), + objaverse=dict( + exclude=[ + "chips_12", # minor hole at bottom of bag + # "chips_2", # a weird texture at top/bottom but keeping this + ] + ), + ), + chocolate=dict( + types=("sweets"), + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=[1.0, 1.0, 1.35], + ), + objaverse=dict( + scale=[0.80, 0.80, 1.20], + exclude=[ + # "chocolate_2", # self turning due to single collision geom + ], + ), + ), + coffee_cup=dict( + types=("drink"), + graspable=True, + washable=False, + microwavable=True, + cookable=False, + freezable=False, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + exclude=[ + "coffee_cup_18", # can see thru top + "coffee_cup_5", # can see thru from bottom side + "coffee_cup_19", # can see thru from bottom side + ], + ), + ), + condiment_bottle=dict( + types=("condiment"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.35, + model_folders=["aigen_objs/condiment"], + ), + objaverse=dict( + scale=1.05, + model_folders=["objaverse/condiment"], + ), + ), + corn=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.5, + ), + objaverse=dict(scale=1.05), + ), + croissant=dict( + types=("pastry"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=0.90, + ), + objaverse=dict( + scale=0.90, + ), + ), + cucumber=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.1, + ), + objaverse=dict(), + ), + cup=dict( + types=("receptacle", "stackable"), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=False, + aigen=dict( + scale=1.35, + ), + objaverse=dict(), + ), + cupcake=dict( + types=("sweets"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=0.90, + ), + objaverse=dict( + exclude=[ + "cupcake_0", # can see thru bottom + "cupcake_10", # can see thru bottom, + "cupcake_1", # very small hole at bottom + ] + ), + ), + cutting_board=dict( + types=("receptacle"), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=2.0, + ), + objaverse=dict( + scale=1.35, + exclude=[ + "cutting_board_14", + "cutting_board_3", + "cutting_board_10", + "cutting_board_6", # these models still modeled with meshes which should work most of the time, but excluding them for safety + ], + ), + ), + donut=dict( + types=("sweets", "pastry"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.5, + ), + objaverse=dict( + scale=1.15, + ), + ), + egg=dict( + types=("dairy"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.15, + ), + objaverse=dict( + scale=0.85, + ), + ), + eggplant=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.30, + ), + objaverse=dict(scale=0.95), + ), + fish=dict( + types=("meat"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=[1.35, 1.35, 2.0], + ), + objaverse=dict( + scale=[1.0, 1.0, 1.5], + ), + ), + fork=dict( + types=("utensil"), + graspable=False, + washable=True, + microwavable=True, + cookable=True, + freezable=False, + aigen=dict( + scale=1.75, + ), + objaverse=dict(), + ), + garlic=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.3, + ), + objaverse=dict(scale=1.10, exclude=["garlic_3"]), # has hole on side + ), + hot_dog=dict( + types=("cooked_food"), + graspable=True, + washable=False, + microwavable=True, + cookable=False, + freezable=True, + aigen=dict( + scale=1.4, + ), + objaverse=dict(), + ), + jam=dict( + types=("packaged_food"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.05, + ), + objaverse=dict( + scale=0.90, + ), + ), + jug=dict( + types=("receptacle"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.5, + ), + objaverse=dict( + scale=1.5, + ), + ), + ketchup=dict( + types=("condiment"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + exclude=[ + "ketchup_5" # causing error: faces of mesh have inconsistent orientation. + ] + ), + ), + kettle_electric=dict( + types=("receptacle"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + objaverse=dict( + scale=1.35, + model_folders=["objaverse/kettle"], + exclude=[ + f"kettle_{i}" + for i in range(29) + if i not in [0, 7, 9, 12, 13, 17, 24, 25, 26, 27] + ], + ), + aigen=dict( + scale=1.5, + model_folders=["aigen_objs/kettle"], + exclude=[f"kettle_{i}" for i in range(11) if i not in [0, 2, 6, 9, 10, 11]], + ), + ), + kettle_non_electric=dict( + types=("receptacle"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + objaverse=dict( + scale=1.35, + model_folders=["objaverse/kettle"], + exclude=[ + f"kettle_{i}" + for i in range(29) + if i in [0, 7, 9, 12, 13, 17, 24, 25, 26, 27] + ], + ), + aigen=dict( + scale=1.5, + model_folders=["aigen_objs/kettle"], + exclude=[f"kettle_{i}" for i in range(11) if i in [0, 2, 6, 9, 10, 11]], + ), + ), + kiwi=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=0.90, + ), + objaverse=dict( + scale=0.90, + ), + ), + knife=dict( + types=("utensil"), + graspable=False, + washable=True, + microwavable=True, + cookable=True, + freezable=False, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + scale=1.20, + ), + ), + ladle=dict( + types=("utensil"), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=False, + aigen=dict( + scale=1.5, + ), + objaverse=dict( + scale=1.10, + ), + ), + lemon=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=True, + aigen=dict( + scale=1.1, + ), + objaverse=dict(), + ), + lime=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=True, + objaverse=dict( + scale=1.0, + ), + aigen=dict( + scale=0.90, + ), + ), + mango=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=True, + aigen=dict( + scale=1.0, + ), + objaverse=dict( + scale=0.85, + exclude=[ + "mango_3", # one half is pitch dark + ], + ), + ), + milk=dict( + types=("dairy", "drink"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + exclude=[ + "milk_6" # causing error: eigenvalues of mesh inertia violate A + B >= C + ] + ), + ), + mug=dict( + types=("receptacle", "stackable"), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=False, + aigen=dict( + scale=1.3, + ), + objaverse=dict(), + ), + mushroom=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + scale=1.20, + exclude=[ + # "mushroom_16", # very very small holes. keeping anyway + ], + ), + ), + onion=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=False, + aigen=dict( + scale=1.1, + ), + objaverse=dict(), + ), + orange=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.05, + ), + objaverse=dict( + exclude=[ + # "orange_11", # bottom half is dark. keeping anyway + ] + ), + ), + pan=dict( + types=("receptacle"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=2.25, + ), + objaverse=dict( + scale=1.70, + exclude=[ + "pan_16", # causing error. faces of mesh have inconsistent orientation, + "pan_0", + "pan_12", + "pan_17", + "pan_22", # these are technically what we consider "pots" + ], + ), + ), + pot=dict( + types=("receptacle"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=2.25, + ), + objaverse=dict( + model_folders=["objaverse/pan"], + scale=1.70, + exclude=list( + set([f"pan_{i}" for i in range(25)]) + - set(["pan_0", "pan_12", "pan_17", "pan_22"]) + ), + ), + ), + peach=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.05, + ), + objaverse=dict(), + ), + pear=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict(), + objaverse=dict( + exclude=[ + "pear_4", # has big hole. excluding + ] + ), + ), + plate=dict( + types=("receptacle"), + graspable=False, + washable=True, + microwavable=True, + cookable=False, + freezable=False, + aigen=dict( + scale=1.65, + ), + objaverse=dict( + scale=1.35, + exclude=[ + "plate_6", # causing error: faces of mesh have inconsistent orientation. + ], + ), + ), + potato=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.10, + ), + objaverse=dict(), + ), + rolling_pin=dict( + types=("tool"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.6, + ), + objaverse=dict( + scale=1.25, + exclude=[ + # "rolling_pin_5", # can see thru side handle edges, keeping anyway + # "rolling_pin_1", # can see thru side handle edges, keeping anyway + ], + ), + ), + scissors=dict( + types=("tool"), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.35, + ), + objaverse=dict( + scale=1.15, + ), + ), + shaker=dict( + types=("condiment"), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.25, + ), + objaverse=dict(), + ), + soap_dispenser=dict( + types=("cleaner"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.7, + ), + objaverse=dict( + exclude=[ + # "soap_dispenser_4", # can see thru body but that's fine if this is glass + ] + ), + ), + spatula=dict( + types=("utensil"), + graspable=False, + washable=True, + microwavable=False, + cookable=True, + freezable=False, + aigen=dict( + scale=1.30, + ), + objaverse=dict( + scale=1.10, + ), + ), + sponge=dict( + types=("cleaner"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.20, + ), + objaverse=dict( + scale=0.90, + # exclude=[ + # "sponge_7", "sponge_1", # self turning due to single collision geom + # ] + ), + ), + spoon=dict( + types=("utensil"), + graspable=False, + washable=True, + microwavable=True, + cookable=True, + freezable=False, + aigen=dict( + scale=1.5, + ), + objaverse=dict(), + ), + spray=dict( + types=("cleaner"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.75, + ), + objaverse=dict( + scale=1.75, + ), + ), + squash=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=1.15, + ), + objaverse=dict( + exclude=[ + "squash_10", # hole at bottom + ], + ), + ), + steak=dict( + types=("meat"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict( + scale=[1.0, 1.0, 2.0], + ), + objaverse=dict( + scale=[1.0, 1.0, 2.0], + exclude=[ + "steak_13", # bottom texture completely messed up + "steak_1", # bottom texture completely messed up + # "steak_9", # bottom with some minor issues, keeping anyway + ], + ), + ), + sweet_potato=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + aigen=dict(), + objaverse=dict(), + ), + tangerine=dict( + types=("fruit"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict(), + objaverse=dict(), + ), + teapot=dict( + types=("receptacle"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.25, + ), + objaverse=dict( + scale=1.25, + exclude=[ + "teapot_9", # hole on bottom + ], + ), + ), + tomato=dict( + types=("vegetable"), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=False, + aigen=dict( + scale=1.25, + ), + objaverse=dict(), + ), + tray=dict( + types=("receptacle"), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict(scale=2.0), + objaverse=dict( + scale=1.80, + ), + ), + waffle=dict( + types=("sweets"), + graspable=False, + washable=False, + microwavable=True, + cookable=False, + freezable=True, + aigen=dict( + scale=1.75, + ), + objaverse=dict( + exclude=[ + "waffle_2", # bottom completely messed up + ] + ), + ), + water_bottle=dict( + types=("drink"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.6, + ), + objaverse=dict( + scale=1.5, + exclude=[ + "water_bottle_11", # sides and bottom see thru, but ok if glass. keeping anyway + ], + ), + ), + wine=dict( + types=("drink", "alcohol"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + aigen=dict( + scale=1.9, + ), + objaverse=dict( + scale=1.6, + exclude=[ + "wine_7", # causing error. faces of mesh have inconsistent orientation + ], + ), + ), + yogurt=dict( + types=("dairy", "packaged_food"), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + aigen=dict( + scale=1.0, + ), + objaverse=dict( + scale=0.95, + ), + ), + dates=dict( + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + aigen=dict(), + ), + lemonade=dict( + aigen=dict( + scale=1.5, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("drink"), + ), + walnut=dict( + aigen=dict( + scale=1.15, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=(), + ), + cheese_grater=dict( + aigen=dict( + scale=2.15, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("tool"), + ), + syrup_bottle=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("condiment"), + ), + scallops=dict( + aigen=dict( + scale=1.25, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + candy=dict( + aigen=dict(), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("sweets"), + ), + whisk=dict( + aigen=dict( + scale=1.8, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("utensil"), + ), + pitcher=dict( + aigen=dict( + scale=1.75, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=False, + types=("receptacle"), + ), + ice_cream=dict( + aigen=dict( + scale=1.25, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + types=("sweets"), + ), + cherry=dict( + aigen=dict(), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + ), + peanut_butter=dict( + aigen=dict( + scale=1.25, + model_folders=["aigen_objs/peanut_butter_jar"], + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + types=("packaged_food"), + ), + thermos=dict( + aigen=dict( + scale=1.75, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=True, + types=("drink"), + ), + ham=dict( + aigen=dict( + scale=1.5, + ), + graspable=False, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + dumpling=dict( + aigen=dict( + scale=1.15, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat", "cooked_food"), + ), + cabbage=dict( + aigen=dict( + scale=2.0, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=True, + freezable=True, + types=("vegetable"), + ), + lettuce=dict( + aigen=dict( + scale=2.0, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("vegetable"), + ), + tongs=dict( + aigen=dict( + scale=1.5, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("tool"), + ), + ginger=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=True, + types=("vegetable"), + ), + ice_cube_tray=dict( + aigen=dict( + scale=2.0, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("receptacle"), + ), + shrimp=dict( + aigen=dict( + scale=1.15, + ), + graspable=False, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + cantaloupe=dict( + aigen=dict( + scale=1.5, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + ), + honey_bottle=dict( + aigen=dict( + scale=1.10, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + types=("packaged_food"), + ), + grapes=dict( + aigen=dict( + scale=1.5, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + ), + spaghetti_box=dict( + aigen=dict( + scale=1.25, + ), + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("packaged_food"), + ), + chili_pepper=dict( + aigen=dict( + scale=1.10, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("vegetable"), + ), + celery=dict( + aigen=dict( + scale=2.0, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("vegetable"), + ), + burrito=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=False, + microwavable=True, + cookable=False, + freezable=True, + types=("cooked_food"), + ), + olive_oil_bottle=dict( + aigen=dict( + scale=1.5, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + types=("packaged_food"), + ), + kebabs=dict( + aigen=dict( + scale=1.65, + ), + graspable=True, + washable=False, + microwavable=True, + cookable=True, + freezable=True, + types=("cooked_food"), + ), + bottle_opener=dict( + aigen=dict(), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("tool"), + ), + chicken_breast=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + jello_cup=dict( + aigen=dict( + scale=1.15, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + types=("packaged_food"), + ), + lobster=dict( + aigen=dict( + scale=1.15, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + brussel_sprout=dict( + aigen=dict(), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("vegetable"), + ), + sushi=dict( + aigen=dict( + scale=0.90, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=True, + types=("meat"), + ), + baking_sheet=dict( + aigen=dict( + scale=1.75, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("receptacle"), + ), + wine_glass=dict( + aigen=dict( + scale=1.5, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=False, + freezable=True, + types=("receptacle"), + ), + asparagus=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("vegetable"), + ), + lamb_chop=dict( + aigen=dict( + scale=1.15, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + pickle=dict( + aigen=dict( + scale=1.0, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("vegetable"), + ), + bacon=dict( + aigen=dict( + scale=1.35, + ), + graspable=False, + washable=False, + microwavable=True, + cookable=True, + freezable=False, + types=("meat"), + ), + canola_oil=dict( + aigen=dict( + scale=1.75, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("packaged_food"), + ), + strawberry=dict( + aigen=dict( + scale=0.9, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + ), + watermelon=dict( + aigen=dict( + scale=2.5, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("fruit"), + ), + pizza_cutter=dict( + aigen=dict( + scale=1.4, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("tool"), + ), + pomegranate=dict( + aigen=dict( + scale=1.25, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("fruit"), + ), + apricot=dict( + aigen=dict( + scale=0.7, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("fruit"), + ), + beet=dict( + aigen=dict(), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=False, + types=("vegetable"), + ), + radish=dict( + aigen=dict( + scale=1.0, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("vegetable"), + ), + salsa=dict( + aigen=dict( + scale=1.15, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("packaged_food"), + ), + artichoke=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=False, + types=("vegetable"), + ), + scone=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("pastry", "bread_food"), + ), + hamburger=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=False, + microwavable=True, + cookable=False, + freezable=False, + types=("cooked_food"), + ), + raspberry=dict( + aigen=dict( + scale=0.85, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + ), + tacos=dict( + aigen=dict( + scale=1.0, + ), + graspable=True, + washable=False, + microwavable=True, + cookable=False, + freezable=False, + types=("cooked_food"), + ), + vinegar=dict( + aigen=dict( + scale=1.4, + ), + graspable=True, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("packaged_food", "condiment"), + ), + zucchini=dict( + aigen=dict( + scale=1.35, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("vegetable"), + ), + pork_loin=dict( + aigen=dict(), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + pork_chop=dict( + aigen=dict( + scale=1.25, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + sausage=dict( + aigen=dict( + scale=1.45, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + coconut=dict( + aigen=dict( + scale=2.0, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("fruit"), + ), + cauliflower=dict( + aigen=dict( + scale=1.5, + ), + graspable=False, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("vegetable"), + ), + lollipop=dict( + aigen=dict(), + graspable=False, + washable=False, + microwavable=False, + cookable=False, + freezable=False, + types=("sweets"), + ), + salami=dict( + aigen=dict( + scale=1.5, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=True, + types=("meat"), + ), + butter_stick=dict( + aigen=dict( + scale=1.3, + ), + graspable=True, + washable=False, + microwavable=True, + cookable=True, + freezable=True, + types=("dairy"), + ), + can_opener=dict( + aigen=dict( + scale=1.5, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=False, + types=("tool"), + ), + tofu=dict( + aigen=dict(), + graspable=True, + washable=True, + microwavable=False, + cookable=True, + freezable=True, + types=(), + ), + pineapple=dict( + aigen=dict( + scale=2.0, + ), + graspable=False, + washable=True, + microwavable=False, + cookable=False, + freezable=True, + types=("fruit"), + ), + skewers=dict( + aigen=dict( + scale=1.75, + ), + graspable=True, + washable=True, + microwavable=True, + cookable=True, + freezable=False, + types=("meat", "cooked_food"), + ), +) + + +def get_cats_by_type(types, obj_registries=None): + """ + Retrieves a list of item keys from the global `OBJ_CATEGORIES` dictionary based on the specified types. + + Args: + types (list): A list of valid types to filter items by. Only items with a matching type will be included. + obj_registries (list): only consider categories belonging to these object registries + + Returns: + list: A list of keys from `OBJ_CATEGORIES` where the item's types intersect with the provided `types`. + """ + types = set(types) + + res = [] + for key, val in OBJ_CATEGORIES.items(): + # check if category is in one of valid object registries + if obj_registries is not None: + if isinstance(obj_registries, str): + obj_registries = [obj_registries] + if any([reg in val for reg in obj_registries]) is False: + continue + + if "types" in val: + cat_types = val["types"] + else: + cat_types = list(val.values())[0].types + if isinstance(cat_types, str): + cat_types = [cat_types] + cat_types = set(cat_types) + # Access the "types" key in the dictionary using the correct syntax + if len(cat_types.intersection(types)) > 0: + res.append(key) + + return res + + +### define all object categories ### +OBJ_GROUPS = dict( + all=list(OBJ_CATEGORIES.keys()), +) + +for k in OBJ_CATEGORIES: + OBJ_GROUPS[k] = [k] + +all_types = set() +# populate all_types +for (cat, cat_meta_dict) in OBJ_CATEGORIES.items(): + # types are common to both so we only need to examine one + cat_types = cat_meta_dict["types"] + if isinstance(cat_types, str): + cat_types = [cat_types] + all_types = all_types.union(cat_types) + +for t in all_types: + OBJ_GROUPS[t] = get_cats_by_type(types=[t]) + +OBJ_GROUPS["food"] = get_cats_by_type( + [ + "vegetable", + "fruit", + "sweets", + "dairy", + "meat", + "bread_food", + "pastry", + "cooked_food", + ] +) +OBJ_GROUPS["in_container"] = get_cats_by_type( + [ + "vegetable", + "fruit", + "sweets", + "dairy", + "meat", + "bread_food", + "pastry", + "cooked_food", + ] +) + +# custom groups +OBJ_GROUPS["container"] = ["plate"] # , "bowl"] +OBJ_GROUPS["kettle"] = ["kettle_electric", "kettle_non_electric"] +OBJ_GROUPS["cookware"] = ["pan", "pot", "kettle_non_electric"] +OBJ_GROUPS["pots_and_pans"] = ["pan", "pot"] +OBJ_GROUPS["food_set1"] = [ + "apple", + "baguette", + "banana", + "carrot", + "cheese", + "cucumber", + "egg", + "lemon", + "orange", + "potato", +] +OBJ_GROUPS["group1"] = ["apple", "carrot", "banana", "bowl", "can"] +OBJ_GROUPS["container_set2"] = ["plate", "bowl"] diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/objects.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/objects.py new file mode 100644 index 0000000000000000000000000000000000000000..396a53c0315c20f6bae1dd615c6565e922fedc7c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/objects/objects.py @@ -0,0 +1,192 @@ +import os +import time +import xml.etree.ElementTree as ET + +import numpy as np +import robosuite +import robosuite.utils.transform_utils as T +from robosuite.models.objects import MujocoXMLObject +from robosuite.utils.mjcf_utils import array_to_string, string_to_array + + +class MJCFObject(MujocoXMLObject): + """ + Blender object with support for changing the scaling + """ + + def __init__( + self, + name, + mjcf_path, + scale=1.0, + solimp=(0.998, 0.998, 0.001), + solref=(0.001, 1), + density=100, + friction=(0.95, 0.3, 0.1), + margin=None, + rgba=None, + priority=None, + ): + # get scale in x, y, z + if isinstance(scale, float): + scale = [scale, scale, scale] + elif isinstance(scale, tuple) or isinstance(scale, list): + assert len(scale) == 3 + scale = tuple(scale) + else: + raise Exception("got invalid scale: {}".format(scale)) + scale = np.array(scale) + + self.solimp = solimp + self.solref = solref + self.density = density + self.friction = friction + self.margin = margin + + self.priority = priority + + self.rgba = rgba + + # read default xml + xml_path = mjcf_path + folder = os.path.dirname(xml_path) + tree = ET.parse(xml_path) + root = tree.getroot() + + # write modified xml (and make sure to postprocess any paths just in case) + xml_str = ET.tostring(root, encoding="utf8").decode("utf8") + xml_str = self.postprocess_model_xml(xml_str) + time_str = str(time.time()).replace(".", "_") + new_xml_path = os.path.join(folder, "{}_{}.xml".format(time_str, os.getpid())) + f = open(new_xml_path, "w") + f.write(xml_str) + f.close() + + # initialize object with new xml we wrote + super().__init__( + fname=new_xml_path, + name=name, + joints=[dict(type="free", damping="0.0005")], + obj_type="all", + duplicate_collision_geoms=False, + scale=scale, + ) + + # clean up xml - we don't need it anymore + if os.path.exists(new_xml_path): + os.remove(new_xml_path) + + def postprocess_model_xml(self, xml_str): + """ + New version of postprocess model xml that only replaces robosuite file paths if necessary (otherwise + there is an error with the "max" operation) + """ + + path = os.path.split(robosuite.__file__)[0] + path_split = path.split("/") + + # replace mesh and texture file paths + tree = ET.fromstring(xml_str) + root = tree + asset = root.find("asset") + meshes = asset.findall("mesh") + textures = asset.findall("texture") + all_elements = meshes + textures + + for elem in all_elements: + old_path = elem.get("file") + if old_path is None: + continue + + old_path_split = old_path.split("/") + # maybe replace all paths to robosuite assets + check_lst = [ + loc for loc, val in enumerate(old_path_split) if val == "robosuite" + ] + if len(check_lst) > 0: + ind = max(check_lst) # last occurrence index + new_path_split = path_split + old_path_split[ind + 1 :] + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + return ET.tostring(root, encoding="utf8").decode("utf8") + + def _get_geoms(self, root, _parent=None): + """ + Helper function to recursively search through element tree starting at @root and returns + a list of (parent, child) tuples where the child is a geom element + + Args: + root (ET.Element): Root of xml element tree to start recursively searching through + + _parent (ET.Element): Parent of the root element tree. Should not be used externally; only set + during the recursive call + + Returns: + list: array of (parent, child) tuples where the child element is a geom type + """ + geom_pairs = super(MJCFObject, self)._get_geoms(root=root, _parent=_parent) + + # modify geoms according to the attributes + for i, (parent, element) in enumerate(geom_pairs): + element.set("solref", array_to_string(self.solref)) + element.set("solimp", array_to_string(self.solimp)) + element.set("density", str(self.density)) + element.set("friction", array_to_string(self.friction)) + if self.margin is not None: + element.set("margin", str(self.margin)) + + if (self.rgba is not None) and (element.get("group") == "1"): + element.set("rgba", array_to_string(self.rgba)) + + if self.priority is not None: + # set high priorit + element.set("priority", str(self.priority)) + + return geom_pairs + + @property + def horizontal_radius(self): + horizontal_radius_site = self.worldbody.find( + "./body/site[@name='{}horizontal_radius_site']".format(self.naming_prefix) + ) + site_values = string_to_array(horizontal_radius_site.get("pos")) + return np.linalg.norm(site_values[0:2]) + + def get_bbox_points(self, trans=None, rot=None): + """ + Get the full 8 bounding box points of the object + rot: a rotation matrix + """ + bbox_offsets = [] + + bottom_offset = self.bottom_offset + top_offset = self.top_offset + horizontal_radius_site = self.worldbody.find( + "./body/site[@name='{}horizontal_radius_site']".format(self.naming_prefix) + ) + horiz_radius = string_to_array(horizontal_radius_site.get("pos"))[:2] + + center = np.mean([bottom_offset, top_offset], axis=0) + half_size = [horiz_radius[0], horiz_radius[1], top_offset[2] - center[2]] + + bbox_offsets = [ + center + half_size * np.array([-1, -1, -1]), # p0 + center + half_size * np.array([1, -1, -1]), # px + center + half_size * np.array([-1, 1, -1]), # py + center + half_size * np.array([-1, -1, 1]), # pz + center + half_size * np.array([1, 1, 1]), + center + half_size * np.array([-1, 1, 1]), + center + half_size * np.array([1, -1, 1]), + center + half_size * np.array([1, 1, -1]), + ] + + if trans is None: + trans = np.array([0, 0, 0]) + if rot is not None: + rot = T.quat2mat(rot) + else: + rot = np.eye(3) + + points = [(np.matmul(rot, p) + trans) for p in bbox_offsets] + return points diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/robots/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/robots/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..438ed7ea17342d58a392ccc67126794c824a3cfd --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/robots/__init__.py @@ -0,0 +1,761 @@ +import mujoco +import numpy as np +from enum import Enum + +from robosuite.controllers.parts.generic.joint_pos import JointPositionController +from robosuite.controllers.parts.arm.osc import OperationalSpaceController +from robosuite.controllers.parts.gripper.simple_grip import SimpleGripController +from robosuite.controllers.composite.composite_controller import HybridMobileBase +from robosuite.models.grippers import ( + PandaGripper, + InspireLeftHand, + InspireRightHand, + FourierLeftHand, + FourierRightHand, +) + +class RotationType(Enum): + """Type of rotation representation""" + AXIS_ANGLE = "axis_angle" + QUATERNION = "quaternion" + ROTATION_6D = "rotation_6d" + MATRIX = "matrix" + EULER_ANGLES_RPY = "euler_angles_rpy" + EULER_ANGLES_RYP = "euler_angles_ryp" + EULER_ANGLES_PRY = "euler_angles_pry" + EULER_ANGLES_PYR = "euler_angles_pyr" + EULER_ANGLES_YRP = "euler_angles_yrp" + EULER_ANGLES_YPR = "euler_angles_ypr" + +# This function returns in the order of the gripper XML's joints. +def unformat_gripper_space(gripper, formatted_action): + formatted_action = np.array(formatted_action) + if isinstance(gripper, InspireLeftHand) or isinstance(gripper, InspireRightHand): + action = formatted_action[[0, 2, 4, 6, 8, 11]] + elif isinstance(gripper, FourierLeftHand) or isinstance(gripper, FourierRightHand): + action = formatted_action[[0, 1, 4, 6, 8, 10]] + elif isinstance(gripper, PandaGripper): + action = formatted_action + else: + raise TypeError + return action + + +def _reconstruct_latest_action_gr1_impl(robot, verbose=False): + action_dict = {} + cc = robot.composite_controller + pf = robot.robot_model.naming_prefix + + for part_name, controller in cc.part_controllers.items(): + if isinstance(controller, JointPositionController): + assert controller.input_type == "absolute" + act = controller.goal_qpos + elif isinstance(controller, SimpleGripController): + assert not controller.use_action_scaling + act = unformat_gripper_space(cc.grippers[part_name], controller.goal_qvel) + else: + raise TypeError + action_dict[f"{pf}{part_name}"] = act + + if verbose: + print("Actions:", [(k, len(action_dict[k])) for k in action_dict]) + + return action_dict + + +def _reconstruct_latest_action_panda_impl(robot, action, verbose=False): + action_dict = {} + cc = robot.composite_controller + pf = robot.robot_model.naming_prefix + + for part_name, controller in cc.part_controllers.items(): + start_idx, end_idx = cc._action_split_indexes[part_name] + act = action[start_idx:end_idx] + # split action deeper for OSC + action_dict[f"{pf}{part_name}"] = act + + if verbose: + print("Actions:", [(k, len(action_dict[k])) for k in action_dict]) + + return action_dict + + +# This function tries to get all joints value, but sometimes we want to keep original action +# The function must be called after robot.control() +def reconstruct_latest_actions(env, actions=None, verbose=False): + if actions is None: + actions = np.zeros(env.action_dim) + action_dict = {} + cutoff = 0 + for robot in env.robots: + cc = robot.composite_controller + pf = robot.robot_model.naming_prefix + robot_action = actions[cutoff : cutoff + robot.action_dim] + cutoff += robot.action_dim + if "GR1" in robot.name: + action_dict.update(_reconstruct_latest_action_gr1_impl(robot)) + elif "Panda" in robot.name: + action_dict.update( + _reconstruct_latest_action_panda_impl(robot, robot_action) + ) + else: + raise ValueError(f"Unknown robot name: {robot.name}") + if isinstance(cc, HybridMobileBase): + action_dict[f"{pf}base_mode"] = robot_action[-1] + + if verbose: + print("Actions:", [(k, len(action_dict[k])) for k in action_dict]) + + return action_dict + + +def gather_robot_observations(env, verbose=False): + observations = {} + + for robot_id, robot in enumerate(env.robots): + sim = robot.sim + gripper_names = { + robot.get_gripper_name(arm): robot.gripper[arm] for arm in robot.arms + } + for part_name, indexes in robot._ref_joints_indexes_dict.items(): + qpos_values = [] + for joint_id in indexes: + qpos_addr = sim.model.jnt_qposadr[joint_id] + # https://mujoco.readthedocs.io/en/stable/APIreference/APItypes.html#mjtjoint + joint_type = sim.model.jnt_type[joint_id] + if joint_type == mujoco.mjtJoint.mjJNT_FREE: + qpos_size = 7 # Free joint has 7 DOFs + elif joint_type == mujoco.mjtJoint.mjJNT_BALL: + qpos_size = 4 # Ball joint has 4 DOFs (quaternion) + else: + qpos_size = 1 # Revolute or prismatic joint has 1 DOF + qpos_values = np.append( + qpos_values, sim.data.qpos[qpos_addr : qpos_addr + qpos_size] + ) + if part_name in gripper_names.keys(): + gripper = gripper_names[part_name] + # Reverse the order to match the real robot + qpos_values = unformat_gripper_space(gripper, qpos_values)[::-1] + if len(qpos_values) > 0: + observations[f"robot{robot_id}_{part_name}"] = qpos_values + + if verbose: + print("States:", [(k, len(observations[k])) for k in observations]) + + return observations + + + +from gymnasium import spaces + + +class RobotKeyConverter: + @classmethod + def get_camera_config(cls): + raise NotImplementedError + + @classmethod + def map_obs(cls, input_obs): + raise NotImplementedError + + @classmethod + def map_action(cls, input_action): + raise NotImplementedError + + @classmethod + def unmap_action(cls, input_action): + raise NotImplementedError + + @classmethod + def get_metadata(cls, name): + raise NotImplementedError + + @classmethod + def map_obs_in_eval(cls, input_obs): + output_obs = {} + mapped_obs = cls.map_obs(input_obs) + for k, v in mapped_obs.items(): + assert k.startswith("hand.") or k.startswith("body.") + output_obs["state." + k[5:]] = v + return output_obs + + @classmethod + def get_missing_keys_in_dumping_dataset(cls): + return {} + + @classmethod + def convert_to_float64(cls, input): + for k, v in input.items(): + if isinstance(v, np.ndarray) and v.dtype == np.float32: + input[k] = v.astype(np.float64) + return input + + @classmethod + def deduce_observation_space(cls, env): + obs = ( + env.viewer._get_observations(force_update=True) + if env.viewer_get_obs + else env._get_observations(force_update=True) + ) + obs.update(gather_robot_observations(env)) + obs = cls.map_obs(obs) + observation_space = spaces.Dict() + + for k, v in obs.items(): + if k.startswith("hand.") or k.startswith("body."): + observation_space["state." + k[5:]] = spaces.Box( + low=-1, high=1, shape=(len(v),), dtype=np.float32 + ) + else: + raise ValueError(f"Unknown key: {k}") + + return observation_space + + @classmethod + def deduce_action_space(cls, env): + action = cls.map_action(reconstruct_latest_actions(env)) + action_space = spaces.Dict() + for k, v in action.items(): + if isinstance(v, np.int64): + action_space["action." + k[5:]] = spaces.Discrete(2) + elif isinstance(v, np.ndarray): + action_space["action." + k[5:]] = spaces.Box( + low=-1, high=1, shape=(len(v),), dtype=np.float32 + ) + else: + raise ValueError(f"Unknown type: {type(v)}") + return action_space + + +class GR1ArmsOnlyKeyConverter(RobotKeyConverter): + @classmethod + def get_camera_config(cls): + mapped_names = ["video.ego_view_pad_res256_freq20"] + camera_names = [ + "egoview", + ] + camera_widths, camera_heights = 1280, 800 + return mapped_names, camera_names, camera_widths, camera_heights + + @classmethod + def map_obs(cls, input_obs): + output_obs = type(input_obs)() + output_obs = { + "hand.right_hand": input_obs["robot0_right_gripper"], + "hand.left_hand": input_obs["robot0_left_gripper"], + "body.right_arm": input_obs["robot0_right"], + "body.left_arm": input_obs["robot0_left"], + } + return output_obs + + @classmethod + def map_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "hand.left_hand": input_action["robot0_left_gripper"], + "hand.right_hand": input_action["robot0_right_gripper"], + "body.left_arm": input_action["robot0_left"], + "body.right_arm": input_action["robot0_right"], + } + return output_action + + @classmethod + def unmap_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "robot0_left_gripper": input_action["action.left_hand"], + "robot0_right_gripper": input_action["action.right_hand"], + "robot0_left": input_action["action.left_arm"], + "robot0_right": input_action["action.right_arm"], + } + return output_action + + @classmethod + def get_missing_keys_in_dumping_dataset(cls): + return { + "body.waist": np.zeros(3, dtype=np.float64), + "body.neck": np.zeros(3, dtype=np.float64), + "body.right_leg": np.zeros(6, dtype=np.float64), + "body.left_leg": np.zeros(6, dtype=np.float64), + } + + @classmethod + def get_metadata(cls, name): + return { + "absolute": True, + "rotation_type": None, + } + + +class GR1ArmsAndWaistKeyConverter(RobotKeyConverter): + @classmethod + def get_camera_config(cls): + mapped_names = ["video.ego_view_pad_res256_freq20"] + camera_names = [ + "egoview", + ] + camera_widths, camera_heights = 1280, 800 + return mapped_names, camera_names, camera_widths, camera_heights + + @classmethod + def map_obs(cls, input_obs): + output_obs = type(input_obs)() + output_obs = { + "hand.right_hand": input_obs["robot0_right_gripper"], + "hand.left_hand": input_obs["robot0_left_gripper"], + "body.right_arm": input_obs["robot0_right"], + "body.left_arm": input_obs["robot0_left"], + "body.waist": input_obs["robot0_torso"], + } + return output_obs + + @classmethod + def map_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "hand.left_hand": input_action["robot0_left_gripper"], + "hand.right_hand": input_action["robot0_right_gripper"], + "body.left_arm": input_action["robot0_left"], + "body.right_arm": input_action["robot0_right"], + "body.waist": input_action["robot0_torso"], + } + return output_action + + @classmethod + def unmap_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "robot0_left_gripper": input_action["action.left_hand"], + "robot0_right_gripper": input_action["action.right_hand"], + "robot0_left": input_action["action.left_arm"], + "robot0_right": input_action["action.right_arm"], + "robot0_torso": input_action["action.waist"], + } + return output_action + + @classmethod + def get_missing_keys_in_dumping_dataset(cls): + return { + "body.neck": np.zeros(3, dtype=np.float64), + "body.right_leg": np.zeros(6, dtype=np.float64), + "body.left_leg": np.zeros(6, dtype=np.float64), + } + + @classmethod + def get_metadata(cls, name): + return { + "absolute": True, + "rotation_type": None, + } + + +class GR1FixedLowerBodyKeyConverter(RobotKeyConverter): + @classmethod + def get_camera_config(cls): + mapped_names = ["video.agentview_pad_res256_freq20"] + camera_names = [ + "agentview", + ] + camera_widths, camera_heights = 1280, 800 + return mapped_names, camera_names, camera_widths, camera_heights + + @classmethod + def map_obs(cls, input_obs): + output_obs = type(input_obs)() + output_obs = { + "hand.right_hand": input_obs["robot0_right_gripper"], + "hand.left_hand": input_obs["robot0_left_gripper"], + "body.right_arm": input_obs["robot0_right"], + "body.left_arm": input_obs["robot0_left"], + "body.waist": input_obs["robot0_torso"], + "body.neck": input_obs["robot0_head"], + } + return output_obs + + @classmethod + def map_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "hand.left_hand": input_action["robot0_left_gripper"], + "hand.right_hand": input_action["robot0_right_gripper"], + "body.left_arm": input_action["robot0_left"], + "body.right_arm": input_action["robot0_right"], + "body.waist": input_action["robot0_torso"], + "body.neck": input_action["robot0_head"], + } + return output_action + + @classmethod + def unmap_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "robot0_left_gripper": input_action["action.left_hand"], + "robot0_right_gripper": input_action["action.right_hand"], + "robot0_left": input_action["action.left_arm"], + "robot0_right": input_action["action.right_arm"], + "robot0_torso": input_action["action.waist"], + "robot0_head": input_action["action.neck"], + } + return output_action + + @classmethod + def get_missing_keys_in_dumping_dataset(cls): + return { + "body.right_leg": np.zeros(6, dtype=np.float64), + "body.left_leg": np.zeros(6, dtype=np.float64), + } + + @classmethod + def get_metadata(cls, name): + return { + "absolute": True, + "rotation_type": None, + } + + +class PandaOmronKeyConverter(RobotKeyConverter): + @classmethod + def get_camera_config(cls): + mapped_names = [ + "video.res256_image_side_0", + "video.res256_image_side_1", + "video.res256_image_wrist_0", + ] + camera_names = [ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ] + camera_widths, camera_heights = 512, 512 + return mapped_names, camera_names, camera_widths, camera_heights + + @classmethod + def map_obs(cls, input_obs): + output_obs = type(input_obs)() + output_obs = { + "hand.gripper_qpos": input_obs["robot0_gripper_qpos"], + "body.base_position": input_obs["robot0_base_pos"], + "body.base_rotation": input_obs["robot0_base_quat"], + "body.end_effector_position_relative": input_obs["robot0_base_to_eef_pos"], + "body.end_effector_rotation_relative": input_obs["robot0_base_to_eef_quat"], + "hand.gripper_qvel": input_obs["robot0_gripper_qvel"], + "body.end_effector_position_absolute": input_obs["robot0_eef_pos"], + "body.end_effector_rotation_absolute": input_obs["robot0_eef_quat"], + "body.joint_position": input_obs["robot0_joint_pos"], + "body.joint_position_cos": input_obs["robot0_joint_pos_cos"], + "body.joint_position_sin": input_obs["robot0_joint_pos_sin"], + "body.joint_velocity": input_obs["robot0_joint_vel"], + } + return output_obs + + @classmethod + def map_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "hand.gripper_close": np.int64(0) + if input_action["robot0_right_gripper"] < 0 + else np.int64(1), + "body.end_effector_position": input_action["robot0_right"][..., 0:3], + "body.end_effector_rotation": input_action["robot0_right"][..., 3:6], + "body.base_motion": np.concatenate( + ( + input_action["robot0_base"], + input_action["robot0_torso"], + ), + axis=-1, + ), + "body.control_mode": np.int64(0) + if input_action["robot0_base_mode"] < 0 + else np.int64(1), + } + return output_action + + @classmethod + def unmap_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "robot0_right_gripper": -1.0 + if input_action["action.gripper_close"] < 0.5 + else 1.0, + "robot0_right": np.concatenate( + ( + input_action["action.end_effector_position"], + input_action["action.end_effector_rotation"], + ), + axis=-1, + ), + "robot0_base": input_action["action.base_motion"][..., 0:3], + "robot0_torso": input_action["action.base_motion"][..., 3:4], + "robot0_base_mode": -1.0 + if input_action["action.control_mode"] < 0.5 + else 1.0, + } + return output_action + + @classmethod + def get_metadata(cls, name): + if name in [ + "body.base_position", + "body.end_effector_position_relative", + "body.end_effector_position", + ]: + return { + "absolute": False, + "rotation_type": None, + } + elif name in ["body.base_rotation", "body.end_effector_rotation_relative"]: + return { + "absolute": False, + "rotation_type": RotationType.QUATERNION, + } + elif name in ["body.end_effector_rotation"]: + return { + "absolute": False, + "rotation_type": RotationType.AXIS_ANGLE, + } + else: + return { + "absolute": True, + "rotation_type": None, + } + + +class PandaPandaKeyConverter(RobotKeyConverter): + @classmethod + def get_camera_config(cls): + mapped_names = [ + "video.agentview_pad_res256_freq20", + "video.robot0_eye_in_hand_pad_res256_freq20", + "video.robot1_eye_in_hand_pad_res256_freq20", + ] + camera_names = [ + "agentview", + "robot0_eye_in_hand", + "robot1_eye_in_hand", + ] + camera_widths, camera_heights = 1280, 800 + return mapped_names, camera_names, camera_widths, camera_heights + + @classmethod + def map_obs(cls, input_obs): + output_obs = type(input_obs)() + output_obs = { + "hand.right_gripper_qpos": input_obs["robot0_right_gripper"], + "hand.left_gripper_qpos": input_obs["robot1_right_gripper"], + "body.right_arm_eef_pos": input_obs["robot0_eef_pos"], + "body.right_arm_eef_quat": input_obs["robot0_eef_quat"], + "body.right_arm_joint_pos": input_obs["robot0_joint_pos"], + "body.left_arm_eef_pos": input_obs["robot1_eef_pos"], + "body.left_arm_eef_quat": input_obs["robot1_eef_quat"], + "body.left_arm_joint_pos": input_obs["robot1_joint_pos"], + } + return output_obs + + @classmethod + def map_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "hand.right_gripper_close": np.int64(0) + if input_action["robot0_right_gripper"] < 0 + else np.int64(1), + "hand.left_gripper_close": np.int64(0) + if input_action["robot1_right_gripper"] < 0 + else np.int64(1), + "body.right_arm_eef_pos": input_action["robot0_right"][..., 0:3], + "body.right_arm_eef_rot": input_action["robot0_right"][..., 3:6], + "body.left_arm_eef_pos": input_action["robot1_right"][..., 0:3], + "body.left_arm_eef_rot": input_action["robot1_right"][..., 3:6], + } + return output_action + + @classmethod + def unmap_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "robot0_right_gripper": -1.0 + if input_action["action.right_gripper_close"] < 0.5 + else 1.0, + "robot1_right_gripper": -1.0 + if input_action["action.left_gripper_close"] < 0.5 + else 1.0, + "robot0_right": np.concatenate( + ( + input_action["action.right_arm_eef_pos"], + input_action["action.right_arm_eef_rot"], + ), + axis=-1, + ), + "robot1_right": np.concatenate( + ( + input_action["action.left_arm_eef_pos"], + input_action["action.left_arm_eef_rot"], + ), + axis=-1, + ), + } + return output_action + + @classmethod + def get_metadata(cls, name): + if name in ["body.right_arm_eef_pos", "body.left_arm_eef_pos"]: + return { + "absolute": False, + "rotation_type": None, + } + elif name in ["body.right_arm_eef_quat", "body.right_arm_eef_quat"]: + return { + "absolute": False, + "rotation_type": RotationType.QUATERNION, + } + elif name in ["body.right_arm_eef_rot", "body.left_arm_eef_rot"]: + return { + "absolute": False, + "rotation_type": RotationType.AXIS_ANGLE, + } + else: + return { + "absolute": True, + "rotation_type": None, + } + + +class PandaDexRHPandaDexRHKeyConverter(RobotKeyConverter): + @classmethod + def get_camera_config(cls): + mapped_names = [ + "video.agentview_pad_res256_freq20", + "video.robot0_eye_in_hand_pad_res256_freq20", + "video.robot1_eye_in_hand_pad_res256_freq20", + ] + camera_names = [ + "agentview", + "robot0_eye_in_hand", + "robot1_eye_in_hand", + ] + camera_widths, camera_heights = 1280, 800 + return mapped_names, camera_names, camera_widths, camera_heights + + @classmethod + def map_obs(cls, input_obs): + output_obs = type(input_obs)() + output_obs = { + "hand.right_hand": input_obs["robot0_right_gripper"], + "hand.left_hand": input_obs["robot1_right_gripper"], + "body.right_arm_eef_pos": input_obs["robot0_eef_pos"], + "body.right_arm_eef_quat": input_obs["robot0_eef_quat"], + "body.right_arm_joint_pos": input_obs["robot0_joint_pos"], + "body.left_arm_eef_pos": input_obs["robot1_eef_pos"], + "body.left_arm_eef_quat": input_obs["robot1_eef_quat"], + "body.left_arm_joint_pos": input_obs["robot1_joint_pos"], + } + return output_obs + + @classmethod + def map_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "hand.right_hand": input_action["robot0_right_gripper"], + "hand.left_hand": input_action["robot1_right_gripper"], + "body.right_arm_eef_pos": input_action["robot0_right"][0:3], + "body.right_arm_eef_rot": input_action["robot0_right"][3:6], + "body.left_arm_eef_pos": input_action["robot1_right"][0:3], + "body.left_arm_eef_rot": input_action["robot1_right"][3:6], + } + return output_action + + @classmethod + def unmap_action(cls, input_action): + output_action = type(input_action)() + output_action = { + "robot0_right_gripper": input_action["action.right_hand"], + "robot1_right_gripper": input_action["action.left_hand"], + "robot0_right": np.concatenate( + ( + input_action["action.right_arm_eef_pos"], + input_action["action.right_arm_eef_rot"], + ), + axis=-1, + ), + "robot1_right": np.concatenate( + ( + input_action["action.left_arm_eef_pos"], + input_action["action.left_arm_eef_rot"], + ), + axis=-1, + ), + } + return output_action + + @classmethod + def get_metadata(cls, name): + if name in ["body.right_arm_eef_pos", "body.left_arm_eef_pos"]: + return { + "absolute": False, + "rotation_type": None, + } + elif name in ["body.right_arm_eef_quat", "body.right_arm_eef_quat"]: + return { + "absolute": False, + "rotation_type": RotationType.QUATERNION, + } + elif name in ["body.right_arm_eef_rot", "body.left_arm_eef_rot"]: + return { + "absolute": False, + "rotation_type": RotationType.AXIS_ANGLE, + } + else: + return { + "absolute": True, + "rotation_type": None, + } + + +# The values are only used in groot dataset embodiment tag and env name +GROOT_ROBOCASA_ENVS_GR1_ARMS_ONLY = { + "GR1ArmsOnly": "gr1_arms_only_fourier_hands", + "GR1ArmsOnlyInspireHands": "gr1_arms_only_inspire_hands", + "GR1ArmsOnlyFourierHands": "gr1_arms_only_fourier_hands", +} +GROOT_ROBOCASA_ENVS_GR1_ARMS_AND_WAIST = { + "GR1ArmsAndWaistFourierHands": "gr1_arms_waist_fourier_hands", +} +GROOT_ROBOCASA_ENVS_GR1_FIXED_LOWER_BODY = { + "GR1FixedLowerBody": "gr1_fixed_lower_body_fourier_hands", + "GR1FixedLowerBodyInspireHands": "gr1_fixed_lower_body_inspire_hands", + "GR1FixedLowerBodyFourierHands": "gr1_fixed_lower_body_fourier_hands", +} +GROOT_ROBOCASA_ENVS_PANDA = { + "PandaMobile": "panda_mobile", + "PandaOmron": "panda_omron", +} +GROOT_ROBOCASA_ENVS_BIMANUAL_GRIPPER = { + "Panda_Panda": "bimanual_panda_parallel_gripper", +} +GROOT_ROBOCASA_ENVS_BIMANUAL_HAND = { + "PandaDexRH_PandaDexLH": "bimanual_panda_inspire_hand", +} +GROOT_ROBOCASA_ENVS_ROBOTS = { + **GROOT_ROBOCASA_ENVS_GR1_ARMS_ONLY, + **GROOT_ROBOCASA_ENVS_GR1_ARMS_AND_WAIST, + **GROOT_ROBOCASA_ENVS_GR1_FIXED_LOWER_BODY, + **GROOT_ROBOCASA_ENVS_PANDA, + **GROOT_ROBOCASA_ENVS_BIMANUAL_GRIPPER, + **GROOT_ROBOCASA_ENVS_BIMANUAL_HAND, +} + + +def make_key_converter(robots_name): + if robots_name in GROOT_ROBOCASA_ENVS_GR1_ARMS_ONLY: + return GR1ArmsOnlyKeyConverter + elif robots_name in GROOT_ROBOCASA_ENVS_GR1_ARMS_AND_WAIST: + return GR1ArmsAndWaistKeyConverter + elif robots_name in GROOT_ROBOCASA_ENVS_GR1_FIXED_LOWER_BODY: + return GR1FixedLowerBodyKeyConverter + elif robots_name in GROOT_ROBOCASA_ENVS_PANDA: + return PandaOmronKeyConverter + elif robots_name in GROOT_ROBOCASA_ENVS_BIMANUAL_GRIPPER: + return PandaPandaKeyConverter + elif robots_name in GROOT_ROBOCASA_ENVS_BIMANUAL_HAND: + return PandaDexRHPandaDexRHKeyConverter + else: + raise ValueError(f"Unknown robot name: {robots_name}") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0d114e7fa12939a4a9d9578f5e5950e0e997f100 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/__init__.py @@ -0,0 +1 @@ +from .kitchen_arena import KitchenArena diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/kitchen_arena.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/kitchen_arena.py new file mode 100644 index 0000000000000000000000000000000000000000..ba27460e1580905037a0fdfce020509ae5c5448e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/kitchen_arena.py @@ -0,0 +1,52 @@ +from robosuite.models.arenas import Arena +from robosuite.utils.mjcf_utils import xml_path_completion + +import robocasa +from robocasa.models.scenes.scene_builder import create_fixtures + + +# base class for kitchens +class KitchenArena(Arena): + """ + Kitchen arena class holding all of the fixtures + + Args: + layout_id (int or LayoutType): layout of the kitchen to load + + style_id (int or StyleType): style of the kitchen to load + + rng (np.random.Generator): random number generator used for initializing + fixture state in the KitchenArena + """ + + def __init__(self, layout_id, style_id, rng=None): + super().__init__( + xml_path_completion( + "arenas/empty_kitchen_arena.xml", root=robocasa.models.assets_root + ) + ) + self.fixtures = create_fixtures( + layout_id=layout_id, + style_id=style_id, + rng=rng, + ) + + def get_fixture_cfgs(self): + """ + Returns config data for all fixtures in the arena + + Returns: + list: list of fixture configurations + """ + fixture_cfgs = [] + for (name, fxtr) in self.fixtures.items(): + cfg = {} + cfg["name"] = name + cfg["model"] = fxtr + cfg["type"] = "fixture" + if hasattr(fxtr, "_placement"): + cfg["placement"] = fxtr._placement + + fixture_cfgs.append(cfg) + + return fixture_cfgs diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_builder.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_builder.py new file mode 100644 index 0000000000000000000000000000000000000000..7a6ddb17fdac5061c916864f3f1f9f85342fc51e --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_builder.py @@ -0,0 +1,293 @@ +import numpy as np +import yaml +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import string_to_array as s2a + +from robocasa.models.scenes.scene_registry import get_layout_path, get_style_path +from robocasa.models.scenes.scene_utils import * +from robocasa.models.fixtures import * + +# fixture string to class +FIXTURES = dict( + hinge_cabinet=HingeCabinet, + single_cabinet=SingleCabinet, + open_cabinet=OpenCabinet, + panel_cabinet=PanelCabinet, + housing_cabinet=HousingCabinet, + drawer=Drawer, + counter=Counter, + stove=Stove, + stovetop=Stovetop, + oven=Oven, + microwave=Microwave, + hood=Hood, + sink=Sink, + fridge=Fridge, + dishwasher=Dishwasher, + wall=Wall, + floor=Floor, + box=Box, + accessory=Accessory, + paper_towel=Accessory, + plant=Accessory, + knife_block=Accessory, + stool=Stool, + utensil_holder=Accessory, + coffee_machine=CoffeeMachine, + toaster=Toaster, + utensil_rack=WallAccessory, + wall_accessory=WallAccessory, + window=Window, + framed_window=FramedWindow, + # needs some additional work + # slide_cabinet=SlideCabinet, +) +# fixtures that are attached to other fixtures, disables positioning system in this script +FIXTURES_INTERIOR = dict( + sink=Sink, stovetop=Stovetop, accessory=Accessory, wall_accessory=WallAccessory +) + +ALL_SIDES = ["left", "right", "front", "back", "bottom", "top"] + + +def check_syntax(fixture): + """ + Checks that specifications of a fixture follows syntax rules + """ + + if fixture["type"] != "stack" and fixture["type"] not in FIXTURES: + raise ValueError( + 'Invalid value for fixture type: "{}".'.format(fixture["type"]) + ) + + if "config_name" in fixture and "default_config_name" in fixture: + raise ValueError('Cannot specify both "config_name" and "default_config_name"') + + if "align_to" in fixture or "side" in fixture or "alignment" in fixture: + if not ("align_to" in fixture and "side" in fixture): + raise ValueError( + 'Both or neither of "align_to" and ' '"side" need to be specified.' + ) + if "pos" in fixture: + raise ValueError("Cannot specify both relative and absolute positions.") + + # check alignment and side arguments are compatible + if "alignment" in fixture: + for keywords in AXES_KEYWORDS.values(): + if fixture["side"] in keywords: + # check that neither keyword is used for alignment + if ( + keywords[0] in fixture["alignment"] + or keywords[1] in fixture["alignment"] + ): + raise ValueError( + 'Cannot set alignment to "{}" when aligning to the "{}" side'.format( + fixture["alignment"], fixture["side"] + ) + ) + + # check if side is valid + if fixture["side"] not in ALL_SIDES: + raise ValueError( + '"{}" is not a valid side for alignment'.format(fixture["side"]) + ) + + +def create_fixtures(layout_id, style_id, rng=None): + """ + Initializes fixtures based on the given layout yaml file and style type + + Args: + layout_id (int or LayoutType): layout of the kitchen to load + + style_id (int or StyleType): style of the kitchen to load + + rng (np.random.Generator): random number generator used for initializing fixture state + """ + try: + style = int(style) + except: + pass + + layout_path = get_layout_path(layout_id=layout_id) + style_path = get_style_path(style_id=style_id) + + # load style + with open(style_path, "r") as f: + style = yaml.safe_load(f) + + # load arena + with open(layout_path, "r") as f: + arena_config = yaml.safe_load(f) + + # contains all fixtures with updated configs + arena = list() + + # Update each fixture config. First iterate through groups: subparts of the arena that can be + # rotated and displaced together. example: island group, right group, room group, etc + for group_name, group_config in arena_config.items(): + group_fixtures = list() + # each group is further divded into similar subcollections of fixtures + # ex: main group counter accessories, main group top cabinets, etc + for k, fixture_list in group_config.items(): + # these values are rotations/displacements that are applied to all fixtures in the group + if k in ["group_origin", "group_z_rot", "group_pos"]: + continue + elif type(fixture_list) != list: + raise ValueError('"{}" is not a valid argument for groups'.format(k)) + + # add suffix to support different groups + for fxtr_config in fixture_list: + fxtr_config["name"] += "_" + group_name + # update fixture names for alignment, interior objects, etc. + for k in ATTACH_ARGS + ["align_to", "stack_fixtures", "size"]: + if k in fxtr_config: + if isinstance(fxtr_config[k], list): + for i in range(len(fxtr_config[k])): + if isinstance(fxtr_config[k][i], str): + fxtr_config[k][i] += "_" + group_name + else: + if isinstance(fxtr_config[k], str): + fxtr_config[k] += "_" + group_name + + group_fixtures.extend(fixture_list) + + # update group rotation/displacement if necessary + if "group_origin" in group_config: + for fxtr_config in group_fixtures: + # do not update the rotation of the walls/floor + if fxtr_config["type"] in ["wall", "floor"]: + continue + fxtr_config["group_origin"] = group_config["group_origin"] + fxtr_config["group_pos"] = group_config["group_pos"] + fxtr_config["group_z_rot"] = group_config["group_z_rot"] + + # addto overall fixture list + arena.extend(group_fixtures) + + # maps each fixture name to its object class + fixtures = dict() + # maps each fixture name to its configuration + configs = dict() + # names of composites, delete from fixtures before returning + composites = list() + + # initialize each fixture in the arena by processing config + for fixture_config in arena: + check_syntax(fixture_config) + fixture_name = fixture_config["name"] + + # stack of fixtures, handled separately + if fixture_config["type"] == "stack": + stack = FixtureStack( + fixture_config, + fixtures, + configs, + style, + default_texture=None, + rng=rng, + ) + fixtures[fixture_name] = stack + configs[fixture_name] = fixture_config + composites.append(fixture_name) + continue + + # load style information and update config to include it + default_config = load_style_config(style, fixture_config) + if default_config is not None: + for k, v in fixture_config.items(): + default_config[k] = v + fixture_config = default_config + + # set fixture type + fixture_config["type"] = FIXTURES[fixture_config["type"]] + + # pre-processing for fixture size + size = fixture_config.get("size", None) + if isinstance(size, list): + for i in range(len(size)): + elem = size[i] + if isinstance(elem, str): + ref_fxtr = fixtures[elem] + size[i] = ref_fxtr.size[i] + + # initialize fixture + fixture = initialize_fixture(fixture_config, fixtures, rng=rng) + fixtures[fixture_name] = fixture + configs[fixture_name] = fixture_config + + # update fixture position + if fixture_config["type"] not in FIXTURES_INTERIOR.values(): + # relative positioning + if "align_to" in fixture_config: + pos = get_relative_position( + fixture, + fixture_config, + fixtures[fixture_config["align_to"]], + configs[fixture_config["align_to"]], + ) + + elif "stack_on" in fixture_config: + stack_on = fixtures[fixture_config["stack_on"]] + + # account for off-centered objects + stack_on_center = stack_on.center + + # infer unspecified axes of position + pos = fixture_config["pos"] + if pos[0] is None: + pos[0] = stack_on.pos[0] + stack_on_center[0] + if pos[1] is None: + pos[1] = stack_on.pos[1] + stack_on_center[1] + + # calculate height of fixture + pos[2] = stack_on.pos[2] + stack_on.size[2] / 2 + fixture.size[2] / 2 + pos[2] += stack_on_center[2] + else: + # absolute position + pos = fixture_config.get("pos", None) + if pos is not None and type(fixture) not in [Wall, Floor]: + fixture.set_pos(pos) + + # composites are non-MujocoObjects, must remove + for composite in composites: + del fixtures[composite] + + # update the rotation and postion of each fixture based on their group + for name, fixture in fixtures.items(): + # check if updates are necessary + config = configs[name] + if "group_origin" not in config: + continue + + # TODO: add default for group origin? + # rotate about this coordinate (around the z-axis) + origin = config["group_origin"] + pos = config["group_pos"] + z_rot = config["group_z_rot"] + displacement = [pos[0] - origin[0], pos[1] - origin[1]] + + if type(fixture) not in [Wall, Floor]: + dx = fixture.pos[0] - origin[0] + dy = fixture.pos[1] - origin[1] + dx_rot = dx * np.cos(z_rot) - dy * np.sin(z_rot) + dy_rot = dx * np.sin(z_rot) + dy * np.cos(z_rot) + + x_rot = origin[0] + dx_rot + y_rot = origin[1] + dy_rot + z = fixture.pos[2] + pos_new = [x_rot + displacement[0], y_rot + displacement[1], z] + + # account for previous z-axis rotation + rot_prev = fixture._obj.get("euler") + if rot_prev is not None: + # TODO: switch to quaternion since euler rotations are ambiguous + rot_new = s2a(rot_prev) + rot_new[2] += z_rot + else: + rot_new = [0, 0, z_rot] + + fixture._obj.set("pos", a2s(pos_new)) + fixture._obj.set("euler", a2s(rot_new)) + + return fixtures diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_registry.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_registry.py new file mode 100644 index 0000000000000000000000000000000000000000..546e40b66470d8855ba4dda9797415a2af95c8f8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_registry.py @@ -0,0 +1,154 @@ +from collections import OrderedDict +from enum import IntEnum +from robosuite.utils.mjcf_utils import xml_path_completion +import robocasa + + +class LayoutType(IntEnum): + """ + Enum for available layouts in RoboCasa environment + """ + + ONE_WALL_SMALL = 0 + ONE_WALL_LARGE = 1 + L_SHAPED_SMALL = 2 + L_SHAPED_LARGE = 3 + GALLEY = 4 + U_SHAPED_SMALL = 5 + U_SHAPED_LARGE = 6 + G_SHAPED_SMALL = 7 + G_SHAPED_LARGE = 8 + WRAPAROUND = 9 + + # negative values correspond to groups (see LAYOUT_GROUPS_TO_IDS) + ALL = -1 + NO_ISLAND = -2 + ISLAND = -3 + DINING = -4 + + +LAYOUT_GROUPS_TO_IDS = { + -1: list(range(10)), # all + -2: [0, 2, 4, 5, 7], # no island + -3: [1, 3, 6, 8, 9], # island + -4: [1, 3, 6, 7, 8, 9], # dining +} + + +class StyleType(IntEnum): + """ + Enums for available styles in RoboCasa environment + """ + + INDUSTRIAL = 0 + SCANDANAVIAN = 1 + COASTAL = 2 + MODERN_1 = 3 + MODERN_2 = 4 + TRADITIONAL_1 = 5 + TRADITIONAL_2 = 6 + FARMHOUSE = 7 + RUSTIC = 8 + MEDITERRANEAN = 9 + TRANSITIONAL_1 = 10 + TRANSITIONAL_2 = 11 + + # negative values correspond to groups + ALL = -1 + + +STYLE_GROUPS_TO_IDS = { + -1: list(range(12)), # all +} + + +def get_layout_path(layout_id): + """ + Get corresponding blueprint filepath (yaml) for a layout + + Args: + layout_id (int or LayoutType): layout id (int or enum) + + Return: + str: yaml path for specified layout + """ + if isinstance(layout_id, int): + layout_int_to_name = dict( + map(lambda item: (item.value, item.name.lower()), LayoutType) + ) + layout_name = layout_int_to_name[layout_id] + elif isinstance(layout_id, LayoutType): + layout_name = layout_id.name.lower() + else: + raise ValueError + + # special case: if name starts with one letter, capitalize it + if layout_name[1] == "_": + layout_name = layout_name.capitalize() + + return xml_path_completion( + f"scenes/kitchen_layouts/{layout_name}.yaml", + root=robocasa.models.assets_root, + ) + + +def get_style_path(style_id): + """ + Get corresponding blueprint filepath (yaml) for a style + + Args: + style_id (int or StyleType): style id (int or enum) + + Return: + str: yaml path for specified style + """ + if isinstance(style_id, int): + style_int_to_name = dict( + map(lambda item: (item.value, item.name.lower()), StyleType) + ) + style_name = style_int_to_name[style_id] + elif isinstance(style_id, StyleType): + style_name = style_id.name.lower() + else: + raise ValueError + + return xml_path_completion( + f"scenes/kitchen_styles/{style_name}.yaml", + root=robocasa.models.assets_root, + ) + + +def unpack_layout_ids(layout_ids): + if layout_ids is None: + layout_ids = LayoutType.ALL + + if not isinstance(layout_ids, list): + layout_ids = [layout_ids] + + layout_ids = [int(id) for id in layout_ids] + + all_layout_ids = [] + for id in layout_ids: + if id < 0: + all_layout_ids += LAYOUT_GROUPS_TO_IDS[id] + else: + all_layout_ids.append(id) + return list(OrderedDict.fromkeys(all_layout_ids)) + + +def unpack_style_ids(style_ids): + if style_ids is None: + style_ids = StyleType.ALL + + if not isinstance(style_ids, list): + style_ids = [style_ids] + + style_ids = [int(id) for id in style_ids] + + all_style_ids = [] + for id in style_ids: + if id < 0: + all_style_ids += STYLE_GROUPS_TO_IDS[id] + else: + all_style_ids.append(id) + return list(OrderedDict.fromkeys(all_style_ids)) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..98dcced8de6c15209527c21a809f593ad81fc159 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/models/scenes/scene_utils.py @@ -0,0 +1,180 @@ +from collections import OrderedDict +from copy import deepcopy +import yaml +from robosuite.utils.mjcf_utils import xml_path_completion + +import robocasa + + +# second keyword corresponds to positive end of axis +AXES_KEYWORDS = {0: ["left", "right"], 1: ["front", "back"], 2: ["bottom", "top"]} + +# arguments not to be passed into fixture classes when initializing +IGNORE_ARGS = [ + "name", + "align_to", + "side", + "alignment", + "type", + "center", + "offset", + "group_origin", + "group_pos", + "group_z_rot", + "stack_height", + "stack_fixtures", +] + +# arguments used to point to other fixtures +ATTACH_ARGS = ["interior_obj", "stack_on", "attach_to"] + + +def initialize_fixture(config, cur_fixtures, rng=None): + """ + initializes a fixture object based on the given configuration + ignores positional arguments as it is changed later + + Args: + config (dict): dictionary containing the fixture configuration. + Serves as the arguments to initialize the fixture + + cur_fixtures (dict): dictionary containing the current fixtures + """ + + config = deepcopy(config) + name, class_type = config["name"], config["type"] + + # set size if stack_height is specified: + if config.get("stack_height", None) is not None: + stack_height = config["stack_height"] + stack_fixtures = config["stack_fixtures"] + curr_height = 0 + for fxtr in stack_fixtures: + curr_height += cur_fixtures[fxtr].size[2] + config["size"][2] = stack_height - curr_height + + # these fields should not be passed in when initializing the fixture + for field in IGNORE_ARGS: + if field in config: + del config[field] + + if "pos" not in config: + # need position to initialize fixture, adjusted later fo relative positioning + config["pos"] = [0.0, 0.0, 0.0] + + # update fixture pointers + for k in ATTACH_ARGS: + if k in config: + config[k] = cur_fixtures[config[k]] + + config["rng"] = rng + fixture = class_type(name=name, **config) + # print(class_type, name, type(fixture)) + return fixture + + +def load_style_config(style, fixture_config): + """ + Loads the style information for a given fixture. Style information can consist of + which xml to use if there are multiple instances of a fixture, which texture to apply, + which subcomponents to apply (panels/handles for a cab), etc. + + Args: + style (dict): dictionary containing the style information for each fixture type + + fixture_config (dict): dictionary containing the fixture configuration + """ + # accounts for the different types of cabinets + fixture_type = fixture_config["type"] + + # cabinets, shelves, drawers, and boxes use the same default configurations + if "cabinet" in fixture_type or "drawer" in fixture_type or "box" in fixture_type: + fixture_type = "cabinet" + + # if fixture_type not in style: + # raise ValueError("Did not specify fixture type \"{}\" in chosen style".format(fixture_type)) + fixture_style = style.get(fixture_type, "default") + + yaml_path = xml_path_completion( + f"fixtures/fixture_registry/{fixture_type}.yaml", + root=robocasa.models.assets_root, + ) + with open(yaml_path, "r") as f: + default_configs = yaml.safe_load(f) + + # find which configuration to use + if type(fixture_style) == dict and "config_name" not in fixture_config: + if "default_config_name" in fixture_config: + config_ids = fixture_style.get( + fixture_config["default_config_name"], fixture_style["default"] + ) + del fixture_config["default_config_name"] + else: + config_ids = fixture_style["default"] + elif "default_config_name" in fixture_config: + raise ValueError('Specified "default_config_name" but no default config found') + + elif "config_name" in fixture_config: + config_ids = fixture_config["config_name"] + del fixture_config["config_name"] + else: + config_ids = fixture_style + + # search for config by name + config = default_configs["default"] + if not isinstance(config_ids, list): + config_ids = [config_ids] + for cfg_id in config_ids: + if cfg_id in default_configs: + # add additional arguments based on default config + additional_config = default_configs[cfg_id] + for k, v in additional_config.items(): + config[k] = v + else: + raise ValueError( + 'Did not find style that matches "{}" for ' + 'fixture type "{}"'.format(cfg_id, fixture_type) + ) + return config + + +def get_relative_position(fixture, config, prev_fxtr, prev_fxtr_config): + """ + Calculates the position of `fixture` based on a specified side + and alignment relative to `prev_fixture` + + This assumes that the fixtures are properly centered! + """ + + side = config["side"].lower() + alignment = config["alignment"].lower() if "alignment" in config else "center" + size = fixture.size + prev_pos, prev_size = prev_fxtr.pos, prev_fxtr.size + + # for fixtures that are not perfectly centered (e.g. stoves) + prev_pos += prev_fxtr.origin_offset + + # place fixtures next to each others + for axis, keywords in AXES_KEYWORDS.items(): + if side not in keywords: + continue + pos = deepcopy(prev_pos) + if side == keywords[1]: + pos[axis] = prev_pos[axis] + prev_size[axis] / 2 + size[axis] / 2 + elif side == keywords[0]: + pos[axis] = prev_pos[axis] - prev_size[axis] / 2 - size[axis] / 2 + + # align such that the specified faces are flush + # alignment - side compatibility is checked in check_syntax() + for axis, keywords in AXES_KEYWORDS.items(): + if keywords[0] in alignment: + pos[axis] = prev_pos[axis] - prev_size[axis] / 2 + size[axis] / 2 + elif keywords[1] in alignment: + pos[axis] = prev_pos[axis] + prev_size[axis] / 2 - size[axis] / 2 + + if "offset" in config: + pos += config["offset"] + + # for fixtures that are not perfectly centered (e.g. stoves) + pos -= fixture.origin_offset + return pos diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/bench_speed.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/bench_speed.py new file mode 100644 index 0000000000000000000000000000000000000000..0d3031a221e8f5d9ceb98416b990c46c1da4ace8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/bench_speed.py @@ -0,0 +1,193 @@ +""" +A script to run benchmarking on environments. +Runs several rollouts and logs the reset times and fps of the environment. +""" + +import argparse +import os +import time + +import numpy as np +from termcolor import colored +from tianshou.env import SubprocVectorEnv + +import robosuite as suite +from robosuite.controllers import load_composite_controller_config +from robocasa import ALL_KITCHEN_ENVIRONMENTS +import robocasa + + +def run_rollout(env, arm, env_configuration, num_steps=200, render=False): + """ + Use the device (keyboard or SpaceNav 3D mouse) to collect a demonstration. + The rollout trajectory is saved to files in npz format. + Modify the DataCollectionWrapper wrapper to add new fields or change data formats. + Args: + env (MujocoEnv): environment to control + device (Device): to receive controls from the device + arms (str): which arm to control (eg bimanual) 'right' or 'left' + env_configuration (str): specified environment configuration + """ + + t_reset_start = time.time() + obs = env.reset() + # print(obs.keys()) + reset_time = time.time() - t_reset_start + + # ID = 2 always corresponds to agentview + if render: + env.render() + + # Loop until we get a reset from the input or the task completes + + if isinstance(env, SubprocVectorEnv): + ac_dim = env.get_env_attr(key="action_spec", id=0)[0][0].shape + ac_dim = list([len(env)]) + list(ac_dim) + else: + ac_dim = env.action_spec[0].shape + + t_start = time.time() + + for _ in range(num_steps): + # Get the newest action + action = np.random.normal(size=ac_dim) + + # Run environment step + obs, _, _, _ = env.step(action) + + # import cv2 + # im = obs["robot0_agentview_left_image"] + # cv2.imshow("offscreen render", im) + # key = cv2.waitKey(1) + + if render: + env.render() + + t_end = time.time() + steps_per_sec = num_steps / (t_end - t_start) + + # # cleanup for end of data collection episodes + # env.close() + + return reset_time, steps_per_sec + + +def log_info(message, color="yellow"): + print(colored(message, color)) + + +if __name__ == "__main__": + # Arguments + parser = argparse.ArgumentParser() + parser.add_argument("--mjcf_path", type=str, help="path to object MJCF") + parser.add_argument("--env", type=str, default="Lift") + parser.add_argument("--num_envs", type=int, default=1) + parser.add_argument("--n_objs", type=int, default=None) + parser.add_argument( + "--robots", + nargs="+", + type=str, + default="PandaOmron", + help="Which robot(s) to use in the env", + ) + parser.add_argument( + "--config", + type=str, + default="single-arm-opposed", + help="Specified environment configuration if necessary", + ) + parser.add_argument( + "--arm", + type=str, + default="right", + help="Which arm to control (eg bimanual) 'right' or 'left'", + ) + parser.add_argument( + "--camera", + type=str, + default=None, + help="Which camera to use for collecting demos", + ) + parser.add_argument( + "--seed", + type=int, + default=0, + help="Environment seed", + ) + parser.add_argument( + "--controller", + type=str, + default=None, + help="Choice of controller. Can be, eg. 'NONE' or 'WHOLE_BODY_IK', etc. Or path to controller json file", + ) + + parser.add_argument("--no_render", action="store_true") + args = parser.parse_args() + + def create_env(): + # Get controller config + # controller_config = load_controller_config(default_controller=args.controller) + controller_config = load_composite_controller_config( + controller=args.controller, + robot=args.robots, + ) + + # Create argument configuration + config = dict( + controller_configs=controller_config, + env_name=args.env, + has_renderer=False, + has_offscreen_renderer=(not args.no_render), + use_camera_obs=(not args.no_render), + render_camera=args.camera, + ignore_done=True, + reward_shaping=True, + control_freq=20, + camera_heights=84, + camera_widths=84, + ) + + if args.env in ALL_KITCHEN_ENVIRONMENTS: + config["camera_names"] = [ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ] + config["layout_ids"] = 0 + config["style_ids"] = 0 + config["seed"] = args.seed + + if args.env == "KitchenDemo" and args.n_objs is not None: + config["num_objs"] = args.n_objs + + config["robots"] = args.robots or "PandaOmron" + else: + config["robots"] = args.robots or "Panda" + + env = suite.make(**config) + return env + + if args.num_envs > 1: + env_fns = [lambda env_i=i: create_env() for i in range(args.num_envs)] + env = SubprocVectorEnv(env_fns) + else: + env = create_env() + + # collect demonstrations + steps_per_sec_list = [] + reset_time_list = [] + for ep in range(10): + reset_time, steps_per_sec = run_rollout( + env, args.arm, args.config, render=False, num_steps=100 + ) + print("ep #{}".format(ep + 1)) + print(" {:.2f}s reset time".format(reset_time)) + print(" {:.2f} fps".format(steps_per_sec)) + print() + reset_time_list.append(reset_time) + steps_per_sec_list.append(steps_per_sec) + + print("reset time: {:.2f}s".format(np.mean(reset_time_list))) + print("fps: {:.2f}".format(np.mean(steps_per_sec_list))) + + env.close() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/browse_mjcf_model.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/browse_mjcf_model.py new file mode 100644 index 0000000000000000000000000000000000000000..e3125f536a3738142bdf00015ee023755c56aec7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/browse_mjcf_model.py @@ -0,0 +1,256 @@ +"""Visualize MJCF models. +""" + +import argparse +import os +import time +import xml.etree.ElementTree as ET + +import cv2 +import mujoco +import mujoco.viewer +import numpy as np +import robosuite +from PIL import Image +from robosuite.utils.binding_utils import MjRenderContextOffscreen, MjSim +from robosuite.utils.mjcf_utils import array_to_string as a2s +from robosuite.utils.mjcf_utils import find_elements +from robosuite.utils.mjcf_utils import string_to_array as s2a + + +def edit_model_xml(xml_str): + """ + This function edits the model xml with custom changes, including resolving relative paths, + applying changes retroactively to existing demonstration files, and other custom scripts. + Environment subclasses should modify this function to add environment-specific xml editing features. + Args: + xml_str (str): Mujoco sim demonstration XML file as string + Returns: + str: Edited xml file as string + """ + + path = os.path.split(robosuite.__file__)[0] + path_split = path.split("/") + + # replace mesh and texture file paths + tree = ET.fromstring(xml_str) + root = tree + asset = root.find("asset") + meshes = asset.findall("mesh") + textures = asset.findall("texture") + all_elements = meshes + textures + + for elem in all_elements: + old_path = elem.get("file") + if old_path is None: + continue + + old_path_split = old_path.split("/") + # maybe replace all paths to robosuite assets + check_lst = [ + loc for loc, val in enumerate(old_path_split) if val == "robosuite" + ] + if len(check_lst) > 0: + ind = max(check_lst) # last occurrence index + new_path_split = path_split + old_path_split[ind + 1 :] + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + return ET.tostring(root, encoding="utf8").decode("utf8") + + +def read_model( + xml=None, + filepath=None, + hide_sites=True, + show_bbox=False, + show_coll_geoms=False, +): + # either xml string is provided directly or filename containing mjcf + assert (xml is not None) + (filepath is not None) == 1 + + if filepath is not None: + with open(filepath, "r") as file: + xml = file.read() + + xml = edit_model_xml(xml) + root = ET.fromstring(xml) + + # add white background + asset = find_elements(root, tags="asset") + skybox = ET.fromstring( + """""" + ) + asset.append(skybox) + + # add lighting + worldbody = find_elements(root, tags="worldbody") + light = ET.fromstring( + """""" + ) + worldbody.append(light) + + # make collision geoms (in)visible + geoms = find_elements(root, tags="geom", return_first=False) + for g in geoms: + if g.get("group", None) == "0": + if show_coll_geoms: + g.set("rgba", "1.0 0.0 0.0 0.5") + else: + g.set("rgba", "1.0 0.0 0.0 0.0") + + if show_bbox: + sites = {} + for site in find_elements(root, tags="site", return_first=False): + name = site.get("name", None) + if name is not None: + sites[name] = s2a(site.get("pos")) + + ext_bbox_center = None + ext_bbox_size = None + if "ext_p0" in sites: + ext_bbox_center = np.array( + [ + np.mean([sites["ext_p0"][0], sites["ext_px"][0]]), + np.mean([sites["ext_p0"][1], sites["ext_py"][1]]), + np.mean([sites["ext_p0"][2], sites["ext_pz"][2]]), + ] + ) + ext_bbox_size = np.array( + [ + sites["ext_px"][0] - sites["ext_p0"][0], + sites["ext_py"][1] - sites["ext_p0"][1], + sites["ext_pz"][2] - sites["ext_p0"][2], + ] + ) + elif "bottom_site" in sites: + ext_bbox_center = np.mean([sites["top_site"], sites["bottom_site"]], axis=0) + ext_bbox_size = ( + np.array( + [ + sites["horizontal_radius_site"][0], + sites["horizontal_radius_site"][1], + sites["top_site"][2] - ext_bbox_center[2], + ] + ) + * 2 + ) + + if (ext_bbox_center is not None) and (ext_bbox_size is not None): + ext_bbox_site = ET.fromstring( + """""".format( + pos=a2s(ext_bbox_center), + hsize=a2s(ext_bbox_size / 2), + ) + ) + worldbody.append(ext_bbox_site) + + sites = find_elements(root, tags="site", return_first=False) + if sites is not None: + if hide_sites: + # hide all sites + for site in sites: + site.set("rgba", "0 0 0 0") + else: + for site in sites: + rgba = s2a(site.get("rgba")) + # rgba[-1] = 1.0 + site.set("rgba", a2s(rgba)) + + info = {} + + # initialize model + xml = ET.tostring(root, encoding="unicode") + if filepath is not None: + os.chdir(os.path.dirname(filepath)) + t = time.time() + model = mujoco.MjModel.from_xml_string(xml) + sim = MjSim(model) + info["sim_load_time"] = time.time() - t + + return sim, info + + +def get_model_screenshot( + sim, + im_width=1024, + im_height=1024, + cam_settings=None, +): + t = time.time() + render_context = MjRenderContextOffscreen(sim, device_id=-1) + render_context.vopt.geomgroup[0] = 0 + # if cam_settings is None: + # cam_settings = {} + # render_context.cam.distance = cam_settings.get("distance", 1.75) + # render_context.cam.elevation = cam_settings.get("elevation", -30) + sim.add_render_context(render_context) + + print(info["sim_load_time"] + (time.time() - t)) + + image = sim.render(width=im_width, height=im_height)[::-1] + + return image + + +def render_model( + sim, + cam_settings=None, +): + if cam_settings is None: + cam_settings = {} + + mujoco.viewer.launch(sim.model._model, sim.data._data) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--mjcf", type=str, required=True) + parser.add_argument( + "--screenshot", + action="store_true", + help="save screenshot of model in same directory as filepath", + ) + parser.add_argument( + "--show_bbox", + action="store_true", + help="visualize exterior bounding box (based on ext_ sites)", + ) + parser.add_argument( + "--show_coll_geoms", + action="store_true", + help="whether to hide collision geoms (group 0)", + ) + args = parser.parse_args() + + # cam_settings = { + # "distance": 0.3, + # "elevation": -30, + # } + while True: + cam_settings = None + + sim, info = read_model( + xml=None, + filepath=args.mjcf, + hide_sites=False, + show_bbox=args.show_bbox, + show_coll_geoms=args.show_coll_geoms, + ) + print("sim load time:", info["sim_load_time"]) + + if args.screenshot: + image = get_model_screenshot( + sim=sim, + cam_settings=cam_settings, + ) + im = Image.fromarray(image) + im.save("screenshot.png") + else: + render_model( + sim=sim, + cam_settings=cam_settings, + ) + + # cv2.imshow('image', image[:,:,::-1]) + # cv2.waitKey(0) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/collect_demos.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/collect_demos.py new file mode 100644 index 0000000000000000000000000000000000000000..960c0243f5af3e47955d71848202c44620a14c50 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/collect_demos.py @@ -0,0 +1,529 @@ +""" +A script to collect a batch of human demonstrations that can be used +to generate a learning curriculum (see `demo_learning_curriculum.py`). + +The demonstrations can be played back using the `playback_demonstrations_from_pkl.py` +script. +""" + +import argparse +from copy import deepcopy +import datetime +import json +import os +import time +from glob import glob + +import h5py +import imageio +import mujoco +import numpy as np +import robosuite + +# from robosuite import load_controller_config +from robosuite.controllers import load_composite_controller_config +from robosuite.wrappers import DataCollectionWrapper, VisualizationWrapper +from termcolor import colored + +import robocasa +import robocasa.macros as macros +from robocasa.models.fixtures import FixtureType +from robocasa.utils.robomimic.robomimic_dataset_utils import convert_to_robomimic_format + + +def is_empty_input_spacemouse(action_dict): + if not np.all(action_dict["right_delta"] == 0): + return False + if "base_mode" in action_dict and action_dict["base_mode"] != -1: + return False + if "base" in action_dict and not np.all(action_dict["base"] == 0): + return False + + return True + + +def collect_human_trajectory( + env, + device, + arm, + env_configuration, + mirror_actions, + render=True, + max_fr=None, + print_info=True, +): + """ + Use the device (keyboard or SpaceNav 3D mouse) to collect a demonstration. + The rollout trajectory is saved to files in npz format. + Modify the DataCollectionWrapper wrapper to add new fields or change data formats. + + Args: + env (MujocoEnv): environment to control + device (Device): to receive controls from the device + arms (str): which arm to control (eg bimanual) 'right' or 'left' + env_configuration (str): specified environment configuration + """ + + env.reset() + + ep_meta = env.get_ep_meta() + # print(json.dumps(ep_meta, indent=4)) + lang = ep_meta.get("lang", None) + if print_info and lang is not None: + print(colored(f"Instruction: {lang}", "green")) + + # degugging: code block here to quickly test and close env + # env.close() + # return None, True + + if render: + # ID = 2 always corresponds to agentview + env.render() + + task_completion_hold_count = ( + -1 + ) # counter to collect 10 timesteps after reaching goal + device.start_control() + + nonzero_ac_seen = False + + # Keep track of prev gripper actions when using since they are position-based and must be maintained when arms switched + all_prev_gripper_actions = [ + { + f"{robot_arm}_gripper": np.repeat([0], robot.gripper[robot_arm].dof) + for robot_arm in robot.arms + if robot.gripper[robot_arm].dof > 0 + } + for robot in env.robots + ] + + zero_action = np.zeros(env.action_dim) + for _ in range(1): + # do a dummy step thru base env to initalize things, but don't record the step + if isinstance(env, DataCollectionWrapper): + env.env.step(zero_action) + else: + env.step(zero_action) + + discard_traj = False + + # Loop until we get a reset from the input or the task completes + while True: + start = time.time() + + # Set active robot + active_robot = env.robots[device.active_robot] + active_arm = device.active_arm + + # Get the newest action + input_ac_dict = device.input2action(mirror_actions=mirror_actions) + + # If action is none, then this a reset so we should break + if input_ac_dict is None: + discard_traj = True + break + + action_dict = deepcopy(input_ac_dict) + + # set arm actions + for arm in active_robot.arms: + controller_input_type = active_robot.part_controllers[arm].input_type + if controller_input_type == "delta": + action_dict[arm] = input_ac_dict[f"{arm}_delta"] + elif controller_input_type == "absolute": + action_dict[arm] = input_ac_dict[f"{arm}_abs"] + else: + raise ValueError + + if is_empty_input_spacemouse(action_dict): + if not nonzero_ac_seen: + if render: + env.render() + continue + else: + nonzero_ac_seen = True + + # Maintain gripper state for each robot but only update the active robot with action + env_action = [ + robot.create_action_vector(all_prev_gripper_actions[i]) + for i, robot in enumerate(env.robots) + ] + env_action[device.active_robot] = active_robot.create_action_vector(action_dict) + env_action = np.concatenate(env_action) + + # Run environment step + obs, _, _, _ = env.step(env_action) + if render: + env.render() + + # Also break if we complete the task + if task_completion_hold_count == 0: + break + + # state machine to check for having a success for 10 consecutive timesteps + if env._check_success(): + if task_completion_hold_count > 0: + task_completion_hold_count -= 1 # latched state, decrement count + else: + task_completion_hold_count = 10 # reset count on first success timestep + else: + task_completion_hold_count = -1 # null the counter if there's no success + + # limit frame rate if necessary + if max_fr is not None: + elapsed = time.time() - start + diff = 1 / max_fr - elapsed + if diff > 0: + time.sleep(diff) + + # with open("/home/soroushn/tmp/model.xml", "w") as f: + # f.write(env.model.get_xml()) + # exit() + + if nonzero_ac_seen and hasattr(env, "ep_directory"): + ep_directory = env.ep_directory + else: + ep_directory = None + + # cleanup for end of data collection episodes + env.close() + + return ep_directory, discard_traj + + +def gather_demonstrations_as_hdf5(directory, out_dir, env_info, excluded_episodes=None): + """ + Gathers the demonstrations saved in @directory into a + single hdf5 file. + The strucure of the hdf5 file is as follows. + data (group) + date (attribute) - date of collection + time (attribute) - time of collection + repository_version (attribute) - repository version used during collection + env (attribute) - environment name on which demos were collected + demo1 (group) - every demonstration has a group + model_file (attribute) - model xml string for demonstration + states (dataset) - flattened mujoco states + actions (dataset) - actions applied during demonstration + demo2 (group) + ... + Args: + directory (str): Path to the directory containing raw demonstrations. + out_dir (str): Path to where to store the hdf5 file. + env_info (str): JSON-encoded string containing environment information, + including controller and robot info + """ + + hdf5_path = os.path.join(out_dir, "demo.hdf5") + print("Saving hdf5 to", hdf5_path) + f = h5py.File(hdf5_path, "w") + + # store some metadata in the attributes of one group + grp = f.create_group("data") + + num_eps = 0 + env_name = None # will get populated at some point + + for ep_directory in os.listdir(directory): + # print("Processing {} ...".format(ep_directory)) + if (excluded_episodes is not None) and (ep_directory in excluded_episodes): + # print("\tExcluding this episode!") + continue + + state_paths = os.path.join(directory, ep_directory, "state_*.npz") + states = [] + actions = [] + actions_abs = [] + # success = False + + for state_file in sorted(glob(state_paths)): + dic = np.load(state_file, allow_pickle=True) + env_name = str(dic["env"]) + + states.extend(dic["states"]) + for ai in dic["action_infos"]: + actions.append(ai["actions"]) + if "actions_abs" in ai: + actions_abs.append(ai["actions_abs"]) + # success = success or dic["successful"] + + if len(states) == 0: + continue + + # # Add only the successful demonstration to dataset + # if success: + + # print("Demonstration is successful and has been saved") + # Delete the last state. This is because when the DataCollector wrapper + # recorded the states and actions, the states were recorded AFTER playing that action, + # so we end up with an extra state at the end. + del states[-1] + assert len(states) == len(actions) + + num_eps += 1 + ep_data_grp = grp.create_group("demo_{}".format(num_eps)) + + # store model xml as an attribute + xml_path = os.path.join(directory, ep_directory, "model.xml") + with open(xml_path, "r") as f: + xml_str = f.read() + ep_data_grp.attrs["model_file"] = xml_str + + # store ep meta as an attribute + ep_meta_path = os.path.join(directory, ep_directory, "ep_meta.json") + if os.path.exists(ep_meta_path): + with open(ep_meta_path, "r") as f: + ep_meta = f.read() + ep_data_grp.attrs["ep_meta"] = ep_meta + + # write datasets for states and actions + ep_data_grp.create_dataset("states", data=np.array(states)) + ep_data_grp.create_dataset("actions", data=np.array(actions)) + if len(actions_abs) > 0: + print(np.array(actions_abs).shape) + ep_data_grp.create_dataset("actions_abs", data=np.array(actions_abs)) + + # else: + # pass + # # print("Demonstration is unsuccessful and has NOT been saved") + + print("{} successful demos so far".format(num_eps)) + + if num_eps == 0: + f.close() + return + + # write dataset attributes (metadata) + now = datetime.datetime.now() + grp.attrs["date"] = "{}-{}-{}".format(now.month, now.day, now.year) + grp.attrs["time"] = "{}:{}:{}".format(now.hour, now.minute, now.second) + grp.attrs["robocasa_version"] = robocasa.__version__ + grp.attrs["robosuite_version"] = robosuite.__version__ + grp.attrs["mujoco_version"] = mujoco.__version__ + grp.attrs["env"] = env_name + grp.attrs["env_info"] = env_info + + f.close() + + return hdf5_path + + +if __name__ == "__main__": + # Arguments + parser = argparse.ArgumentParser() + parser.add_argument( + "--directory", + type=str, + default=os.path.join(robocasa.models.assets_root, "demonstrations_private"), + ) + parser.add_argument("--environment", type=str, default="Kitchen") + parser.add_argument( + "--robots", + nargs="+", + type=str, + default="PandaOmron", + help="Which robot(s) to use in the env", + ) + parser.add_argument( + "--config", + type=str, + default="single-arm-opposed", + help="Specified environment configuration if necessary", + ) + parser.add_argument( + "--arm", + type=str, + default="right", + help="Which arm to control (eg bimanual) 'right' or 'left'", + ) + parser.add_argument( + "--obj_groups", + type=str, + nargs="+", + default=None, + help="In kitchen environments, either the name of a group to sample object from or path to an .xml file", + ) + + parser.add_argument( + "--camera", + type=str, + default=None, + help="Which camera to use for collecting demos", + ) + parser.add_argument( + "--controller", + type=str, + default=None, + help="Choice of controller. Can be, eg. 'NONE' or 'WHOLE_BODY_IK', etc. Or path to controller json file", + ) + parser.add_argument( + "--device", + type=str, + default="spacemouse", + choices=["keyboard", "keyboardmobile", "spacemouse", "dummy"], + ) + parser.add_argument( + "--pos-sensitivity", + type=float, + default=4.0, + help="How much to scale position user inputs", + ) + parser.add_argument( + "--rot-sensitivity", + type=float, + default=4.0, + help="How much to scale rotation user inputs", + ) + + parser.add_argument("--debug", action="store_true") + parser.add_argument( + "--renderer", type=str, default="mjviewer", choices=["mjviewer", "mujoco"] + ) + parser.add_argument( + "--max_fr", default=30, type=int, help="If specified, limit the frame rate" + ) + + parser.add_argument("--layout", type=int, nargs="+", default=-1) + parser.add_argument( + "--style", type=int, nargs="+", default=[0, 1, 2, 3, 4, 5, 6, 7, 8, 11] + ) + parser.add_argument("--generative_textures", action="store_true") + args = parser.parse_args() + + # Get controller config + # controller_config = load_controller_config(default_controller=args.controller) + controller_config = load_composite_controller_config( + controller=args.controller, + robot=args.robots if isinstance(args.robots, str) else args.robots[0], + ) + + if controller_config["type"] == "WHOLE_BODY_MINK_IK": + # mink-speicific import. requires installing mink + from robosuite.examples.third_party_controller.mink_controller import ( + WholeBodyMinkIK, + ) + + env_name = args.environment + + # Create argument configuration + config = { + "env_name": env_name, + "robots": args.robots, + "controller_configs": controller_config, + } + + if args.generative_textures is True: + config["generative_textures"] = "100p" + + # Check if we're using a multi-armed environment and use env_configuration argument if so + if "TwoArm" in env_name: + config["env_configuration"] = args.config + + # Mirror actions if using a kitchen environment + if env_name in ["Lift"]: # add other non-kitchen tasks here + if args.obj_groups is not None: + print( + "Specifying 'obj_groups' in non-kitchen environment does not have an effect." + ) + mirror_actions = False + if args.camera is None: + args.camera = "agentview" + # special logic: "free" camera corresponds to Null camera + elif args.camera == "free": + args.camera = None + else: + mirror_actions = True + config["layout_ids"] = args.layout + config["style_ids"] = args.style + ### update config for kitchen envs ### + if args.obj_groups is not None: + config.update({"obj_groups": args.obj_groups}) + if args.camera is None: + args.camera = "robot0_frontview" + # special logic: "free" camera corresponds to Null camera + elif args.camera == "free": + args.camera = None + + config["translucent_robot"] = True + + # by default use obj instance split A + config["obj_instance_split"] = "A" + # config["obj_instance_split"] = None + # config["obj_registries"] = ("aigen",) + + # Create environment + env = robosuite.make( + **config, + has_renderer=True, + has_offscreen_renderer=False, + render_camera=args.camera, + ignore_done=True, + use_camera_obs=False, + control_freq=20, + renderer=args.renderer, + ) + + # Wrap this with visualization wrapper + env = VisualizationWrapper(env) + + # Grab reference to controller config and convert it to json-encoded string + env_info = json.dumps(config) + + t_now = time.time() + time_str = datetime.datetime.fromtimestamp(t_now).strftime("%Y-%m-%d-%H-%M-%S") + + if not args.debug: + # wrap the environment with data collection wrapper + tmp_directory = "/tmp/{}".format(time_str) + env = DataCollectionWrapper(env, tmp_directory) + + # initialize device + if args.device == "keyboard": + from robosuite.devices import Keyboard + + device = Keyboard( + env=env, + pos_sensitivity=args.pos_sensitivity, + rot_sensitivity=args.rot_sensitivity, + ) + elif args.device == "spacemouse": + from robosuite.devices import SpaceMouse + + device = SpaceMouse( + env=env, + pos_sensitivity=args.pos_sensitivity, + rot_sensitivity=args.rot_sensitivity, + vendor_id=macros.SPACEMOUSE_VENDOR_ID, + product_id=macros.SPACEMOUSE_PRODUCT_ID, + ) + else: + raise ValueError + + # make a new timestamped directory + new_dir = os.path.join(args.directory, time_str) + os.makedirs(new_dir) + + excluded_eps = [] + + # collect demonstrations + while True: + print() + ep_directory, discard_traj = collect_human_trajectory( + env, + device, + args.arm, + args.config, + mirror_actions, + render=(args.renderer != "mjviewer"), + max_fr=args.max_fr, + ) + + print("Keep traj?", not discard_traj) + + if not args.debug: + if discard_traj and ep_directory is not None: + excluded_eps.append(ep_directory.split("/")[-1]) + hdf5_path = gather_demonstrations_as_hdf5( + tmp_directory, new_dir, env_info, excluded_episodes=excluded_eps + ) + convert_to_robomimic_format(hdf5_path) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/dataset_states_to_obs.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/dataset_states_to_obs.py new file mode 100644 index 0000000000000000000000000000000000000000..462503c7f27432daf0c8c645a85ef71e594b17fe --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/dataset_states_to_obs.py @@ -0,0 +1,666 @@ +""" +Script to extract observations from low-dimensional simulation states in a robocasa dataset. +Adapted from robomimic's dataset_states_to_obs.py script. +""" +import os +import json +import h5py +import argparse +import numpy as np +from copy import deepcopy +import multiprocessing +import queue +import time +import traceback +import torch + +import robocasa.utils.robomimic.robomimic_tensor_utils as TensorUtils +import robocasa.utils.robomimic.robomimic_env_utils as EnvUtils +import robocasa.utils.robomimic.robomimic_dataset_utils as DatasetUtils + +# from robomimic.utils.log_utils import log_warning + + +def extract_trajectory( + env, + initial_state, + states, + actions, + done_mode, + add_datagen_info=False, +): + """ + Helper function to extract observations, rewards, and dones along a trajectory using + the simulator environment. + + Args: + env (instance of EnvBase): environment + initial_state (dict): initial simulation state to load + states (np.array): array of simulation states to load to extract information + actions (np.array): array of actions + done_mode (int): how to write done signal. If 0, done is 1 whenever s' is a + success state. If 1, done is 1 at the end of each trajectory. + If 2, do both. + """ + assert states.shape[0] == actions.shape[0] + + # load the initial state + env.reset() + obs = env.reset_to(initial_state) + + # get updated ep meta in case it's been modified + ep_meta = env.env.get_ep_meta() + initial_state["ep_meta"] = json.dumps(ep_meta, indent=4) + + traj = dict( + obs=[], + next_obs=[], + rewards=[], + dones=[], + actions=np.array(actions), + # actions_abs=[], + states=np.array(states), + initial_state_dict=initial_state, + datagen_info=[], + ) + traj_len = states.shape[0] + # iteration variable @t is over "next obs" indices + for t in range(traj_len): + obs = deepcopy(env.reset_to({"states": states[t]})) + + # extract datagen info + if add_datagen_info: + datagen_info = env.base_env.get_datagen_info(action=actions[t]) + else: + datagen_info = {} + + # infer reward signal + # note: our tasks use reward r(s'), reward AFTER transition, so this is + # the reward for the current timestep + r = env.get_reward() + + # infer done signal + done = False + if (done_mode == 1) or (done_mode == 2): + # done = 1 at end of trajectory + done = done or (t == traj_len) + if (done_mode == 0) or (done_mode == 2): + # done = 1 when s' is task success state + done = done or env.is_success()["task"] + done = int(done) + + # get the absolute action + # action_abs = env.base_env.convert_rel_to_abs_action(actions[t]) + + # collect transition + traj["obs"].append(obs) + traj["rewards"].append(r) + traj["dones"].append(done) + traj["datagen_info"].append(datagen_info) + # traj["actions_abs"].append(action_abs) + + # convert list of dict to dict of list for obs dictionaries (for convenient writes to hdf5 dataset) + traj["obs"] = TensorUtils.list_of_flat_dict_to_dict_of_list(traj["obs"]) + traj["datagen_info"] = TensorUtils.list_of_flat_dict_to_dict_of_list( + traj["datagen_info"] + ) + + # list to numpy array + for k in traj: + if k == "initial_state_dict": + continue + if isinstance(traj[k], dict): + for kp in traj[k]: + traj[k][kp] = np.array(traj[k][kp]) + else: + traj[k] = np.array(traj[k]) + + return traj + + +""" The process that writes over the generated files to memory """ + + +def write_traj_to_file( + args, output_path, total_samples, total_run, processes, mul_queue +): + f = h5py.File(args.dataset, "r") + f_out = h5py.File(output_path, "w") + data_grp = f_out.create_group("data") + start_time = time.time() + num_processed = 0 + + try: + while (total_run.value < (processes)) or not mul_queue.empty(): + if not mul_queue.empty(): + num_processed = num_processed + 1 + item = mul_queue.get() + ep = item[0] + traj = item[1] + process_num = item[2] + try: + ep_data_grp = data_grp.create_group(ep) + ep_data_grp.create_dataset( + "actions", data=np.array(traj["actions"]) + ) + ep_data_grp.create_dataset("states", data=np.array(traj["states"])) + ep_data_grp.create_dataset( + "rewards", data=np.array(traj["rewards"]) + ) + ep_data_grp.create_dataset("dones", data=np.array(traj["dones"])) + # ep_data_grp.create_dataset( + # "actions_abs", data=np.array(traj["actions_abs"]) + # ) + for k in traj["obs"]: + if args.no_compress: + ep_data_grp.create_dataset( + "obs/{}".format(k), data=np.array(traj["obs"][k]) + ) + else: + ep_data_grp.create_dataset( + "obs/{}".format(k), + data=np.array(traj["obs"][k]), + compression="gzip", + ) + if args.include_next_obs: + if args.no_compress: + ep_data_grp.create_dataset( + "next_obs/{}".format(k), + data=np.array(traj["next_obs"][k]), + ) + else: + ep_data_grp.create_dataset( + "next_obs/{}".format(k), + data=np.array(traj["next_obs"][k]), + compression="gzip", + ) + + if "datagen_info" in traj: + for k in traj["datagen_info"]: + ep_data_grp.create_dataset( + "datagen_info/{}".format(k), + data=np.array(traj["datagen_info"][k]), + ) + + # copy action dict (if applicable) + if "data/{}/action_dict".format(ep) in f: + action_dict = f["data/{}/action_dict".format(ep)] + for k in action_dict: + ep_data_grp.create_dataset( + "action_dict/{}".format(k), + data=np.array(action_dict[k][()]), + ) + + # episode metadata + ep_data_grp.attrs["model_file"] = traj["initial_state_dict"][ + "model" + ] # model xml for this episode + ep_data_grp.attrs["ep_meta"] = traj["initial_state_dict"][ + "ep_meta" + ] # ep meta data for this episode + # if "ep_meta" in f["data/{}".format(ep)].attrs: + # ep_data_grp.attrs["ep_meta"] = f["data/{}".format(ep)].attrs["ep_meta"] + ep_data_grp.attrs["num_samples"] = traj["actions"].shape[ + 0 + ] # number of transitions in this episode + + total_samples.value += traj["actions"].shape[0] + except Exception as e: + print("++" * 50) + print( + f"Error at Process {process_num} on episode {ep} with \n\n {e}" + ) + print("++" * 50) + raise Exception("Write out to file has failed") + print( + "ep {}: wrote {} transitions to group {} at process {} with {} finished. Datagen rate: {:.2f} sec/demo".format( + num_processed, + ep_data_grp.attrs["num_samples"], + ep, + process_num, + total_run.value, + (time.time() - start_time) / num_processed, + ) + ) + except KeyboardInterrupt: + print("Control C pressed. Closing File and ending \n\n\n\n\n\n\n") + + if "mask" in f: + f.copy("mask", f_out) + + # global metadata + data_grp.attrs["total"] = total_samples.value + env_meta = DatasetUtils.get_env_metadata_from_dataset(dataset_path=args.dataset) + if args.generative_textures: + env_meta["env_kwargs"]["generative_textures"] = "100p" + if args.randomize_cameras: + env_meta["env_kwargs"]["randomize_cameras"] = True + env = EnvUtils.create_env_for_data_processing( + env_meta=env_meta, + camera_names=args.camera_names, + camera_height=args.camera_height, + camera_width=args.camera_width, + reward_shaping=args.shaped, + ) + print("total processes end {}".format(total_run.value)) + data_grp.attrs["env_args"] = json.dumps( + env.serialize(), indent=4 + ) # environment info + print("Wrote {} total samples to {}".format(total_samples.value, output_path)) + + f_out.close() + f.close() + + DatasetUtils.extract_action_dict(dataset=output_path) + DatasetUtils.make_demo_ids_contiguous(dataset=output_path) + for num_demos in [ + 10, + 20, + 30, + 40, + 50, + 60, + 70, + 75, + 80, + 90, + 100, + 125, + 150, + 200, + 250, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, + 1500, + 2000, + 2500, + 3000, + 4000, + 5000, + 10000, + ]: + DatasetUtils.filter_dataset_size( + output_path, + num_demos=num_demos, + ) + + print("Writing has finished") + + end_time = time.time() + + # Calculate the elapsed time + elapsed_time = end_time - start_time + + print(f"Time elapsed: {elapsed_time:.2f} seconds") + return + + +# runs multiple trajectory. If there has been an unrecoverable error, the system puts the current work back into the queue and exits +def extract_multiple_trajectories( + process_num, current_work_array, work_queue, lock, args2, num_finished, mul_queue +): + try: + extract_multiple_trajectories_with_error( + process_num, current_work_array, work_queue, lock, args2, mul_queue + ) + except Exception as e: + work_queue.put(current_work_array[process_num]) + print("*>*" * 50) + print("Error process num {}:".format(process_num)) + print(e) + print(traceback.format_exc()) + print("*>*" * 50) + print() + + num_finished.value = num_finished.value + 1 + + +def retrieve_new_index(process_num, current_work_array, work_queue, lock): + with lock: + if work_queue.empty(): + return -1 + try: + tmp = work_queue.get(False) + current_work_array[process_num] = tmp + return tmp + except queue.Empty: + return -1 + + +def extract_multiple_trajectories_with_error( + process_num, current_work_array, work_queue, lock, args, mul_queue +): + # create environment to use for data processing + + if args.add_datagen_info: + import mimicgen.utils.file_utils as MG_FileUtils + + env_meta = MG_FileUtils.get_env_metadata_from_dataset(dataset_path=args.dataset) + else: + env_meta = DatasetUtils.get_env_metadata_from_dataset(dataset_path=args.dataset) + if args.generative_textures: + env_meta["env_kwargs"]["generative_textures"] = "100p" + if args.randomize_cameras: + env_meta["env_kwargs"]["randomize_cameras"] = True + env = EnvUtils.create_env_for_data_processing( + env_meta=env_meta, + camera_names=args.camera_names, + camera_height=args.camera_height, + camera_width=args.camera_width, + reward_shaping=args.shaped, + ) + + start_time = time.time() + + print("==== Using environment with the following metadata ====") + print(json.dumps(env.serialize(), indent=4)) + print("") + + # list of all demonstration episodes (sorted in increasing number order) + f = h5py.File(args.dataset, "r") + if args.filter_key is not None: + print("using filter key: {}".format(args.filter_key)) + demos = [ + elem.decode("utf-8") + for elem in np.array(f["mask/{}".format(args.filter_key)]) + ] + else: + demos = list(f["data"].keys()) + inds = np.argsort([int(elem[5:]) for elem in demos]) + demos = [demos[i] for i in inds] + + # maybe reduce the number of demonstrations to playback + if args.n is not None: + demos = demos[: args.n] + + ind = retrieve_new_index(process_num, current_work_array, work_queue, lock) + while (not work_queue.empty()) and (ind != -1): + try: + # print("Running {} index".format(ind)) + ep = demos[ind] + + # prepare initial state to reload from + states = f["data/{}/states".format(ep)][()] + initial_state = dict(states=states[0]) + initial_state["model"] = f["data/{}".format(ep)].attrs["model_file"] + initial_state["ep_meta"] = f["data/{}".format(ep)].attrs.get( + "ep_meta", None + ) + + # extract obs, rewards, dones + actions = f["data/{}/actions".format(ep)][()] + + traj = extract_trajectory( + env=env, + initial_state=initial_state, + states=states, + actions=actions, + done_mode=args.done_mode, + add_datagen_info=args.add_datagen_info, + ) + + # maybe copy reward or done signal from source file + if args.copy_rewards: + traj["rewards"] = f["data/{}/rewards".format(ep)][()] + if args.copy_dones: + traj["dones"] = f["data/{}/dones".format(ep)][()] + + ep_grp = f["data/{}".format(ep)] + + states = ep_grp["states"][()] + initial_state = dict(states=states[0]) + initial_state["model"] = ep_grp.attrs["model_file"] + initial_state["ep_meta"] = ep_grp.attrs.get("ep_meta", None) + + # store transitions + + # IMPORTANT: keep name of group the same as source file, to make sure that filter keys are + # consistent as well + # print("(process {}): ADD TO QUEUE index {}".format(process_num, ind)) + mul_queue.put([ep, traj, process_num]) + + ind = retrieve_new_index(process_num, current_work_array, work_queue, lock) + except Exception as e: + print("_" * 50) + print("Process {}:".format(process_num)) + print("Error processing demo index {}: {}".format(ind, e)) + print(traceback.format_exc()) + print("_" * 50) + del env + env = EnvUtils.create_env_for_data_processing( # when it errors, it like blows up the environment for some reason + env_meta=env_meta, + camera_names=args.camera_names, + camera_height=args.camera_height, + camera_width=args.camera_width, + reward_shaping=args.shaped, + ) + + f.close() + print("Process {} finished".format(process_num)) + + +def dataset_states_to_obs_multiprocessing(args): + # create environment to use for data processing + + # output file in same directory as input file + output_name = args.output_name + if output_name is None: + if len(args.camera_names) == 0: + output_name = os.path.basename(args.dataset)[:-5] + "_ld.hdf5" + else: + image_suffix = str(args.camera_width) + image_suffix = ( + image_suffix + "_randcams" if args.randomize_cameras else image_suffix + ) + if args.generative_textures: + output_name = os.path.basename(args.dataset)[ + :-5 + ] + "_gentex_im{}.hdf5".format(image_suffix) + else: + output_name = os.path.basename(args.dataset)[:-5] + "_im{}.hdf5".format( + image_suffix + ) + + output_path = os.path.join(os.path.dirname(args.dataset), output_name) + + print("input file: {}".format(args.dataset)) + print("output file: {}".format(output_path)) + + f = h5py.File(args.dataset, "r") + if args.filter_key is not None: + print("using filter key: {}".format(args.filter_key)) + demos = [ + elem.decode("utf-8") + for elem in np.array(f["mask/{}".format(args.filter_key)]) + ] + else: + demos = list(f["data"].keys()) + inds = np.argsort([int(elem[5:]) for elem in demos]) + demos = [demos[i] for i in inds] + + if args.n is not None: + demos = demos[: args.n] + + num_demos = len(demos) + f.close() + + env_meta = DatasetUtils.get_env_metadata_from_dataset(dataset_path=args.dataset) + num_processes = args.num_procs + + index = multiprocessing.Value("i", 0) + lock = multiprocessing.Lock() + total_samples_shared = multiprocessing.Value("i", 0) + num_finished = multiprocessing.Value("i", 0) + mul_queue = multiprocessing.Queue() + work_queue = multiprocessing.Queue() + for index in range(num_demos): + work_queue.put(index) + current_work_array = multiprocessing.Array("i", num_processes) + processes = [] + for i in range(num_processes): + process = multiprocessing.Process( + target=extract_multiple_trajectories, + args=( + i, + current_work_array, + work_queue, + lock, + args, + num_finished, + mul_queue, + ), + ) + processes.append(process) + + process1 = multiprocessing.Process( + target=write_traj_to_file, + args=( + args, + output_path, + total_samples_shared, + num_finished, + num_processes, + mul_queue, + ), + ) + processes.append(process1) + + for process in processes: + process.start() + + for process in processes: + process.join() + + print("Finished Multiprocessing") + return + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--dataset", + type=str, + required=True, + help="path to input hdf5 dataset", + ) + # name of hdf5 to write - it will be in the same directory as @dataset + parser.add_argument( + "--output_name", + type=str, + help="name of output hdf5 dataset", + ) + + parser.add_argument( + "--filter_key", + type=str, + help="filter key for input dataset", + ) + + # specify number of demos to process - useful for debugging conversion with a handful + # of trajectories + parser.add_argument( + "--n", + type=int, + default=None, + help="(optional) stop after n trajectories are processed", + ) + + # flag for reward shaping + parser.add_argument( + "--shaped", + action="store_true", + help="(optional) use shaped rewards", + ) + + # camera names to use for observations + parser.add_argument( + "--camera_names", + type=str, + nargs="+", + default=[ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ], + help="(optional) camera name(s) to use for image observations. Leave out to not use image observations.", + ) + + parser.add_argument( + "--camera_height", + type=int, + default=128, + help="(optional) height of image observations", + ) + + parser.add_argument( + "--camera_width", + type=int, + default=128, + help="(optional) width of image observations", + ) + + # specifies how the "done" signal is written. If "0", then the "done" signal is 1 wherever + # the transition (s, a, s') has s' in a task completion state. If "1", the "done" signal + # is one at the end of every trajectory. If "2", the "done" signal is 1 at task completion + # states for successful trajectories and 1 at the end of all trajectories. + parser.add_argument( + "--done_mode", + type=int, + default=0, + help="how to write done signal. If 0, done is 1 whenever s' is a success state.\ + If 1, done is 1 at the end of each trajectory. If 2, both.", + ) + + # flag for copying rewards from source file instead of re-writing them + parser.add_argument( + "--copy_rewards", + action="store_true", + help="(optional) copy rewards from source file instead of inferring them", + ) + + # flag for copying dones from source file instead of re-writing them + parser.add_argument( + "--copy_dones", + action="store_true", + help="(optional) copy dones from source file instead of inferring them", + ) + + # flag to include next obs in dataset + parser.add_argument( + "--include-next-obs", + action="store_true", + help="(optional) include next obs in dataset", + ) + + # flag to disable compressing observations with gzip option in hdf5 + parser.add_argument( + "--no_compress", + action="store_true", + help="(optional) disable compressing observations with gzip option in hdf5", + ) + + parser.add_argument( + "--num_procs", + type=int, + default=5, + help="number of parallel processes for extracting image obs", + ) + + parser.add_argument( + "--add_datagen_info", + action="store_true", + help="(optional) add datagen info (used for mimicgen)", + ) + + parser.add_argument("--generative_textures", action="store_true") + + parser.add_argument("--randomize_cameras", action="store_true") + + args = parser.parse_args() + dataset_states_to_obs_multiprocessing(args) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/download_datasets.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/download_datasets.py new file mode 100644 index 0000000000000000000000000000000000000000..c727dfd2bc932509a737368b7c4088dcfb6a565a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/download_datasets.py @@ -0,0 +1,104 @@ +import argparse +import os +from pathlib import Path + +from termcolor import colored + +import robocasa +from robocasa.scripts.download_kitchen_assets import download_url +from robocasa.utils.dataset_registry import ( + MULTI_STAGE_TASK_DATASETS, + SINGLE_STAGE_TASK_DATASETS, + get_ds_path, +) + + +def download_datasets(tasks, ds_types, overwrite=False, dryrun=False): + if tasks is None: + tasks = list(SINGLE_STAGE_TASK_DATASETS.keys()) + list( + MULTI_STAGE_TASK_DATASETS.keys() + ) + + for task_name in tasks: + for ds_type in ds_types: + print(colored(f"Task: {task_name}\nDataset type: {ds_type}", "yellow")) + + ds_path, ds_info = get_ds_path(task_name, ds_type, return_info=True) + if ds_path is None: + print( + colored( + f"No dataset for this task and dataset type exists!\nSkipping.\n", + "yellow", + ) + ) + continue + ds_dir = "/".join(ds_path.split("/")[0:-1]) + fname = ds_path.split("/")[-1] + + Path(ds_dir).mkdir(parents=True, exist_ok=True) + + if overwrite is False and os.path.exists(ds_path): + print( + colored( + f"Dataset already exists under {ds_path}\nSkipping.\n", "yellow" + ) + ) + continue + + if not dryrun: + download_url( + url=ds_info["url"], + download_dir=ds_dir, + fname=fname, + check_overwrite=(overwrite is False), + ) + print() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + + parser.add_argument( + "--tasks", + type=str, + nargs="+", + default=None, + help="Tasks to download datasets for. Defaults to all tasks", + ) + + parser.add_argument( + "--ds_types", + type=str, + nargs="+", + default=["human_raw", "human_im"], + choices=["human_raw", "human_im", "mg_im"], + help="Dataset types. Choose one or multiple options among human_raw, human_im, mg_im", + ) + + parser.add_argument( + "--overwrite", + action="store_true", + help="automatically overwrite any existing files", + ) + + parser.add_argument( + "--dryrun", + action="store_true", + help="simulate without downloading datasets", + ) + + args = parser.parse_args() + + ans = input("This script may download several Gb of data. Proceed? (y/n) ") + if ans == "y": + print("Proceeding...") + else: + print("Aborting.") + exit() + + download_datasets( + tasks=args.tasks, + ds_types=args.ds_types, + overwrite=args.overwrite, + dryrun=args.dryrun, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/download_kitchen_assets.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/download_kitchen_assets.py new file mode 100644 index 0000000000000000000000000000000000000000..1cc412d9999c6b63a9eb1d88a185f759c0dca743 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/download_kitchen_assets.py @@ -0,0 +1,200 @@ +import os +import time +import urllib.request +from pathlib import Path +from zipfile import ZipFile + +from termcolor import colored +from tqdm import tqdm + +import robocasa + +DOWNLOAD_ASSET_REGISTRY = dict( + textures=dict( + message="Downloading environment textures", + url="https://utexas.box.com/shared/static/otdsyfjontk17jdp24bkhy2hgalofbh4.zip", + folder=os.path.join(robocasa.__path__[0], "models/assets/textures"), + check_folder_exists=False, + ), + fixtures=dict( + message="Downloading fixtures", + url="https://utexas.box.com/shared/static/pobhbsjyacahg2mx8x4rm5fkz3wlmyzp.zip", + folder=os.path.join(robocasa.__path__[0], "models/assets/fixtures"), + check_folder_exists=False, + ), + objaverse=dict( + message="Downloading objaverse objects", + url="https://utexas.box.com/shared/static/ejt1kc2v5vhae1rl4k5697i4xvpbjcox.zip", + folder=os.path.join(robocasa.__path__[0], "models/assets/objects/objaverse"), + check_folder_exists=False, + ), + aigen_objs=dict( + message="Downloading AI-generated objects", + url="https://utexas.box.com/shared/static/os3hrui06lasnuvwqpmwn0wcrduh6jg3.zip", + folder=os.path.join(robocasa.__path__[0], "models/assets/objects/aigen_objs"), + check_folder_exists=False, + ), + generative_textures=dict( + message="Downloading AI-generated environment textures", + url="https://utexas.box.com/shared/static/gf9nkadvfrowkb9lmkcx58jwt4d6c1g3.zip", + folder=os.path.join(robocasa.__path__[0], "models/assets/generative_textures"), + check_folder_exists=False, + ), +) + + +class DownloadProgressBar(tqdm): + def update_to(self, b=1, bsize=1, tsize=None): + if tsize is not None: + self.total = tsize + self.update(b * bsize - self.n) + + +def url_is_alive(url): + """ + Checks that a given URL is reachable. + From https://gist.github.com/dehowell/884204. + + Args: + url (str): url string + + Returns: + is_alive (bool): True if url is reachable, False otherwise + """ + request = urllib.request.Request(url) + request.get_method = lambda: "HEAD" + + try: + urllib.request.urlopen(request) + return True + except urllib.request.HTTPError: + return False + + +def download_url(url, download_dir, fname=None, check_overwrite=True): + """ + First checks that @url is reachable, then downloads the file + at that url into the directory specified by @download_dir. + Prints a progress bar during the download using tqdm. + + Modified from https://github.com/tqdm/tqdm#hooks-and-callbacks, and + https://stackoverflow.com/a/53877507. + + Args: + url (str): url string + download_dir (str): path to directory where file should be downloaded + check_overwrite (bool): if True, will sanity check the download fpath to make sure a file of that name + doesn't already exist there + """ + + # check if url is reachable. We need the sleep to make sure server doesn't reject subsequent requests + # assert url_is_alive(url), "@download_url got unreachable url: {}".format(url) + # time.sleep(0.5) + + if fname is None: + # infer filename from url link + fname = url.split("/")[-1] + file_to_write = os.path.join(download_dir, fname) + + # If we're checking overwrite and the path already exists, + # we ask the user to verify that they want to overwrite the file + if check_overwrite and os.path.exists(file_to_write): + user_response = input( + f"Warning: file {file_to_write} already exists. Overwrite? y/n " + ) + assert user_response.lower() in { + "yes", + "y", + }, f"Did not receive confirmation. Aborting download." + + print(colored(f"Downloading to {file_to_write}", "yellow")) + + with DownloadProgressBar(unit="B", unit_scale=True, miniters=1, desc=fname) as t: + urllib.request.urlretrieve(url, filename=file_to_write, reporthook=t.update_to) + + +def download_and_extract_zip( + url, + folder, + check_folder_exists=True, + prompt_before_download=False, + message="Downloading...", +): + assert url.endswith(".zip") + + download_dir = os.path.abspath(os.path.join(folder, os.pardir)) + Path(download_dir).mkdir(parents=True, exist_ok=True) + + download_path = os.path.join( + download_dir, "{}.zip".format(os.path.basename(folder)) + ) + + print(colored(message, "yellow")) + + # extract files + if check_folder_exists and os.path.exists(folder): + ans = input("{} already exists! \noverwrite? (y/n) ".format(folder)) + + if ans == "y": + print(colored("Proceeding.", "yellow")) + else: + print(colored("Skipping.\n", "yellow")) + return + + if prompt_before_download: + ans = input( + "Assets to be downloaded may be a few Gb. Proceed? (y/n) ".format(folder) + ) + + if ans == "y": + print(colored("Proceeding.", "yellow")) + else: + print(colored("Skipping.\n", "yellow")) + return + + download_success = False + for i in range(3): + try: + download_url( + url=url, + download_dir=download_dir, + fname=os.path.basename(download_path), + check_overwrite=False, + ) + download_success = True + break + except: + print("Error downloading after try #{}".format(i + 1)) + + if download_success is False: + print("Failed to download. Try again...") + return + + print(colored("Extracting...", "yellow")) + with ZipFile(download_path, "r") as zip_ref: + # Extracting all the members of the zip + # into a specific location. + zip_ref.extractall(path=download_dir) + + # delete zip file + os.remove(download_path) + + print(colored("Done.\n", "yellow")) + + +def download_kitchen_assets(): + ans = input("The script will download ~5 Gb of data. Proceed? (y/n) ") + if ans == "y": + print("Proceeding...") + else: + print("Aborting.") + return + + for ds_name, config in DOWNLOAD_ASSET_REGISTRY.items(): + if ds_name == "aigen_objs": + continue # skip for now, too large to download initially + download_and_extract_zip(**config) + + +if __name__ == "__main__": + download_kitchen_assets() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/filter_dataset_size.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/filter_dataset_size.py new file mode 100644 index 0000000000000000000000000000000000000000..ddf4d2c0f1eeb20c16756c10c36f9c62880dc689 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/filter_dataset_size.py @@ -0,0 +1,75 @@ +import argparse +import h5py +import numpy as np + +import robocasa.utils.robomimic.robomimic_dataset_utils as DatasetUtils + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--dataset", + type=str, + required=True, + help="path to hdf5 dataset", + ) + parser.add_argument( + "--input_filter_key", + type=str, + default=None, + help="if provided, split the subset of trajectories in the file that correspond to\ + this filter key into a training and validation set of trajectories, instead of\ + splitting the full set of trajectories", + ) + parser.add_argument( + "--num_demos", + type=int, + nargs="+", + default=[ + 10, + 20, + 30, + 40, + 50, + 60, + 70, + 75, + 80, + 90, + 100, + 125, + 150, + 200, + 250, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, + 1500, + 2000, + 2500, + ] + + [n * 1000 for n in range(3, 21)], + ) + parser.add_argument( + "--output_filter_key", + type=str, + required=False, + help="(optional) use custom name for output filter key name", + ) + args = parser.parse_args() + + # seed to make sure results are consistent + np.random.seed(0) + + for n in args.num_demos: + DatasetUtils.filter_dataset_size( + args.dataset, + input_filter_key=args.input_filter_key, + num_demos=n, + output_filter_key=args.output_filter_key, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/generate_usd_trajectories.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/generate_usd_trajectories.py new file mode 100644 index 0000000000000000000000000000000000000000..0d1e47eb1787b406172fc3481fca8727f386af5c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/generate_usd_trajectories.py @@ -0,0 +1,263 @@ +import argparse +import json +import os +import random +from pathlib import Path + +import h5py +import imageio +import mujoco +import numpy as np +import robomimic +import robomimic.utils.env_utils as EnvUtils +import robomimic.utils.file_utils as FileUtils +import robomimic.utils.obs_utils as ObsUtils +from robomimic.envs.env_base import EnvBase, EnvType +from tqdm import tqdm + +from robocasa.utils.usd.exporter import USDExporter + +front_camera_pos = { + 0: (2.25, -5.74, 1.75), + 1: (2.65, -6.17, 1.9), + 2: (0.03418, -5.66508, 2.46522), + 3: (6.415, -5.16, 2.58), + 4: (1.6, -7, 1.749), + 5: (2.077, -6.369, 1.922), + 6: (3.2, -7.56, 2.3), + 7: (2.2, -7.613, 1.91), + 8: (2.248, -7.643, 1.81), + 9: (4.212, -6.63, 2), +} + +front_camera_angle = { + 0: (84.09, 0, 0), + 1: (80.24, 0, 0), + 2: (72.10401, 0, -41.11511), + 3: (73.23, 0, 58.19), + 4: (79, 0, 0), + 5: (79.755, 0, 0.103), + 6: (76.93, 0, 0.786), + 7: (78.139, 0, 0), + 8: (79.98, 0, 0), + 9: (76.754, 0, 0), +} + +# os.environ["KMP_DUPLICATE_LIB_OK"] = "True" + +# Define default cameras to use for each env type +DEFAULT_CAMERAS = { + EnvType.ROBOSUITE_TYPE: ["agentview"], + EnvType.IG_MOMART_TYPE: ["rgb"], + EnvType.GYM_TYPE: ValueError("No camera names supported for gym type env!"), +} + + +def playback_trajectory_with_env( + demo_name, + env, + initial_state, + states, + save_dir, + actions=None, + camera_names=None, + first=False, + ep_name="tmp", +): + """ + Helper function to playback a single trajectory using the simulator environment. + If @actions are not None, it will play them open-loop after loading the initial state. + Otherwise, @states are loaded one by one. + + Args: + env (instance of EnvBase): environment + initial_state (dict): initial simulation state to load + states (np.array): array of simulation states to load + actions (np.array): if provided, play actions back open-loop instead of using @states + camera_names (list): determines which camera(s) are used for rendering. Pass more than + one to output a video with multiple camera views concatenated horizontally. + first (bool): if True, only use the first frame of each episode. + """ + + print(f"playing demonstration {demo_name}...") + + ep_meta = json.loads(initial_state["ep_meta"]) + layout_id = int(ep_meta["layout_id"]) + + assert isinstance(env, EnvBase) + + env.reset_to(initial_state) + + model = env.env.sim.model._model + data = env.env.sim.data._data + + renderer = USDExporter( + model, + light_intensity=100000, + camera_names=[ + "robot0_eye_in_hand", + "robot0_agentview_left", + "robot0_agentview_right", + ], + output_directory_name=f"{ep_name}", + output_directory_root=save_dir, + ) + + traj_len = states.shape[0] + action_playback = actions is not None + if action_playback: + assert states.shape[0] == actions.shape[0] + + for i in tqdm(range(traj_len)): + + env.reset_to({"states": states[i]}) + + scene_option = mujoco.MjvOption() + scene_option.geomgroup = [0, 1, 1, 0, 0, 0] + + renderer.update_scene(data, scene_option=scene_option) + + renderer.add_camera( + list(front_camera_pos[layout_id]), list(front_camera_angle[layout_id]), objid=1 + ) + + renderer.add_light( + pos=[0.0, 0.0, 0.0], intensity=4000, objid="dome_light", light_type="dome" + ) + + renderer.save_scene(filetype="usd") + + +def playback_dataset(dataset, args): + save_dir = dataset.split(".hdf5")[0] + "_usd" + + # Auto-fill camera rendering info if not specified + if args.render_image_names is None: + # We fill in the automatic values + env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path=dataset) + env_type = EnvUtils.get_env_type(env_meta=env_meta) + args.render_image_names = DEFAULT_CAMERAS[env_type] + + # need to make sure ObsUtils knows which observations are images, but it doesn't matter + # for playback since observations are unused. Pass a dummy spec here. + dummy_spec = dict( + obs=dict( + low_dim=["robot0_eef_pos"], + rgb=[], + ), + ) + ObsUtils.initialize_obs_utils_with_obs_specs(obs_modality_specs=dummy_spec) + + env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path=dataset) + # env_meta["env_kwargs"]["controller_configs"]["control_delta"] = False # absolute action space + env = EnvUtils.create_env_from_metadata( + env_meta=env_meta, render=False, render_offscreen=False + ) + + # some operations for playback are robosuite-specific, so determine if this environment is a robosuite env + is_robosuite_env = EnvUtils.is_robosuite_env(env_meta) + + f = h5py.File(dataset, "r") + + # list of all demonstration episodes (sorted in increasing number order) + if args.filter_key is not None: + print("using filter key: {}".format(args.filter_key)) + demos = [ + elem.decode("utf-8") + for elem in np.array(f["mask/{}".format(args.filter_key)]) + ] + else: + demos = list(f["data"].keys()) + inds = np.argsort([int(elem[5:]) for elem in demos]) + demos = [demos[i] for i in inds] + + if args.demo_key is not None: + demos = [demo_key] + + for ind in range(len(demos)): + ep = demos[ind] + print("Playing back episode: {}".format(ep)) + + # prepare initial state to reload from + states = f["data/{}/states".format(ep)][()] + initial_state = dict(states=states[0]) + if is_robosuite_env: + initial_state["model"] = f["data/{}".format(ep)].attrs["model_file"] + initial_state["ep_meta"] = f["data/{}".format(ep)].attrs.get( + "ep_meta", None + ) + + # supply actions if using open-loop action playback + actions = None + if args.use_actions: + actions = f["data/{}/actions".format(ep)][()] + + playback_trajectory_with_env( + demo_name=Path(dataset).stem, + env=env, + initial_state=initial_state, + states=states, + actions=actions, + camera_names=args.render_image_names, + first=args.first, + save_dir=save_dir, + ep_name=ep, + ) + + f.close() + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + + parser.add_argument("--dataset", type=str, help="the hdf5 dataset") + + parser.add_argument( + "--filter_key", + type=str, + default=None, + help="(optional) filter key, to select a subset of trajectories in the file", + ) + + parser.add_argument( + "--demo_key", type=int, default=None, help="(optional) a single demo to convert" + ) + + # Use image observations instead of doing playback using the simulator env. + parser.add_argument( + "--use-obs", + action="store_true", + help="visualize trajectories with dataset image observations instead of simulator", + ) + + # Playback stored dataset actions open-loop instead of loading from simulation states. + parser.add_argument( + "--use-actions", + action="store_true", + help="use open-loop action playback instead of loading sim states", + ) + + # camera names to render, or image observations to use for writing to video + parser.add_argument( + "--render_image_names", + type=str, + nargs="+", + default=[ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ], + help="(optional) camera name(s) / image observation(s) to use for rendering on-screen or to video. Default is" + "None, which corresponds to a predefined camera for each env type", + ) + + # Only use the first frame of each episode + parser.add_argument( + "--first", + action="store_true", + help="use first frame of each episode", + ) + + args = parser.parse_args() + + playback_dataset(args.dataset, args) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/get_dataset_info.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/get_dataset_info.py new file mode 100644 index 0000000000000000000000000000000000000000..16be19e57d2f0a75efa357e948d88a169b082f44 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/get_dataset_info.py @@ -0,0 +1,186 @@ +""" +Helper script to report dataset information. By default, will print trajectory length statistics, +the maximum and minimum action element in the dataset, filter keys present, environment +metadata, and the structure of the first demonstration. If --verbose is passed, it will +report the exact demo keys under each filter key, and the structure of all demonstrations +(not just the first one). + +Args: + dataset (str): path to hdf5 dataset + + filter_key (str): if provided, report statistics on the subset of trajectories + in the file that correspond to this filter key + + verbose (bool): if flag is provided, print more details, like the structure of all + demonstrations (not just the first one) + +Example usage: + + # run script on example hdf5 packaged with repository + python get_dataset_info.py --dataset ../../tests/assets/test.hdf5 + + # run script only on validation data + python get_dataset_info.py --dataset ../../tests/assets/test.hdf5 --filter_key valid +""" +import h5py +import json +import argparse +import numpy as np + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--dataset", + type=str, + help="path to hdf5 dataset", + ) + parser.add_argument( + "--filter_key", + type=str, + default=None, + help="(optional) if provided, report statistics on the subset of trajectories \ + in the file that correspond to this filter key", + ) + parser.add_argument( + "--verbose", + action="store_true", + help="verbose output", + ) + args = parser.parse_args() + + # extract demonstration list from file + filter_key = args.filter_key + all_filter_keys = None + f = h5py.File(args.dataset, "r") + if filter_key is not None: + # use the demonstrations from the filter key instead + print("NOTE: using filter key {}".format(filter_key)) + demos = sorted( + [elem.decode("utf-8") for elem in np.array(f["mask/{}".format(filter_key)])] + ) + else: + # use all demonstrations + demos = sorted(list(f["data"].keys())) + + # extract filter key information + if "mask" in f: + all_filter_keys = {} + for fk in f["mask"]: + fk_demos = sorted( + [elem.decode("utf-8") for elem in np.array(f["mask/{}".format(fk)])] + ) + all_filter_keys[fk] = fk_demos + + # put demonstration list in increasing episode order + inds = np.argsort([int(elem[5:]) for elem in demos]) + demos = [demos[i] for i in inds] + + # extract length of each trajectory in the file + traj_lengths = [] + action_min = np.inf + action_max = -np.inf + for ep in demos: + traj_lengths.append(f["data/{}/actions".format(ep)].shape[0]) + action_min = min(action_min, np.min(f["data/{}/actions".format(ep)][()])) + action_max = max(action_max, np.max(f["data/{}/actions".format(ep)][()])) + traj_lengths = np.array(traj_lengths) + + # report statistics on the data + print("") + print("total transitions: {}".format(np.sum(traj_lengths))) + print("total trajectories: {}".format(traj_lengths.shape[0])) + print("traj length mean: {}".format(np.mean(traj_lengths))) + print("traj length std: {}".format(np.std(traj_lengths))) + print("traj length min: {}".format(np.min(traj_lengths))) + print("traj length max: {}".format(np.max(traj_lengths))) + print("action min: {}".format(action_min)) + print("action max: {}".format(action_max)) + print("") + print("==== Filter Keys ====") + if all_filter_keys is not None: + for fk in all_filter_keys: + print("filter key {} with {} demos".format(fk, len(all_filter_keys[fk]))) + else: + print("no filter keys") + print("") + if args.verbose: + if all_filter_keys is not None: + print("==== Filter Key Contents ====") + for fk in all_filter_keys: + print( + "filter_key {} with {} demos: {}".format( + fk, len(all_filter_keys[fk]), all_filter_keys[fk] + ) + ) + print("") + env_meta = json.loads(f["data"].attrs["env_args"]) + print("==== Env Meta ====") + print(json.dumps(env_meta, indent=4)) + print("") + + print("==== Dataset Structure ====") + for ep in demos: + print( + "episode {} with {} transitions".format( + ep, f["data/{}".format(ep)].attrs["num_samples"] + ) + ) + for k in f["data/{}".format(ep)]: + if k in ["obs", "next_obs"]: + print(" key: {}".format(k)) + for obs_k in f["data/{}/{}".format(ep, k)]: + shape = f["data/{}/{}/{}".format(ep, k, obs_k)].shape + print( + " observation key {} with shape {}".format(obs_k, shape) + ) + elif isinstance(f["data/{}/{}".format(ep, k)], h5py.Dataset): + key_shape = f["data/{}/{}".format(ep, k)].shape + print(" key: {} with shape {}".format(k, key_shape)) + + if not args.verbose: + break + + obj_cat_counts = {} + layout_counts = {} + style_counts = {} + langs = [] + for ep in demos: + ep_meta = json.loads(f["data/{}".format(ep)].attrs["ep_meta"]) + langs.append(ep_meta["lang"]) + obj_cfgs = ep_meta["object_cfgs"] + cat = None + for cfg in obj_cfgs: + if cfg["name"] == "obj": + cat = cfg["info"]["cat"] + break + if cat not in obj_cat_counts: + obj_cat_counts[cat] = 0 + obj_cat_counts[cat] += 1 + + layout_id = ep_meta["layout_id"] + style_id = ep_meta["style_id"] + if layout_id not in layout_counts: + layout_counts[layout_id] = 0 + if style_id not in style_counts: + style_counts[style_id] = 0 + layout_counts[layout_id] += 1 + style_counts[style_id] += 1 + + # for k, v in obj_cat_counts.items(): + # print(k, v) + print() + print("obj cat counts:", obj_cat_counts) + print("layout_counts:", layout_counts) + print("style_counts:", style_counts) + print("num unique lang instructions:", len(set(langs))) + + f.close() + + # maybe display error message + print("") + if (action_min < -1.0) or (action_max > 1.0): + raise Exception( + "Dataset should have actions in [-1., 1.] but got bounds [{}, {}]".format( + action_min, action_max + ) + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/README.md b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..2ac7b01f50b6bd54c651feb9c9d3f61db8571437 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/README.md @@ -0,0 +1,76 @@ +# RoboCasa Model Zoo Guide +This guide explains how to import and visualize assets in RoboCasa. + +## Installation +1. setup v-hacd: `scripts/model_zoo; bash install_vhacd.sh` +2. install additional dependencies: `pip install trimesh` + +## Overview +The structure of generated assets is as follows: +- `model.xml`: mjcf file containing visual geoms, collision geoms, joints, and sites +- `raw`: the original, unmodified model files (includes .glb file, .obj/.mtl files, image texture files) +- `visual`: the processed visual data (.obj files, image texture files) +- `collision`: the collision meshes .obj files (if applicable) + +## Importing objects +#### `import_glb_model.py` +Import a `.glb` model: +``` +python robocasa/scripts/model_zoo/import_glb_model.py --prescale --center --no_cached_coll --path +``` + +## Inspecting objects +#### `browse_mjcf_model.py` +Visualize the assets interactively: +``` +python robocasa/scripts/browse_mjcf_model.py --show_bbox --show_coll_geoms --mjcf +``` +Arguments: +- `show_bbox`: visualize the bounding box +- `show_coll_geoms`: show collision geoms + + + +## Importing fixtures +1. Bring object into Blender +- Use objaverse to find an object model and download it in the .glb format. A more manual process can be done with other file types, but none are well tested. +- Create a directory for the model in robosuite_model_zoo/assets/kitchen_fixtures/ +- Put the .glb file in the newly created model directory +- Use the Blender scripting tab to load scripts/glb_to_blender.py and set the string on line 29 to point to the model directory +- Run the script to bring the object into blender and export the textures - it should create a separate 'raw' directory in the model directory + +2. Export object from Blender +- Select objects that are part of a single body (not connected by a joint) + - Be sure to select the actual objects (with the triangle symbol in front), and not just the parent groupings +- File > Export as a Wavefront .obj and ensure that Limit to Selected Only is checked +- Export the files into the raw directory +- This should create both a .obj file and a .mtl file with the same name if done correctly +- Repeat for each connected body, using a different name for the .obj/.mtl files for each export + +3. Turn .obj files into Mujoco xml +``` + python objs_to_mjcf.py --path --primary +``` +- The path argument should be the model directory created in section 1, and the primary is the obj file for the main body of the object +- If you would like the model name to be different from the name of the primary body, add a --model_name parameter +- After running the script, there should be a composite .xml file, a visuals directory, and a command file in the model directory. + - The composite .xml file is a mujoco XML which correctly references all visual assets in visuals, is prescaled, and is centered at the origin + - The command file specifies the command used + +4. Add joints, collision boxes, and sites to the xml +- The .xml file has comments where to include the collision geoms and joints + - Make sure to use class="collision" for the collision geoms +- Use the mujoco viewer to check the fit of the joints, collision geoms, and sites while working +``` + python -m mujoco.viewer --mjcf= +``` + +5. Add object to the kitchen +- The current directory structure for visuals in robosuite-model-zoo does not match the one required for kitchen fixtures, so it is not easy to import + - Eventually, robosuite will pull objects from robosuite-model-zoo for fixtures + - This has not been tested, but it may be possible to just copy the contents of the object directory as a way to test temporarily diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/__init__.py @@ -0,0 +1 @@ + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/glb_to_blender.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/glb_to_blender.py new file mode 100644 index 0000000000000000000000000000000000000000..a3c9cb4e294112bee3c1f3033df483da6c8847ea --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/glb_to_blender.py @@ -0,0 +1,54 @@ +# RUN SCRIPT IN BLENDER CONSOLE + +import bpy +import os + + +def print(data): + for window in bpy.context.window_manager.windows: + screen = window.screen + for area in screen.areas: + if area.type == "CONSOLE": + override = {"window": window, "screen": screen, "area": area} + bpy.ops.console.scrollback_append( + override, text=str(data), type="OUTPUT" + ) + + +def clear_scene(): + # delete all objects + for obj in bpy.data.objects: + if obj.name != "Light" and obj.name != "Camera": + obj.select_set(True) + bpy.ops.object.delete() + + # delete all images + for image in bpy.data.images: + if "Image" in image.name: + bpy.data.images.remove(image) + + +clear_scene() + +# SET PATH TO MODEL FOLDER HERE - THE FOLDER MUST INCLUDE A .glb / .gltf FILE +model_folder = "" + +glb_files = [ + os.path.join(model_folder, name) + for name in os.listdir(model_folder) + if name.endswith(".glb") or name.endswith(".gltf") +] + +glb_path = glb_files[0] + +raw = os.path.join(model_folder, "raw") +os.mkdir(raw) + +bpy.ops.import_scene.gltf(filepath=glb_path) + +# save all textures +for i, image in enumerate(bpy.data.images): + if "Image" in image.name: + image_save_path = os.path.join(raw, f"image{i}.jpg") + image.filepath = image_save_path + image.save() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/import_glb_model.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/import_glb_model.py new file mode 100644 index 0000000000000000000000000000000000000000..e1f2fa8af84923b892115f1126b81478494fefb7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/import_glb_model.py @@ -0,0 +1,128 @@ +import os +import shutil +from distutils.dir_util import copy_tree +import trimesh +import robocasa +from termcolor import colored + +from pathlib import Path + +import robocasa.utils.model_zoo.mjcf_gen_utils as MJCFGenUtils +import robocasa.utils.model_zoo.file_utils as FileUtils +import robocasa.utils.model_zoo.parser_utils as ParserUtils +import robocasa.utils.model_zoo.log_utils as LogUtils + +if __name__ == "__main__": + parser = ParserUtils.get_base_parser() + parser.add_argument( + "--path", + type=str, + required=True, + help="path to existing .glb model", + ) + parser.add_argument( + "--output_path", + type=str, + help="path to store converted model", + ) + parser.add_argument( + "--rot", + type=str, + required=False, + help="axis to rotate around", + choices=[ + "x", + "y", + "z", # 90 degrees + "x90", + "x180", + "x270", + "y90", + "y180", + "y270", + "z60", + "z90", + "z180", + "z270", + ], + default="x", + ) + parser.add_argument( + "--show_coll_geoms", + action="store_true", + help="visually show collision geoms in addition to visual geoms", + ) + parser.add_argument( + "--hide_vis_geoms", + action="store_true", + help="hide visual geoms", + ) + parser.add_argument( + "--no_cached_coll", + action="store_true", + help="disable using cached coll geoms already generated in previous runs", + ) + parser.add_argument("--center", type=str, nargs="?", const="False", default="True") + parser.add_argument( + "--prescale", type=str, nargs="?", const="False", default="True" + ) + args = parser.parse_args() + + # if not os.path.isabs(args.path): + # args.path = os.path.join(macros.OBJAVERSE_PATH, args.path) + + verbose = args.verbose + + # get model name and asset path + model_name = args.model_name or FileUtils.get_stem(args.path) + output_path = args.output_path or os.path.join( + os.path.dirname(robocasa.__file__), "models/assets/model_zoo_assets", model_name + ) + if os.path.exists(output_path): + shutil.rmtree(output_path) + os.makedirs(output_path) + + # # save metadata + # LogUtils.save_meta(args, asset_path) + + glb_mesh = trimesh.load(args.path) + if not os.path.exists(os.path.join(output_path, "raw")): + os.makedirs(os.path.join(output_path, "raw")) + glb_mesh.export(os.path.join(output_path, "raw", "model_normalized.obj")) + + coll_path = os.path.join(output_path, "collision") + if not Path(coll_path).exists() or args.no_cached_coll: + MJCFGenUtils.decompose_convex( + Path(os.path.join(output_path, "raw/model_normalized.obj")), + Path(coll_path), + max_output_convex_hulls=args.vhacd_max_output_convex_hulls, + voxel_resolution=args.vhacd_voxel_resolution, + volume_error_percent=args.vhacd_volume_error_percent, + max_hull_vert_count=args.vhacd_max_hull_vert_count, + ) + + # get geom meta data + model_info = MJCFGenUtils.parse_model_info( + model_path=os.path.join(output_path, "raw"), + model_name=model_name, + coll_model_path=os.path.join(output_path, "collision"), + asset_path=os.path.join(output_path), + rot=args.rot, + verbose=verbose, + prescale=args.prescale, + center=args.center, + ) + + # generate mjcf file + mjcf_path = MJCFGenUtils.generate_mjcf( + asset_path=os.path.join(output_path), + model_name=model_name, + model_info=model_info, + sc=args.scale, + hide_vis_geoms=args.hide_vis_geoms, + show_coll_geoms=args.show_coll_geoms, + show_sites=args.show_sites, + verbose=verbose, + ) + + print(colored(f"Model output to: {output_path}/model.xml", color="green")) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/install_vhacd.sh b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/install_vhacd.sh new file mode 100644 index 0000000000000000000000000000000000000000..f4bc7c6684b15f865b1bccc30edfca5f552d0a9c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/install_vhacd.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Install V-HACD 4.0. +# Adapted from https://github.com/kevinzakka/obj2mjcf/blob/main/install_vhacd.sh + +# Check that cmake is installed. +t=`which cmake` +if [ -z "$t" ]; then + echo "You need cmake to install V-HACD." 1>&2 + exit 1 +fi + +# Clone and build executable. +# TODO(kevin): Peg to a 4.0 release when available, see #113. +git clone https://github.com/kmammou/v-hacd.git +cd v-hacd/app +cmake CMakeLists.txt +cmake --build . + +# Add executable to /usr/local/bin. +sudo ln -s "$PWD/TestVHACD" /usr/local/bin/TestVHACD diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/objs_to_mjcf.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/objs_to_mjcf.py new file mode 100644 index 0000000000000000000000000000000000000000..422700f7ed290c8e4e6cd3fc828f996c1295ec2d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/model_zoo/objs_to_mjcf.py @@ -0,0 +1,275 @@ +import os + +from pathlib import Path +import argparse +import tempfile +import shutil +import trimesh +import numpy as np + +import lxml.etree as ET + +from PIL import Image + +from robocasa.utils.model_zoo.mjcf_gen_utils import ( + parse_model_info, + decompose_convex, + generate_mjcf, +) + +# takes list of xml paths (primary first) +def merge_xmls(xmls, model_name, save_path): + + # Load XML tree + et = ET.parse( + os.path.join( + os.path.dirname(os.path.realpath(__file__)), "../utils/fixture_template.xml" + ) + ) + + root = et.getroot() + + # Relative path from final XML to visuals directory + visuals = "visuals" + + root.attrib["model"] = model_name + assets = root.find("asset") + + body = root.find("worldbody/body") + main = True + for xml in xmls: + model_tree = ET.parse(xml) + model_root = model_tree.getroot() + # Copy textures, materials, and meshes to main XML, ignoring collision meshes + for tex in model_root.iterfind("asset/texture"): + if all( + [ + tex.attrib["name"] != existing_tex.attrib["name"] + for existing_tex in assets.iterfind("texture") + ] + ): + tex.attrib["file"] = os.path.join( + visuals, Path(tex.attrib["file"]).stem + ".png" + ) + assets.append(tex) + + for mat in model_root.iterfind("asset/material"): + if all( + [ + mat.attrib["name"] != existing_mat.attrib["name"] + for existing_mat in assets.iterfind("material") + ] + ): + assets.append(mat) + + for mesh in model_root.iterfind("asset/mesh"): + if mesh.attrib["name"].split(".")[-1] != "_coll" and all( + [ + mesh.attrib["name"] != existing_mesh.attrib["name"] + for existing_mesh in assets.iterfind("mesh") + ] + ): + mesh.attrib["file"] = os.path.join( + visuals, Path(mesh.attrib["file"]).stem + ".obj" + ) + assets.append(mesh) + + new_body = ET.Element("body") + body.append(new_body) + + model_body = model_root.find("worldbody/body/body") + + if main: + body = body.find("body") + body.attrib["name"] = "object" + main = False + else: + new_body.attrib["name"] = Path(xml).stem + new_body.append(ET.Comment("Add Joint Here")) + + # Add geoms (ignoring collisions) to composite XML + for geom in model_body.iterfind("geom"): + if geom.attrib["group"] == "1": + del geom.attrib["group"] + del geom.attrib["conaffinity"] + del geom.attrib["contype"] + geom.attrib["class"] = "visual" + new_body.append(geom) + + new_body.append( + ET.Comment( + f'Add Collision Geom(s) for {Path(xml).stem} here - i.e. ' + ) + ) + + et.write(save_path) + + +def generate_xml_from_objs(model_dir, primary, model_name, rot, verbose): + raw = os.path.join(model_dir, "raw") + + obj_files = [ + os.path.join(model_dir, "raw", name) + for name in os.listdir(raw) + if name.endswith(".obj") + ] + + if len(obj_files) == 0: + raise Exception(f"Could not find .obj file in {raw}") + + if len(obj_files) > 1 and primary is None: + raise Exception("Must specify primary obj if there are multiple objs") + + # get model name + if model_name is not None: + model_name = model_name + elif primary is not None: + model_name = primary[:-4] + else: + model_name = Path(obj_files[0]).stem + + visuals = os.path.join(model_dir, "visuals") + os.makedirs(visuals, exist_ok=True) + + xmls = tempfile.TemporaryDirectory() + + # Load and concatenate all objs in trimesh + meshes = [] + for obj_file in obj_files: + meshes.append(trimesh.load(os.path.join(raw, obj_file), force="mesh")) + + conc = meshes[0] + for m in meshes[1:]: + conc = trimesh.util.concatenate(conc, m) + + # Compute center and scale factor for composite object + mat_t = np.eye((4)) + center = (conc.bounds[0] + conc.bounds[1]) / 2 + mat_t[:3, 3] = -center + transform = mat_t + + mat_s = np.eye((4)) + scale_factor = 1 / np.max(conc.bounds[1] - conc.bounds[0]) + mat_s *= scale_factor + + transform = np.matmul(mat_s, transform) + + # Use mjcf_gen_utils to create a mujoco xml for each component + for obj_file in obj_files: + output = tempfile.TemporaryDirectory() + obj_name = Path(obj_file).stem + asset_path = output.name + if not os.path.isdir(asset_path): + os.mkdir(asset_path) + + model_info = parse_model_info( + model_path=raw, + model_name=model_name, + obj_path=obj_file, + coll_model_path=None, + asset_path=asset_path, + rot=rot, + transform=transform, + verbose=verbose, + ) + + # generate mjcf file + mjcf_path = generate_mjcf( + asset_path=asset_path, + model_name=model_name, + model_info=model_info, + sc=1, + verbose=verbose, + texture_path=os.path.join(visuals, "material_0.png"), + ) + + shutil.copyfile( + os.path.join(output.name, "model.xml"), + os.path.join(xmls.name, Path(obj_file).stem + ".xml"), + ) + + if os.path.isfile(os.path.join(output.name, "visual", "material_0.jpeg")): + im = Image.open(os.path.join(output.name, "visual", "material_0.jpeg")) + im.save(os.path.join(visuals, "material_0.png")) + + for name in os.listdir(os.path.join(output.name, "visual")): + if name.endswith(".obj"): + shutil.copyfile( + os.path.join(output.name, "visual", name), + os.path.join(visuals, name), + ) + + for name in os.listdir(os.path.join(output.name, "visual")): + if name.endswith(".png"): + shutil.copy( + os.path.join(output.name, "visual", name), + os.path.join(visuals, name), + ) + + output.cleanup() + + # Ensure primary obj is first in the xml list + prim = primary[:-4] + ".xml" + xml_paths = os.listdir(xmls.name) + xml_paths.remove(prim) + xml_paths.insert(0, prim) + + xml_paths = [os.path.join(xmls.name, path) for path in xml_paths] + + merge_xmls(xml_paths, model_name, os.path.join(model_dir, model_name + ".xml")) + + xmls.cleanup() + + # Write command args to text file so the pipeline is easy to reuse + with open(os.path.join(model_dir, "command"), "w") as f: + short_model_path = model_dir[model_dir.index("robosuite_model_zoo") :] + cmd_string = f"python scripts/objs_to_mjcf.py --path ...{short_model_path}" + if primary is not None: + cmd_string += f" --primary {primary}" + if model_name is not None: + cmd_string += f" --model_name {model_name}" + if rot != "x": + cmd_string += f" --rot {rot}" + + f.write(cmd_string) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser() + parser.add_argument( + "--path", type=str, required=True, help="path to model directory" + ) + parser.add_argument( + "--rot", + type=str, + required=False, + help="axis to rotate around", + choices=["x", "y", "z", "none"], + default="x", + ) + parser.add_argument( + "--verbose", + action="store_true", + help="print detailed information for debugging", + ) + parser.add_argument( + "--model_name", + required=False, + type=str, + help="(optional) name of saved mjcf model. " + "Defaults to primary .obj file name", + ) + parser.add_argument( + "--primary", + required=False, + type=str, + default="model.obj", + help="(optional) ONLY if there is one obj file. Otherwise, this is the name of the obj file which is the main body", + ) + + args = parser.parse_args() + + generate_xml_from_objs( + args.path, args.primary, args.model_name, args.rot, args.verbose + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/play_dataset_montage.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/play_dataset_montage.py new file mode 100644 index 0000000000000000000000000000000000000000..c8407d668688fa26665105902029f38fdd87f1c7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/play_dataset_montage.py @@ -0,0 +1,63 @@ +from robocasa.utils.dataset_registry import ( + SINGLE_STAGE_TASK_DATASETS, + MULTI_STAGE_TASK_DATASETS, +) +from robocasa.utils.dataset_registry import get_ds_path +from robocasa.scripts.playback_dataset import playback_dataset + +import os +import argparse +from termcolor import colored + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument( + "--output", + type=str, + help="path to store videos", + default="/tmp/robocasa_dataset_montage", + ) + parser.add_argument( + "--num_demos_per_task", + type=int, + help="number of demos to play per task", + default=10, + ) + args = parser.parse_args() + + output_dir = args.output + output_dir = os.path.expanduser(output_dir) + if os.path.exists(output_dir) is False: + os.mkdir(output_dir) + + tasks = list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS) + + for task_i, task in enumerate(tasks): + ds_path = get_ds_path(task, ds_type="human_raw") + + parser = argparse.Namespace() + parser.dataset = ds_path + + parser.render = False + parser.video_path = os.path.join(output_dir, f"{task}.mp4") + parser.use_actions = False + parser.use_abs_actions = False + parser.render_image_names = ["robot0_agentview_center", "robot0_eye_in_hand"] + parser.use_obs = False + parser.n = args.num_demos_per_task + parser.filter_key = None + parser.video_skip = 5 + parser.first = False + parser.verbose = False + parser.extend_states = True + parser.camera_height = 512 + parser.camera_width = 768 + + print( + colored( + f"[{task_i+1} / {len(tasks)}] Playing sample demos for {task}", "yellow" + ) + ) + playback_dataset(parser) + print() + print() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/playback_dataset.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/playback_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..b0ff6e750059bf61b2e7208e550d1bfe3a7ca9ad --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/playback_dataset.py @@ -0,0 +1,540 @@ +import argparse +import json +import os +import random +import time + +import h5py +import imageio +import numpy as np +import robosuite +from termcolor import colored + +import robocasa + + +def playback_trajectory_with_env( + env, + initial_state, + states, + actions=None, + render=False, + video_writer=None, + video_skip=5, + camera_names=None, + first=False, + verbose=False, + camera_height=512, + camera_width=512, +): + """ + Helper function to playback a single trajectory using the simulator environment. + If @actions are not None, it will play them open-loop after loading the initial state. + Otherwise, @states are loaded one by one. + + Args: + env (instance of EnvBase): environment + initial_state (dict): initial simulation state to load + states (np.array): array of simulation states to load + actions (np.array): if provided, play actions back open-loop instead of using @states + render (bool): if True, render on-screen + video_writer (imageio writer): video writer + video_skip (int): determines rate at which environment frames are written to video + camera_names (list): determines which camera(s) are used for rendering. Pass more than + one to output a video with multiple camera views concatenated horizontally. + first (bool): if True, only use the first frame of each episode. + """ + write_video = video_writer is not None + video_count = 0 + assert not (render and write_video) + + # load the initial state + ## this reset call doesn't seem necessary. + ## seems ok to remove but haven't fully tested it. + ## removing for now + # env.reset() + + if verbose: + ep_meta = json.loads(initial_state["ep_meta"]) + lang = ep_meta.get("lang", None) + if lang is not None: + print(colored(f"Instruction: {lang}", "green")) + print(colored("Spawning environment...", "yellow")) + reset_to(env, initial_state) + + traj_len = states.shape[0] + action_playback = actions is not None + if action_playback: + assert states.shape[0] == actions.shape[0] + + if render is False: + print(colored("Running episode...", "yellow")) + + for i in range(traj_len): + start = time.time() + + if action_playback: + env.step(actions[i]) + if i < traj_len - 1: + # check whether the actions deterministically lead to the same recorded states + state_playback = np.array(env.sim.get_state().flatten()) + if not np.all(np.equal(states[i + 1], state_playback)): + err = np.linalg.norm(states[i + 1] - state_playback) + if verbose or i == traj_len - 2: + print( + colored( + "warning: playback diverged by {} at step {}".format( + err, i + ), + "yellow", + ) + ) + else: + reset_to(env, {"states": states[i]}) + + # on-screen render + if render: + if env.viewer is None: + env.initialize_renderer() + + # so that mujoco viewer renders + env.viewer.update() + + max_fr = 60 + elapsed = time.time() - start + diff = 1 / max_fr - elapsed + if diff > 0: + time.sleep(diff) + + # video render + if write_video: + if video_count % video_skip == 0: + video_img = [] + for cam_name in camera_names: + im = env.sim.render( + height=camera_height, width=camera_width, camera_name=cam_name + )[::-1] + video_img.append(im) + video_img = np.concatenate( + video_img, axis=1 + ) # concatenate horizontally + video_writer.append_data(video_img) + + video_count += 1 + + if first: + break + + if render: + env.viewer.close() + env.viewer = None + + +def playback_trajectory_with_obs( + traj_grp, + video_writer, + video_skip=5, + image_names=None, + first=False, +): + """ + This function reads all "rgb" observations in the dataset trajectory and + writes them into a video. + + Args: + traj_grp (hdf5 file group): hdf5 group which corresponds to the dataset trajectory to playback + video_writer (imageio writer): video writer + video_skip (int): determines rate at which environment frames are written to video + image_names (list): determines which image observations are used for rendering. Pass more than + one to output a video with multiple image observations concatenated horizontally. + first (bool): if True, only use the first frame of each episode. + """ + assert ( + image_names is not None + ), "error: must specify at least one image observation to use in @image_names" + video_count = 0 + + traj_len = traj_grp["obs/{}".format(image_names[0] + "_image")].shape[0] + for i in range(traj_len): + if video_count % video_skip == 0: + # concatenate image obs together + im = [traj_grp["obs/{}".format(k + "_image")][i] for k in image_names] + frame = np.concatenate(im, axis=1) + video_writer.append_data(frame) + video_count += 1 + + if first: + break + + +def get_env_metadata_from_dataset(dataset_path, ds_format="robomimic"): + """ + Retrieves env metadata from dataset. + + Args: + dataset_path (str): path to dataset + + Returns: + env_meta (dict): environment metadata. Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + """ + dataset_path = os.path.expanduser(dataset_path) + f = h5py.File(dataset_path, "r") + if ds_format == "robomimic": + env_meta = json.loads(f["data"].attrs["env_args"]) + else: + raise ValueError + f.close() + return env_meta + + +class ObservationKeyToModalityDict(dict): + """ + Custom dictionary class with the sole additional purpose of automatically registering new "keys" at runtime + without breaking. This is mainly for backwards compatibility, where certain keys such as "latent", "actions", etc. + are used automatically by certain models (e.g.: VAEs) but were never specified by the user externally in their + config. Thus, this dictionary will automatically handle those keys by implicitly associating them with the low_dim + modality. + """ + + def __getitem__(self, item): + # If a key doesn't already exist, warn the user and add default mapping + if item not in self.keys(): + print( + f"ObservationKeyToModalityDict: {item} not found," + f" adding {item} to mapping with assumed low_dim modality!" + ) + self.__setitem__(item, "low_dim") + return super(ObservationKeyToModalityDict, self).__getitem__(item) + + +def reset_to(env, state): + """ + Reset to a specific simulator state. + + Args: + state (dict): current simulator state that contains one or more of: + - states (np.ndarray): initial state of the mujoco environment + - model (str): mujoco scene xml + + Returns: + observation (dict): observation dictionary after setting the simulator state (only + if "states" is in @state) + """ + should_ret = False + if "model" in state: + if state.get("ep_meta", None) is not None: + # set relevant episode information + ep_meta = json.loads(state["ep_meta"]) + else: + ep_meta = {} + if hasattr(env, "set_attrs_from_ep_meta"): # older versions had this function + env.set_attrs_from_ep_meta(ep_meta) + elif hasattr(env, "set_ep_meta"): # newer versions + env.set_ep_meta(ep_meta) + # this reset is necessary. + # while the call to env.reset_from_xml_string does call reset, + # that is only a "soft" reset that doesn't actually reload the model. + env.reset() + robosuite_version_id = int(robosuite.__version__.split(".")[1]) + if robosuite_version_id <= 3: + from robosuite.utils.mjcf_utils import postprocess_model_xml + + xml = postprocess_model_xml(state["model"]) + else: + # v1.4 and above use the class-based edit_model_xml function + xml = env.edit_model_xml(state["model"]) + + env.reset_from_xml_string(xml) + env.sim.reset() + # hide teleop visualization after restoring from model + # env.sim.model.site_rgba[env.eef_site_id] = np.array([0., 0., 0., 0.]) + # env.sim.model.site_rgba[env.eef_cylinder_id] = np.array([0., 0., 0., 0.]) + if "states" in state: + env.sim.set_state_from_flattened(state["states"]) + env.sim.forward() + should_ret = True + + # update state as needed + if hasattr(env, "update_sites"): + # older versions of environment had update_sites function + env.update_sites() + if hasattr(env, "update_state"): + # later versions renamed this to update_state + env.update_state() + + # if should_ret: + # # only return obs if we've done a forward call - otherwise the observations will be garbage + # return get_observation() + return None + + +def playback_dataset(args): + # some arg checking + write_video = args.render is not True + if args.video_path is None: + args.video_path = args.dataset.split(".hdf5")[0] + ".mp4" + if args.use_actions: + args.video_path = args.dataset.split(".hdf5")[0] + "_use_actions.mp4" + elif args.use_abs_actions: + args.video_path = args.dataset.split(".hdf5")[0] + "_use_abs_actions.mp4" + assert not (args.render and write_video) # either on-screen or video but not both + + # Auto-fill camera rendering info if not specified + if args.render_image_names is None: + # We fill in the automatic values + env_meta = get_env_metadata_from_dataset(dataset_path=args.dataset) + args.render_image_names = "robot0_agentview_center" + + if args.render: + # on-screen rendering can only support one camera + assert len(args.render_image_names) == 1 + + if args.use_obs: + assert write_video, "playback with observations can only write to video" + assert ( + not args.use_actions and not args.use_abs_actions + ), "playback with observations is offline and does not support action playback" + + env = None + + # create environment only if not playing back with observations + if not args.use_obs: + # # need to make sure ObsUtils knows which observations are images, but it doesn't matter + # # for playback since observations are unused. Pass a dummy spec here. + # dummy_spec = dict( + # obs=dict( + # low_dim=["robot0_eef_pos"], + # rgb=[], + # ), + # ) + # initialize_obs_utils_with_obs_specs(obs_modality_specs=dummy_spec) + + env_meta = get_env_metadata_from_dataset(dataset_path=args.dataset) + if args.use_abs_actions: + env_meta["env_kwargs"]["controller_configs"][ + "control_delta" + ] = False # absolute action space + + env_kwargs = env_meta["env_kwargs"] + env_kwargs["env_name"] = env_meta["env_name"] + env_kwargs["has_renderer"] = False + env_kwargs["renderer"] = "mjviewer" + env_kwargs["has_offscreen_renderer"] = write_video + env_kwargs["use_camera_obs"] = False + + if args.verbose: + print( + colored( + "Initializing environment for {}...".format(env_kwargs["env_name"]), + "yellow", + ) + ) + + env = robosuite.make(**env_kwargs) + + f = h5py.File(args.dataset, "r") + + # list of all demonstration episodes (sorted in increasing number order) + if args.filter_key is not None: + print("using filter key: {}".format(args.filter_key)) + demos = [ + elem.decode("utf-8") + for elem in np.array(f["mask/{}".format(args.filter_key)]) + ] + elif "data" in f.keys(): + demos = list(f["data"].keys()) + + inds = np.argsort([int(elem[5:]) for elem in demos]) + demos = [demos[i] for i in inds] + + # maybe reduce the number of demonstrations to playback + if args.n is not None: + random.shuffle(demos) + demos = demos[: args.n] + + # maybe dump video + video_writer = None + if write_video: + video_writer = imageio.get_writer(args.video_path, fps=20) + + for ind in range(len(demos)): + ep = demos[ind] + print(colored("\nPlaying back episode: {}".format(ep), "yellow")) + + if args.use_obs: + playback_trajectory_with_obs( + traj_grp=f["data/{}".format(ep)], + video_writer=video_writer, + video_skip=args.video_skip, + image_names=args.render_image_names, + first=args.first, + ) + continue + + # prepare initial state to reload from + states = f["data/{}/states".format(ep)][()] + initial_state = dict(states=states[0]) + initial_state["model"] = f["data/{}".format(ep)].attrs["model_file"] + initial_state["ep_meta"] = f["data/{}".format(ep)].attrs.get("ep_meta", None) + + if args.extend_states: + states = np.concatenate((states, [states[-1]] * 50)) + + # supply actions if using open-loop action playback + actions = None + assert not ( + args.use_actions and args.use_abs_actions + ) # cannot use both relative and absolute actions + if args.use_actions: + actions = f["data/{}/actions".format(ep)][()] + elif args.use_abs_actions: + actions = f["data/{}/actions_abs".format(ep)][()] # absolute actions + + playback_trajectory_with_env( + env=env, + initial_state=initial_state, + states=states, + actions=actions, + render=args.render, + video_writer=video_writer, + video_skip=args.video_skip, + camera_names=args.render_image_names, + first=args.first, + verbose=args.verbose, + camera_height=args.camera_height, + camera_width=args.camera_width, + ) + + f.close() + if write_video: + print(colored(f"Saved video to {args.video_path}", "green")) + video_writer.close() + + if env is not None: + env.close() + + +def get_playback_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--dataset", + type=str, + help="path to hdf5 dataset", + ) + parser.add_argument( + "--filter_key", + type=str, + default=None, + help="(optional) filter key, to select a subset of trajectories in the file", + ) + + # number of trajectories to playback. If omitted, playback all of them. + parser.add_argument( + "--n", + type=int, + default=None, + help="(optional) stop after n trajectories are played", + ) + + # Use image observations instead of doing playback using the simulator env. + parser.add_argument( + "--use-obs", + action="store_true", + help="visualize trajectories with dataset image observations instead of simulator", + ) + + # Playback stored dataset actions open-loop instead of loading from simulation states. + parser.add_argument( + "--use-actions", + action="store_true", + help="use open-loop action playback instead of loading sim states", + ) + + # Playback stored dataset absolute actions open-loop instead of loading from simulation states. + parser.add_argument( + "--use-abs-actions", + action="store_true", + help="use open-loop action playback with absolute position actions instead of loading sim states", + ) + + # Whether to render playback to screen + parser.add_argument( + "--render", + action="store_true", + help="on-screen rendering", + ) + + # Dump a video of the dataset playback to the specified path + parser.add_argument( + "--video_path", + type=str, + default=None, + help="(optional) render trajectories to this video file path", + ) + + # How often to write video frames during the playback + parser.add_argument( + "--video_skip", + type=int, + default=5, + help="render frames to video every n steps", + ) + + # camera names to render, or image observations to use for writing to video + parser.add_argument( + "--render_image_names", + type=str, + nargs="+", + default=[ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ], + help="(optional) camera name(s) / image observation(s) to use for rendering on-screen or to video. Default is" + "None, which corresponds to a predefined camera for each env type", + ) + + # Only use the first frame of each episode + parser.add_argument( + "--first", + action="store_true", + help="use first frame of each episode", + ) + + parser.add_argument( + "--extend_states", + action="store_true", + help="play last step of episodes for 50 extra frames", + ) + + parser.add_argument( + "--verbose", + action="store_true", + help="log additional information", + ) + + parser.add_argument( + "--camera_height", + type=int, + default=512, + help="(optional, for offscreen rendering) height of image observations", + ) + + parser.add_argument( + "--camera_width", + type=int, + default=512, + help="(optional, for offscreen rendering) width of image observations", + ) + + args = parser.parse_args() + return args + + +if __name__ == "__main__": + args = get_playback_args() + playback_dataset(args) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/setup_macros.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/setup_macros.py new file mode 100644 index 0000000000000000000000000000000000000000..0c588e6a90cad4cdf91ccf9d578b879cdd487517 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/scripts/setup_macros.py @@ -0,0 +1,35 @@ +""" +This script sets up a private macros file. +The private macros file (macros_private.py) is not tracked by git, +allowing user-specific settings that are not tracked by git. +This script checks if macros_private.py exists. +If applicable, it creates the private macros at robocasa/macros_private.py +""" + +import os +import shutil + +import robocasa + +if __name__ == "__main__": + base_path = robocasa.__path__[0] + macros_path = os.path.join(base_path, "macros.py") + macros_private_path = os.path.join(base_path, "macros_private.py") + + print("Setting up private macros file...") + + if not os.path.exists(macros_path): + print("{} does not exist! Aborting...".format(macros_path)) + + if os.path.exists(macros_private_path): + ans = input( + "{} already exists! \noverwrite? (y/n)\n".format(macros_private_path) + ) + + if ans == "y": + print("REMOVING") + else: + exit() + + shutil.copyfile(macros_path, macros_private_path) + print("copied {}\nto {}".format(macros_path, macros_private_path)) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fd4d6a4f9e82ded5ad6bbec5664058b450a5f55a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/__init__.py @@ -0,0 +1 @@ +from robosuite.utils import * diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/camera_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/camera_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f09cf38ddb9aa09cf43a3f74d2420c7f676f15a7 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/camera_utils.py @@ -0,0 +1,118 @@ +""" +Collection of constants for cameras / robots / etc +in kitchen environments +""" + +# default free cameras for different kitchen layouts +LAYOUT_CAMS = { + 0: dict( + lookat=[2.26593463, -1.00037131, 1.38769295], + distance=3.0505089839567323, + azimuth=90.71563812375285, + elevation=-12.63948837207208, + ), + 1: dict( + lookat=[2.66147999, -1.00162429, 1.2425155], + distance=3.7958766287746255, + azimuth=89.75784013699234, + elevation=-15.177406642875091, + ), + 2: dict( + lookat=[3.02344359, -1.48874618, 1.2412914], + distance=3.6684844368165512, + azimuth=51.67880851867874, + elevation=-13.302619131542388, + ), + # 3: dict( + # lookat=[11.44842548, -11.47664723, 11.24115989], + # distance=43.923271794728187, + # azimuth=227.12928449329333, + # elevation=-16.495686334624907, + # ), + 4: dict( + lookat=[1.6, -1.0, 1.0], + distance=5, + azimuth=89.70301806083651, + elevation=-18.02177994296577, + ), +} + +DEFAULT_LAYOUT_CAM = { + "lookat": [2.25, -1, 1.05312667], + "distance": 5, + "azimuth": 89.70301806083651, + "elevation": -18.02177994296577, +} + +CAM_CONFIGS = dict( + DEFAULT=dict( + robot0_agentview_center=dict( + pos=[-0.6, 0.0, 1.15], + quat=[ + 0.636945903301239, + 0.3325185477733612, + -0.3199238181114197, + -0.6175596117973328, + ], + parent_body="mobilebase0_support", + ), + robot0_agentview_left=dict( + pos=[-0.5, 0.35, 1.05], + quat=[0.55623853, 0.29935253, -0.37678665, -0.6775092], + camera_attribs=dict(fovy="60"), + parent_body="mobilebase0_support", + ), + robot0_agentview_right=dict( + pos=[-0.5, -0.35, 1.05], + quat=[ + 0.6775091886520386, + 0.3767866790294647, + -0.2993525564670563, + -0.55623859167099, + ], + camera_attribs=dict(fovy="60"), + parent_body="mobilebase0_support", + ), + robot0_frontview=dict( + pos=[-0.50, 0, 0.95], + quat=[ + 0.6088936924934387, + 0.3814677894115448, + -0.3673907518386841, + -0.5905545353889465, + ], + camera_attribs=dict(fovy="60"), + parent_body="mobilebase0_support", + ), + robot0_eye_in_hand=dict( + pos=[0.05, 0, 0], + quat=[0, 0.707107, 0.707107, 0], + parent_body="robot0_right_hand", + ), + ), + ### Add robot specific configs here #### + PandaMobile=dict(), + GR1FixedLowerBody=dict(), +) + + +def deep_update(d, u): + """ + Copied from https://stackoverflow.com/a/3233356 + """ + import collections + + for k, v in u.items(): + if isinstance(v, collections.abc.Mapping): + d[k] = deep_update(d.get(k, {}), v) + else: + d[k] = v + return d + + +def get_robot_cam_configs(robot): + from copy import deepcopy + + default_configs = deepcopy(CAM_CONFIGS["DEFAULT"]) + robot_specific_configs = deepcopy(CAM_CONFIGS.get(robot, {})) + return deep_update(default_configs, robot_specific_configs) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/config_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/config_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..bbb5faf04fbc0f37967b7c99b124f5c80307cb1b --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/config_utils.py @@ -0,0 +1,63 @@ +import copy +import os +import pathlib +import robosuite +from robosuite.controllers import load_composite_controller_config + + +def is_stale_controller_config(config: dict): + """ + Checks if a controller config is in the format from robosuite versions <= 1.4.1. + Does not check for config validity, only the format type. + Args: + config (dict): Controller configuration + Returns: + bool: True if the config is in the old format, False otherwise + """ + + OLD_CONTROLLER_TYPES = [ + "JOINT_VELOCITY", + "JOINT_TORQUE", + "JOINT_POSITION", + "OSC_POSITION", + "OSC_POSE", + "IK_POSE", + ] + if ( + "body_parts" not in config or "body_parts_controller_configs" not in config + ) and "type" in config: + return config["type"] in OLD_CONTROLLER_TYPES + return False + + +def refactor_composite_controller_config(controller_config, robot_type, arms): + """ + Checks if a controller config is in the format from robosuite versions <= 1.4.1. + If this is the case, converts the controller config to the new composite controller + config format in robosuite versions >= 1.5. If the robot has a default + controller config use that and override the arms with the old controller config. + If not just use the old controller config for arms. + Args: + old_controller_config (dict): Old controller config + Returns: + dict: New controller config + """ + if not is_stale_controller_config(controller_config): + return controller_config + + config_dir = pathlib.Path(robosuite.__file__).parent / "controllers/config/robots/" + name = robot_type.lower() + configs = os.listdir(config_dir) + if f"default_{name}.json" in configs: + new_controller_config = load_composite_controller_config(robot=name) + else: + new_controller_config = {} + new_controller_config["type"] = "BASIC" + new_controller_config["body_parts"] = {} + + for arm in arms: + new_arm_config = copy.deepcopy(controller_config) + if "gripper" not in new_arm_config: + new_arm_config["gripper"] = {"type": "GRIP"} + new_controller_config["body_parts"][arm] = new_arm_config + return new_controller_config diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/dataset_registry.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/dataset_registry.py new file mode 100644 index 0000000000000000000000000000000000000000..de27f9a1c65151b03af259e447e1638c7ba57dcf --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/dataset_registry.py @@ -0,0 +1,354 @@ +import os +from collections import OrderedDict +from copy import deepcopy +from pathlib import Path + +import robocasa +import robocasa.macros as macros + +SINGLE_STAGE_TASK_DATASETS = OrderedDict( + PnPCounterToCab=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_pnp/PnPCounterToCab/2024-04-24", + mg_path="v0.1/single_stage/kitchen_pnp/PnPCounterToCab/mg/2024-05-04-22-12-27_and_2024-05-07-07-39-33", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/c0a0vdyqeqh6o9z4c57sk61aypladizj.hdf5", + human_im="https://utexas.box.com/shared/static/gznii250ip99731ii2r0ml6be7gzt2cp.hdf5", + mg_im="https://utexas.box.com/shared/static/7y9csrcx6uhhq4p3yctmm2df3rjqpw6g.hdf5", + ), + ), + PnPCabToCounter=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_pnp/PnPCabToCounter/2024-04-24", + mg_path="v0.1/single_stage/kitchen_pnp/PnPCabToCounter/mg/2024-07-12-04-33-29", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/fgd165p91ts9qurfb496ubi1xdqgrz97.hdf5", + human_im="https://utexas.box.com/shared/static/pdfh88slq4bazfglixaw80whvbtlbw6r.hdf5", + mg_im="https://utexas.box.com/shared/static/mfltre5w8qi8ps1fqicblx40p008425z.hdf5", + ), + ), + PnPCounterToSink=dict( + horizon=700, + human_path="v0.1/single_stage/kitchen_pnp/PnPCounterToSink/2024-04-25", + mg_path="v0.1/single_stage/kitchen_pnp/PnPCounterToSink/mg/2024-05-04-22-14-06_and_2024-05-07-07-40-17", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/nc0x55xwlgs4acj97ngdj1q6pv450ooo.hdf5", + human_im="https://utexas.box.com/shared/static/0z1wr8iwfusfqqpp56j3vfxvvse1x0vc.hdf5", + mg_im="https://utexas.box.com/shared/static/5vkb2fpthnw554q888fynk3zqwsgk2e5.hdf5", + ), + ), + PnPSinkToCounter=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_pnp/PnPSinkToCounter/2024-04-26_2", + mg_path="v0.1/single_stage/kitchen_pnp/PnPSinkToCounter/mg/2024-05-04-22-14-34_and_2024-05-07-07-40-21", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/uyhepwjyr0880a5q03fc61qmhbrhwy7k.hdf5", + human_im="https://utexas.box.com/shared/static/pe03k5qvcuq1nzbpfag5pfo2t8fzvl9i.hdf5", + mg_im="https://utexas.box.com/shared/static/ppj3j8jnxkpusi7ft44f5ut7szkmu8yr.hdf5", + ), + ), + PnPCounterToMicrowave=dict( + horizon=600, + human_path="v0.1/single_stage/kitchen_pnp/PnPCounterToMicrowave/2024-04-27", + mg_path="v0.1/single_stage/kitchen_pnp/PnPCounterToMicrowave/mg/2024-05-04-22-13-21_and_2024-05-07-07-41-17", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/z1qwxsuczjmv68p7267nylbv9ebc6g4p.hdf5", + human_im="https://utexas.box.com/shared/static/2kun70ehqzanl5h0hbgpdezrfrvuimq8.hdf5", + mg_im="https://utexas.box.com/shared/static/vdm6pzl68xqqxvk9iy7i3l62j37t3sbp.hdf5", + ), + ), + PnPMicrowaveToCounter=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_pnp/PnPMicrowaveToCounter/2024-04-26", + mg_path="v0.1/single_stage/kitchen_pnp/PnPMicrowaveToCounter/mg/2024-05-04-22-14-26_and_2024-05-07-07-41-42", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/emnl5i3s621sf5smgek5lu4twbc326jt.hdf5", + human_im="https://utexas.box.com/shared/static/z2t1kyto32thprw7xvq3r4tjvkdz0dl2.hdf5", + mg_im="https://utexas.box.com/shared/static/3gs5cvp5qyzvk7gplmp0lkwfs1x1mkrj.hdf5", + ), + ), + PnPCounterToStove=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_pnp/PnPCounterToStove/2024-04-26", + mg_path="v0.1/single_stage/kitchen_pnp/PnPCounterToStove/mg/2024-05-04-22-14-20", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/9z2k5iqspwdo2153yuutcvqb9zzzvtdu.hdf5", + human_im="https://utexas.box.com/shared/static/penrv5sysn192gxwj7n7f6k0gjceovfn.hdf5", + mg_im="https://utexas.box.com/shared/static/1ytpoks6mp9f56wh36ni8k02fz0kbvmb.hdf5", + ), + ), + PnPStoveToCounter=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_pnp/PnPStoveToCounter/2024-05-01", + mg_path="v0.1/single_stage/kitchen_pnp/PnPStoveToCounter/mg/2024-05-04-22-14-40", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/1m3v1rkh7gna5ujt0vcwzej7stv5rdio.hdf5", + human_im="https://utexas.box.com/shared/static/rht9bfh38gaue5ig17ubpsibb4jrgtyv.hdf5", + mg_im="https://utexas.box.com/shared/static/uvrx2d7zxungplafbn9kg6rbe23ysund.hdf5", + ), + ), + OpenSingleDoor=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_doors/OpenSingleDoor/2024-04-24", + mg_path="v0.1/single_stage/kitchen_doors/OpenSingleDoor/mg/2024-05-04-22-37-39", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/hjukxdpqvnrghtbjbhin28idzkysq7oa.hdf5", + human_im="https://utexas.box.com/shared/static/vhvlbuza3g1lpqa9m6zvmbzh8xquvqy8.hdf5", + mg_im="https://utexas.box.com/shared/static/ekf6qwp9s07jnkpazbohlv03d6b73vth.hdf5", + ), + ), + CloseSingleDoor=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_doors/CloseSingleDoor/2024-04-24", + mg_path="v0.1/single_stage/kitchen_doors/CloseSingleDoor/mg/2024-05-04-22-34-56", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/gea28p5mrvj9lnw1s6c8fqvzxk5f779i.hdf5", + human_im="https://utexas.box.com/shared/static/2wnm0u1x9fp9ni02pmzqzhpjsb1kgfrr.hdf5", + mg_im="https://utexas.box.com/shared/static/5mg9vkhilkaxza83l48aht3sk76086tm.hdf5", + ), + ), + OpenDoubleDoor=dict( + horizon=1000, + human_path="v0.1/single_stage/kitchen_doors/OpenDoubleDoor/2024-04-26", + mg_path="v0.1/single_stage/kitchen_doors/OpenDoubleDoor/mg/2024-05-04-22-35-53", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/xl23utiszzdbjdqlveq1mxxca9m3kbvw.hdf5", + human_im="https://utexas.box.com/shared/static/8swihowjd5fdk1vpf0k94gl72f8nbjeb.hdf5", + mg_im="https://utexas.box.com/shared/static/5djutjyyksic6qpl2uuq9cvzj3r78jvf.hdf5", + ), + ), + CloseDoubleDoor=dict( + horizon=700, + human_path="v0.1/single_stage/kitchen_doors/CloseDoubleDoor/2024-04-29", + mg_path="v0.1/single_stage/kitchen_doors/CloseDoubleDoor/mg/2024-05-04-22-22-42_and_2024-05-08-06-02-36", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/zozyctzejc2nrlpjwqjq4w761830kq45.hdf5", + human_im="https://utexas.box.com/shared/static/14f2ssfhwfhyo9cvj0s3kq303bv38g6t.hdf5", + mg_im="https://utexas.box.com/shared/static/7t269kmcrsycc4wz5wonw62ijopjhyv7.hdf5", + ), + ), + OpenDrawer=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_drawer/OpenDrawer/2024-05-03", + mg_path="v0.1/single_stage/kitchen_drawer/OpenDrawer/mg/2024-05-04-22-38-42", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/990d2f339zvalvlw50s4s1l6sfvt018m.hdf5", + human_im="https://utexas.box.com/shared/static/d8a0g5827kbm4ufk3p1tbuz3idstgum8.hdf5", + mg_im="https://utexas.box.com/shared/static/t0sio5vrdax5bdfqkumfh63inq6o9b88.hdf5", + ), + ), + CloseDrawer=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_drawer/CloseDrawer/2024-04-30", + mg_path="v0.1/single_stage/kitchen_drawer/CloseDrawer/mg/2024-05-09-09-32-19", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/ooekd1zdy02hfu234xm5h63f7mzbez4b.hdf5", + human_im="https://utexas.box.com/shared/static/4r5w0a6i4jtgv5qmqx09fnqh5d7c45oi.hdf5", + mg_im="https://utexas.box.com/shared/static/aohabqltp8c6ze61u4h2uhtc9p9w35zb.hdf5", + ), + ), + TurnOnSinkFaucet=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_sink/TurnOnSinkFaucet/2024-04-25", + mg_path="v0.1/single_stage/kitchen_sink/TurnOnSinkFaucet/mg/2024-05-04-22-17-46", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/7vogk85ed3sm1o1vo8fzast9rs8zshgk.hdf5", + human_im="https://utexas.box.com/shared/static/f0brygtzwgmmwccg58b6m82yapa4jnji.hdf5", + mg_im="https://utexas.box.com/shared/static/p8x9njpsf5j9fkmnu7lwajupzm1t7aap.hdf5", + ), + ), + TurnOffSinkFaucet=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_sink/TurnOffSinkFaucet/2024-04-25", + mg_path="v0.1/single_stage/kitchen_sink/TurnOffSinkFaucet/mg/2024-05-04-22-17-26", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/ukkycoa2c6k5d6bpt1cdplzk2nrg879t.hdf5", + human_im="https://utexas.box.com/shared/static/ceewfn4ydhprupdcdppfe8wu4x61oxdg.hdf5", + mg_im="https://utexas.box.com/shared/static/r392ma0dje2t5ov4dug4vbqhn0z6hblk.hdf5", + ), + ), + TurnSinkSpout=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_sink/TurnSinkSpout/2024-04-29", + mg_path="v0.1/single_stage/kitchen_sink/TurnSinkSpout/mg/2024-05-09-09-31-12", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/zxop70u9s6rl4udz7fhp4besrvu508pj.hdf5", + human_im="https://utexas.box.com/shared/static/nnojt3760k143fxwhf2u0kzh1i56n7x1.hdf5", + mg_im="https://utexas.box.com/shared/static/34l1y45xquau66nk8j7hrpfvlad4b9fg.hdf5", + ), + ), + TurnOnStove=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_stove/TurnOnStove/2024-05-02", + mg_path="v0.1/single_stage/kitchen_stove/TurnOnStove/mg/2024-05-08-09-20-31", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/ow4npc933yty4blxg8rc2pgjp6f1yc36.hdf5", + human_im="https://utexas.box.com/shared/static/dewbngq5wk6dipb29x6984x6dygu2gck.hdf5", + mg_im="https://utexas.box.com/shared/static/7gzolvj3fyzhhfjoxswmmpjpxu5q4too.hdf5", + ), + ), + TurnOffStove=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_stove/TurnOffStove/2024-05-02", + mg_path="v0.1/single_stage/kitchen_stove/TurnOffStove/mg/2024-05-08-09-20-45", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/vp6u3huv9c2vg5r09105gkbmwguycnn0.hdf5", + human_im="https://utexas.box.com/shared/static/8tukea09szcjb2ncbe43zt65n7dzg4eh.hdf5", + mg_im="https://utexas.box.com/shared/static/6rv14y77hfknrwfbwn5qtlfdydkr8tog.hdf5", + ), + ), + CoffeeSetupMug=dict( + horizon=600, + human_path="v0.1/single_stage/kitchen_coffee/CoffeeSetupMug/2024-04-25", + mg_path="v0.1/single_stage/kitchen_coffee/CoffeeSetupMug/mg/2024-05-04-22-22-13_and_2024-05-08-05-52-13", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/zxytzos86xes7jo8z0gp7lklawbiyo8g.hdf5", + human_im="https://utexas.box.com/shared/static/pv2i49t4p7238gp34txhm7jcl7domw58.hdf5", + mg_im="https://utexas.box.com/shared/static/uagjbu3y2ds0hzm7789nuj0ppxp9dxxl.hdf5", + ), + ), + CoffeeServeMug=dict( + horizon=600, + human_path="v0.1/single_stage/kitchen_coffee/CoffeeServeMug/2024-05-01", + mg_path="v0.1/single_stage/kitchen_coffee/CoffeeServeMug/mg/2024-05-04-22-21-50", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/tse3mkxx913pf4d4ij7fplchtv1rchkq.hdf5", + human_im="https://utexas.box.com/shared/static/ts3537f93dzjpkux19syy0pndw5re231.hdf5", + mg_im="https://utexas.box.com/shared/static/ikkr7qu89v9e0o1kwiqttkxllaxvv2n4.hdf5", + ), + ), + CoffeePressButton=dict( + horizon=300, + human_path="v0.1/single_stage/kitchen_coffee/CoffeePressButton/2024-04-25", + mg_path="v0.1/single_stage/kitchen_coffee/CoffeePressButton/mg/2024-05-04-22-21-32", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/t6oblmeilexe9ndca4ccaxdclw1tzps5.hdf5", + human_im="https://utexas.box.com/shared/static/l5dnmcfd0r36vhdqgjchxo20vajt7ohl.hdf5", + mg_im="https://utexas.box.com/shared/static/y5zm9mlslfg8p4jkpwnxlizcsvsca1mb.hdf5", + ), + ), + TurnOnMicrowave=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_microwave/TurnOnMicrowave/2024-04-25", + mg_path="v0.1/single_stage/kitchen_microwave/TurnOnMicrowave/mg/2024-05-04-22-40-00", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/o1sp7qrcd97b6jo68olx58l35wffpbna.hdf5", + human_im="https://utexas.box.com/shared/static/t6eromogy5is2no3s1e5bk1nb2hgab2k.hdf5", + mg_im="https://utexas.box.com/shared/static/t1n5oijudf8yn85bj8v64b1codde7kye.hdf5", + ), + ), + TurnOffMicrowave=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_microwave/TurnOffMicrowave/2024-04-25", + mg_path="v0.1/single_stage/kitchen_microwave/TurnOffMicrowave/mg/2024-05-04-22-39-23", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/m2exfytqjd0496y70b3ou2i8993ryb50.hdf5", + human_im="https://utexas.box.com/shared/static/0drm2h7fgd5857x8xgcj1lph23srpbj1.hdf5", + mg_im="https://utexas.box.com/shared/static/7c8bku46us9a8sddwg3zk6z3p4ce6ya0.hdf5", + ), + ), + NavigateKitchen=dict( + horizon=500, + human_path="v0.1/single_stage/kitchen_navigate/NavigateKitchen/2024-05-09", + mg_path=None, + download_links=dict( + human_raw="https://utexas.box.com/shared/static/pzvzuvmkla74kro84yw13uwjr2g89z8m.hdf5", + human_im="https://utexas.box.com/shared/static/mbi6011svy2zb436wsf2hhc337aduwmw.hdf5", + ), + ), +) + + +MULTI_STAGE_TASK_DATASETS = OrderedDict( + ArrangeVegetables=dict( + human_path="v0.1/multi_stage/chopping_food/ArrangeVegetables/2024-05-11", + horizon=1200, + activity="chopping_food", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/hiwbv68h3vty9ksqsdhcw2xhuvkwcf3o.hdf5", + human_im="https://utexas.box.com/shared/static/ovzt0bod4nrrack6dak12jn1fx2cnwbw.hdf5", + ), + ), + MicrowaveThawing=dict( + human_path="v0.1/multi_stage/defrosting_food/MicrowaveThawing/2024-05-11", + horizon=1000, + activity="defrosting_food", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/wreambog4jak8og9nbhm0nr2t6w5ygdt.hdf5", + human_im="https://utexas.box.com/shared/static/ehwo6728r3qyi8g0h70zhawijojqotnm.hdf5", + ), + ), + RestockPantry=dict( + human_path="v0.1/multi_stage/restocking_supplies/RestockPantry/2024-05-10", + horizon=1000, + activity="restocking_supplies", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/t2g6rdyh006bw09cxxxamd7thton5grl.hdf5", + human_im="https://utexas.box.com/shared/static/35yr2xmsmwq0xkknvlmlivh9ifste71q.hdf5", + ), + ), + PreSoakPan=dict( + human_path="v0.1/multi_stage/washing_dishes/PreSoakPan/2024-05-10", + horizon=1500, + activity="washing_dishes", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/d4vg2pag7465xp99vej1skk3frmohzk1.hdf5", + human_im="https://utexas.box.com/shared/static/etotr8tn0z57ttb311bibh0mdmc65j96.hdf5", + ), + ), + PrepareCoffee=dict( + human_path="v0.1/multi_stage/brewing/PrepareCoffee/2024-05-07", + horizon=1000, + activity="brewing", + download_links=dict( + human_raw="https://utexas.box.com/shared/static/qhtle2ccvm17g65ecg2vrudpkl9v5wkk.hdf5", + human_im="https://utexas.box.com/shared/static/qq3p4ctlmiv751jx5av92aaz9dxylw76.hdf5", + ), + ), +) + + +def get_ds_path(task, ds_type, return_info=False): + if task in SINGLE_STAGE_TASK_DATASETS: + ds_config = SINGLE_STAGE_TASK_DATASETS[task] + elif task in MULTI_STAGE_TASK_DATASETS: + ds_config = MULTI_STAGE_TASK_DATASETS[task] + else: + raise ValueError + + if ds_type == "human_raw": + folder = ds_config["human_path"] + fname = "demo.hdf5" + elif ds_type == "human_im": + folder = ds_config["human_path"] + if task in SINGLE_STAGE_TASK_DATASETS: + fname = "demo_gentex_im128_randcams.hdf5" + elif task in MULTI_STAGE_TASK_DATASETS: + fname = "demo_im128.hdf5" + elif ds_type == "mg_im": + # mg dataset is not available for all tasks + folder = ds_config.get("mg_path", None) + fname = "demo_gentex_im128_randcams.hdf5" + else: + raise ValueError + + # if dataset type is not registered, return None + if folder is None: + ret = (None, None) if return_info is True else None + return ret + + if macros.DATASET_BASE_PATH is None: + ds_base_path = os.path.join( + Path(robocasa.__path__[0]).parent.absolute(), "datasets" + ) + else: + ds_base_path = macros.DATASET_BASE_PATH + ds_path = os.path.join(ds_base_path, folder, fname) + + if return_info is False: + return ds_path + + ds_info = {} + ds_info["url"] = ds_config["download_links"][ds_type] + ds_info["horizon"] = ds_config["horizon"] + return ds_path, ds_info diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/env_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/env_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..8ba96e01ec848703856710da8aca85efa0ce37eb --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/env_utils.py @@ -0,0 +1,110 @@ +from robocasa.utils.dataset_registry import ( + get_ds_path, + SINGLE_STAGE_TASK_DATASETS, + MULTI_STAGE_TASK_DATASETS, +) +from robocasa.scripts.playback_dataset import get_env_metadata_from_dataset +from robosuite.controllers import load_composite_controller_config +import os +import robosuite +import imageio +import numpy as np +from tqdm import tqdm +from termcolor import colored + + +def create_env( + env_name, + # robosuite-related configs + robots="PandaOmron", + camera_names=[ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ], + camera_widths=128, + camera_heights=128, + seed=None, + render_onscreen=False, + # robocasa-related configs + obj_instance_split=None, + generative_textures=None, + randomize_cameras=False, + layout_and_style_ids=None, + layout_ids=None, + style_ids=None, +): + controller_config = load_composite_controller_config( + controller=None, + robot=robots if isinstance(robots, str) else robots[0], + ) + + env_kwargs = dict( + env_name=env_name, + robots=robots, + controller_configs=controller_config, + camera_names=camera_names, + camera_widths=camera_widths, + camera_heights=camera_heights, + has_renderer=render_onscreen, + has_offscreen_renderer=(not render_onscreen), + ignore_done=True, + use_object_obs=True, + use_camera_obs=(not render_onscreen), + camera_depths=False, + seed=seed, + obj_instance_split=obj_instance_split, + generative_textures=generative_textures, + randomize_cameras=randomize_cameras, + layout_and_style_ids=layout_and_style_ids, + layout_ids=layout_ids, + style_ids=style_ids, + translucent_robot=False, + ) + + env = robosuite.make(**env_kwargs) + return env + + +def run_random_rollouts(env, num_rollouts, num_steps, video_path=None): + video_writer = None + if video_path is not None: + video_writer = imageio.get_writer(video_path, fps=20) + + info = {} + num_success_rollouts = 0 + for rollout_i in tqdm(range(num_rollouts)): + obs = env.reset() + for step_i in range(num_steps): + # sample and execute random action + action = np.random.uniform(low=env.action_spec[0], high=env.action_spec[1]) + obs, _, _, _ = env.step(action) + + if video_writer is not None: + video_img = env.sim.render( + height=512, width=768, camera_name="robot0_agentview_center" + )[::-1] + video_writer.append_data(video_img) + + if env._check_success(): + num_success_rollouts += 1 + break + + if video_writer is not None: + video_writer.close() + print(colored(f"Saved video of rollouts to {video_path}", color="yellow")) + + info["num_success_rollouts"] = num_success_rollouts + + return info + + +if __name__ == "__main__": + # select random task to run rollouts for + env_name = np.random.choice( + list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS) + ) + env = create_eval_env(env_name=env_name) + info = run_random_rollouts( + env, num_rollouts=3, num_steps=100, video_path="/tmp/test.mp4" + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/eval_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/eval_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..2c87b3631bd659ee837db515ea6e47c1643d0bd2 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/eval_utils.py @@ -0,0 +1,103 @@ +from robocasa.utils.dataset_registry import ( + get_ds_path, + SINGLE_STAGE_TASK_DATASETS, + MULTI_STAGE_TASK_DATASETS, +) +from robocasa.scripts.playback_dataset import get_env_metadata_from_dataset +from robosuite import load_controller_config +import os +import robosuite +import imageio +import numpy as np +from tqdm import tqdm +from termcolor import colored + + +def create_eval_env( + env_name, + # robosuite-related configs + robots="PandaMobile", + controllers="OSC_POSE", + camera_names=[ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ], + camera_widths=128, + camera_heights=128, + seed=None, + # robocasa-related configs + obj_instance_split="B", + generative_textures=None, + randomize_cameras=False, + layout_and_style_ids=((1, 1), (2, 2), (4, 4), (6, 9), (7, 10)), +): + controller_configs = load_controller_config(default_controller=controllers) + + env_kwargs = dict( + env_name=env_name, + robots=robots, + controller_configs=controller_configs, + camera_names=camera_names, + camera_widths=camera_widths, + camera_heights=camera_heights, + has_renderer=False, + has_offscreen_renderer=True, + ignore_done=True, + use_object_obs=True, + use_camera_obs=True, + camera_depths=False, + seed=seed, + obj_instance_split=obj_instance_split, + generative_textures=generative_textures, + randomize_cameras=randomize_cameras, + layout_and_style_ids=layout_and_style_ids, + translucent_robot=False, + ) + + env = robosuite.make(**env_kwargs) + return env + + +def run_random_rollouts(env, num_rollouts, num_steps, video_path=None): + video_writer = None + if video_path is not None: + video_writer = imageio.get_writer(video_path, fps=20) + + info = {} + num_success_rollouts = 0 + for rollout_i in tqdm(range(num_rollouts)): + obs = env.reset() + for step_i in range(num_steps): + # sample and execute random action + action = np.random.uniform(low=env.action_spec[0], high=env.action_spec[1]) + obs, _, _, _ = env.step(action) + + if video_writer is not None: + video_img = env.sim.render( + height=512, width=512, camera_name="robot0_agentview_center" + )[::-1] + video_writer.append_data(video_img) + + if env._check_success(): + num_success_rollouts += 1 + break + + if video_writer is not None: + video_writer.close() + print(colored(f"Saved video of rollouts to {video_path}", color="yellow")) + + info["num_success_rollouts"] = num_success_rollouts + + return info + + +if __name__ == "__main__": + # select random task to run rollouts for + env_name = np.random.choice( + list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS) + ) + env = create_eval_env(env_name=env_name) + info = run_random_rollouts( + env, num_rollouts=3, num_steps=100, video_path="/tmp/test.mp4" + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..03d3d426d6f296b0ca406cf8cc5ec2605a9bbb73 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/__init__.py @@ -0,0 +1,4 @@ +from .gymnasium_basic import RoboCasaEnv # noqa: F401 +from .gymnasium_groot import GrootRoboCasaEnv # noqa: F401 + +# from .gymnasium_gearbc import GearBCRoboCasaEnv # noqa: F401 diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/gymnasium_basic.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/gymnasium_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..c3c200c7823e3c5d2f6cb8a19367cda3c2b3931d --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/gymnasium_basic.py @@ -0,0 +1,309 @@ +import datetime, uuid +from copy import deepcopy +import gymnasium as gym +import numpy as np +import os +import robocasa # we need this to register environments # noqa: F401 +import robosuite +from gymnasium import spaces +from robocasa.environments.kitchen.kitchen import Kitchen +from robocasa.models.robots import ( + GROOT_ROBOCASA_ENVS_GR1_ARMS_ONLY, + GROOT_ROBOCASA_ENVS_GR1_ARMS_AND_WAIST, + GROOT_ROBOCASA_ENVS_GR1_FIXED_LOWER_BODY, + gather_robot_observations, + make_key_converter, +) +from robosuite.controllers import load_composite_controller_config +from robosuite.controllers.parts.arm.osc import OperationalSpaceController +from robosuite.controllers.composite.composite_controller import HybridMobileBase +from robosuite.environments.base import REGISTERED_ENVS + + +ALLOWED_LANGUAGE_CHARSET = ( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.\n\t[]{}()!?'_:" +) + + +def create_env_robosuite( + env_name, + # robosuite-related configs + robots="PandaOmron", + controller_configs=None, + camera_names=[ + "egoview", + "robot0_eye_in_left_hand", + "robot0_eye_in_right_hand", + ], + camera_widths=128, + camera_heights=128, + enable_render=True, + seed=None, + # robocasa-related configs + obj_instance_split=None, + generative_textures=None, + randomize_cameras=False, + layout_and_style_ids=None, + layout_ids=None, + style_ids=None, +): + if controller_configs is None: + controller_configs = load_composite_controller_config( + controller=None, + robot=robots if isinstance(robots, str) else robots[0], + ) + env_kwargs = dict( + env_name=env_name, + robots=robots, + controller_configs=controller_configs, + camera_names=camera_names, + camera_widths=camera_widths, + camera_heights=camera_heights, + has_renderer=False, + has_offscreen_renderer=enable_render, + ignore_done=True, + use_object_obs=True, + use_camera_obs=enable_render, + camera_depths=False, + seed=seed, + translucent_robot=False, + ) + env_class = REGISTERED_ENVS[env_name] + if issubclass(env_class, Kitchen): + env_kwargs.update( + { + "layout_ids": None, + "style_ids": None, + "layout_and_style_ids": [[1, 1], [2, 2], [4, 4], [6, 9], [7, 10]], + "obj_instance_split": "B", + "generative_textures": None, + "randomize_cameras": False, + } + ) + + env = robosuite.make(**env_kwargs) + return env, env_kwargs + + +class RoboCasaEnv(gym.Env): + def __init__( + self, + env_name=None, + robots_name=None, + camera_names=None, + camera_widths=None, + camera_heights=None, + enable_render=True, + dump_rollout_dataset_dir=None, + **kwargs, # Accept additional kwargs + ): + self.key_converter = make_key_converter(robots_name) + ( + _, + camera_names, + default_camera_widths, + default_camera_heights, + ) = self.key_converter.get_camera_config() + + if camera_widths is None: + camera_widths = default_camera_widths + if camera_heights is None: + camera_heights = default_camera_heights + + if isinstance(camera_widths, int): + camera_widths = [camera_widths] * len(camera_names) + if isinstance(camera_heights, int): + camera_heights = [camera_heights] * len(camera_names) + + controller_configs = load_composite_controller_config( + controller=None, + robot=robots_name.split("_")[0], + ) + if ( + robots_name in GROOT_ROBOCASA_ENVS_GR1_ARMS_ONLY + or robots_name in GROOT_ROBOCASA_ENVS_GR1_ARMS_AND_WAIST + or robots_name in GROOT_ROBOCASA_ENVS_GR1_FIXED_LOWER_BODY + ): + controller_configs["type"] = "BASIC" + controller_configs["composite_controller_specific_configs"] = {} + controller_configs["control_delta"] = False + + self.env, self.env_kwargs = create_env_robosuite( + env_name=env_name, + robots=robots_name.split("_"), + controller_configs=controller_configs, + camera_names=camera_names, + camera_widths=camera_widths, + camera_heights=camera_heights, + enable_render=enable_render, + **kwargs, # Forward kwargs to create_env_robosuite + ) + + # TODO: the following info should be output by grootrobocasa + self.camera_names = camera_names + self.camera_widths = camera_widths + self.camera_heights = camera_heights + self.enable_render = enable_render + self.render_obs_key = f"{camera_names[0]}_image" + self.render_cache = None + + # setup spaces + action_space = spaces.Dict() + for robot in self.env.robots: + cc = robot.composite_controller + pf = robot.robot_model.naming_prefix + for part_name, controller in cc.part_controllers.items(): + min_value, max_value = -1, 1 + start_idx, end_idx = cc._action_split_indexes[part_name] + shape = [end_idx - start_idx] + this_space = spaces.Box( + low=min_value, high=max_value, shape=shape, dtype=np.float32 + ) + action_space[f"{pf}{part_name}"] = this_space + if isinstance(cc, HybridMobileBase): + this_space = spaces.Discrete(2) + action_space[f"{pf}base_mode"] = this_space + + action_space = spaces.Dict(action_space) + self.action_space = action_space + + obs = ( + self.env.viewer._get_observations(force_update=True) + if self.env.viewer_get_obs + else self.env._get_observations(force_update=True) + ) + obs.update(gather_robot_observations(self.env)) + observation_space = spaces.Dict() + for obs_name, obs_value in obs.items(): + shape = list(obs_value.shape) + if obs_name.endswith("_image"): + continue + min_value, max_value = -1, 1 + this_space = spaces.Box( + low=min_value, high=max_value, shape=shape, dtype=np.float32 + ) + observation_space[obs_name] = this_space + + for camera_name, camera_width, camera_height in zip(camera_names, camera_widths, camera_heights): + shape = [camera_height, camera_width, 3] + this_space = spaces.Box(low=0, high=255, shape=shape, dtype=np.uint8) + observation_space[f"{camera_name}_image"] = this_space + + observation_space["language"] = spaces.Text( + max_length=256, charset=ALLOWED_LANGUAGE_CHARSET + ) + + self.observation_space = observation_space + + self.dump_rollout_dataset_dir = dump_rollout_dataset_dir + + def begin_rollout_dataset_dump(self): + if self.dump_rollout_dataset_dir is not None: + groot_env_meta = dict( + env_name=self.env_kwargs["env_name"], + env_version=robosuite.__version__, + type=1, + env_kwargs=deepcopy(self.env_kwargs), + ) + groot_dir = os.path.join( + self.dump_rollout_dataset_dir, + self.env_kwargs["env_name"] + + "_" + + "_".join(robot.name for robot in self.env.robots) + + "_Env", + f"{datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')}-{str(uuid.uuid4())[:8]}", + ) + if not os.path.exists(groot_dir): + os.makedirs(groot_dir, exist_ok=True) + + def process_rollout_dataset_dump_before_step(self, env_action): + pass + + def process_rollout_dataset_dump_after_step(self, env_action): + pass + + def complete_rollout_dataset_dump(self): + pass + + def get_basic_observation(self, raw_obs): + raw_obs.update(gather_robot_observations(self.env)) + + # Image are in (H, W, C), flip it upside down + def process_img(img): + return np.copy(img[::-1, :, :]) + + for obs_name, obs_value in raw_obs.items(): + if obs_name.endswith("_image"): + # image observations + raw_obs[obs_name] = process_img(obs_value) + else: + # non-image observations + raw_obs[obs_name] = obs_value.astype(np.float32) + + # Return black image if rendering is disabled + if not self.enable_render: + for name, width, height in zip(self.camera_names, self.camera_widths, self.camera_heights): + raw_obs[f"{name}_image"] = np.zeros( + (height, width, 3), dtype=np.uint8 + ) + + self.render_cache = raw_obs[self.render_obs_key] + raw_obs["language"] = self.env.get_ep_meta().get("lang", "") + + return raw_obs + + def reset(self, seed=None, options=None): + np.random.seed(seed) + raw_obs = self.env.reset() + # return obs + obs = self.get_basic_observation(raw_obs) + + info = {} + info["success"] = False + info["intermediate_signals"] = {} + + self.complete_rollout_dataset_dump() + self.begin_rollout_dataset_dump() + + return obs, info + + def step(self, action_dict): + env_action = [] + for robot in self.env.robots: + cc = robot.composite_controller + pf = robot.robot_model.naming_prefix + action = np.zeros(cc.action_limits[0].shape) + for part_name, controller in cc.part_controllers.items(): + start_idx, end_idx = cc._action_split_indexes[part_name] + act = action_dict.pop(f"{pf}{part_name}") + action[start_idx:end_idx] = act + if isinstance(cc, HybridMobileBase): + action[-1] = action_dict.pop(f"{pf}base_mode") + env_action.append(action) + + assert len(action_dict) == 0, f"Unprocessed actions: {action_dict}" + env_action = np.concatenate(env_action) + + self.process_rollout_dataset_dump_before_step(env_action) + raw_obs, reward, done, info = self.env.step(env_action) + self.process_rollout_dataset_dump_after_step(env_action) + + obs = self.get_basic_observation(raw_obs) + + truncated = False + + info["success"] = reward > 0 + info["intermediate_signals"] = {} + if hasattr(self.env, "_get_intermediate_signals"): + info["intermediate_signals"] = self.env._get_intermediate_signals() + + return obs, reward, done, truncated, info + + def render(self): + if self.render_cache is None: + raise RuntimeError("Must run reset or step before render.") + return self.render_cache + + def close(self): + self.complete_rollout_dataset_dump() + self.env.close() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/gymnasium_groot.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/gymnasium_groot.py new file mode 100644 index 0000000000000000000000000000000000000000..92e0247c288da697faa995ca42d84568f3816628 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/gym_utils/gymnasium_groot.py @@ -0,0 +1,172 @@ +import sys +from typing import Any, Dict + +import cv2 +import numpy as np +from gymnasium import spaces +from gymnasium.envs.registration import register + +from robocasa.models.robots import GROOT_ROBOCASA_ENVS_ROBOTS +from .gymnasium_basic import ( + REGISTERED_ENVS, + RoboCasaEnv, +) + +ALLOWED_LANGUAGE_CHARSET = ( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,.\n\t[]{}()!?'_:" +) +FINAL_IMAGE_RESOLUTION = (256, 256) + + +class GrootRoboCasaEnv(RoboCasaEnv): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.observation_space = self.key_converter.deduce_observation_space(self.env) + mapped_names, _, _, _ = self.key_converter.get_camera_config() + for mapped_name in mapped_names: + self.observation_space[mapped_name] = spaces.Box( + low=0, high=255, shape=(*FINAL_IMAGE_RESOLUTION, 3), dtype=np.uint8 + ) + if mapped_name == "video.ego_view_pad_res256_freq20": + self.observation_space[ + "video.ego_view_res1280x800_freq20" + ] = spaces.Box( + low=0, high=255, shape=(800, 1280, 3), dtype=np.uint8 + ) + self.observation_space[ + "video.ego_view_bg_crop_pad_res256_freq20" + ] = spaces.Box( + low=0, high=255, shape=(*FINAL_IMAGE_RESOLUTION, 3), dtype=np.uint8 + ) + if mapped_name in ["video.res256_image_side_0", "video.res256_image_side_1", "video.res256_image_wrist_0"]: + self.observation_space[ + mapped_name.replace("256", "512") + ] = spaces.Box( + low=0, high=255, shape=(512, 512, 3), dtype=np.uint8 + ) + self.observation_space[ + "annotation.human.action.task_description" + ] = spaces.Text(max_length=256, charset=ALLOWED_LANGUAGE_CHARSET) + self.action_space = self.key_converter.deduce_action_space(self.env) + + self.verbose = False + for k, v in self.observation_space.items(): + self.verbose and print("{OBS}", k, v) + for k, v in self.action_space.items(): + self.verbose and print("{ACTION}", k, v) + + @staticmethod + def process_img(img): + h, w, _ = img.shape + if h != w: + dim = max(h, w) + y_offset = (dim - h) // 2 + x_offset = (dim - w) // 2 + img = np.pad(img, ((y_offset, y_offset), (x_offset, x_offset), (0, 0))) + h, w = dim, dim + if (h, w) != FINAL_IMAGE_RESOLUTION: + img = cv2.resize(img, FINAL_IMAGE_RESOLUTION, cv2.INTER_AREA) + return np.copy(img) + + @staticmethod + def process_img_cotrain(img): + assert img.shape[0] == 800 and img.shape[1] == 1280 + + oh, ow = 256, 256 + crop = (310, 770, 110, 1130) + img = img[crop[0] : crop[1], crop[2] : crop[3]] + + img_resized = cv2.resize(img, (720, 480), cv2.INTER_AREA) + width_pad = (img_resized.shape[1] - img_resized.shape[0]) // 2 + img_pad = np.pad( + img_resized, + ((width_pad, width_pad), (0, 0), (0, 0)), + mode="constant", + constant_values=0, + ) + img_resized = cv2.resize(img_pad, (oh, ow), cv2.INTER_AREA) + return img_resized + + def get_groot_observation(self, raw_obs): + obs = {} + temp_obs = self.key_converter.map_obs(raw_obs) + for k, v in temp_obs.items(): + if k.startswith("hand.") or k.startswith("body."): + obs["state." + k[5:]] = v + else: + raise ValueError(f"Unknown key: {k}") + mapped_names, camera_names, _, _ = self.key_converter.get_camera_config() + for mapped_name, camera_name in zip(mapped_names, camera_names): + obs[mapped_name] = GrootRoboCasaEnv.process_img( + raw_obs[camera_name + "_image"] + ) + if mapped_name == "video.ego_view_pad_res256_freq20": + obs[ + "video.ego_view_res1280x800_freq20" + ] = np.copy(raw_obs[camera_name + "_image"]) + obs[ + "video.ego_view_bg_crop_pad_res256_freq20" + ] = GrootRoboCasaEnv.process_img_cotrain( + raw_obs[camera_name + "_image"] + ) + if mapped_name in ["video.res256_image_side_0", "video.res256_image_side_1", "video.res256_image_wrist_0"]: + obs[ + mapped_name.replace("256", "512") + ] = np.copy(raw_obs[camera_name + "_image"]) + obs["annotation.human.action.task_description"] = raw_obs["language"] + return obs + + def reset(self, seed=None, options=None): + raw_obs, info = super().reset(seed=seed, options=options) + obs = self.get_groot_observation(raw_obs) + return obs, info + + def step(self, action): + for k, v in action.items(): + self.verbose and print("", k, v) + + action = self.key_converter.unmap_action(action) + raw_obs, reward, terminated, truncated, info = super().step(action) + obs = self.get_groot_observation(raw_obs) + + for k, v in obs.items(): + self.verbose and print("", k, v.shape if k.startswith("video.") else v) + self.verbose = False + + return obs, reward, terminated, truncated, info + + +def create_grootrobocasa_env_class(env, robot, robot_alias): + class_name = f"{env}_{robot}_Env" + id_name = f"robocasa_{robot_alias}/{class_name}" + + env_class_type = type( + class_name, + (GrootRoboCasaEnv,), + { + "__init__": lambda self, **kwargs: super(self.__class__, self).__init__( + env_name=env, + robots_name=robot, + **kwargs, + ) + }, + ) + + current_module = sys.modules["robocasa.utils.gym_utils.gymnasium_groot"] + setattr(current_module, class_name, env_class_type) + register( + id=id_name, # Unique ID for the environment + entry_point=f"robocasa.utils.gym_utils.gymnasium_groot:{class_name}", # Path to your environment class + ) + + if robot_alias == "gr1_arms_waist_fourier_hands": + id_name = f"gr1_unified/{class_name}" + register( + id=id_name, # Unique ID for the environment + entry_point=f"robocasa.utils.gym_utils.gymnasium_groot:{class_name}", # Path to your environment class + ) + + +for ENV in REGISTERED_ENVS: + for ROBOT, ROBOT_ALIAS in GROOT_ROBOCASA_ENVS_ROBOTS.items(): + create_grootrobocasa_env_class(ENV, ROBOT, ROBOT_ALIAS) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4eb69cbf75946578508a38c3d3e60381e68c4091 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/__init__.py @@ -0,0 +1,3 @@ +import os + +assets_root = os.path.join(os.path.dirname(__file__), "assets") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/file_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/file_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..c246eb915655646febc9ee39d9611d1ef51f0d31 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/file_utils.py @@ -0,0 +1,35 @@ +from pathlib import Path + +# import robosuite_model_zoo +import os +import shutil + + +def get_ext(path): + return Path(path).suffix + + +def get_stem(path): + return Path(path).stem + + +def get_name(path): + return Path(path).name + + +def make_asset_path(base_asset_path, model_prefix, model_name): + if base_asset_path is None: + base_asset_path = os.path.join( + os.path.dirname(robosuite_model_zoo.__file__), + "assets_private", + ) + if model_prefix is not None: + base_asset_path = os.path.join(base_asset_path, model_prefix) + asset_path = os.path.join(base_asset_path, model_name) + + if os.path.exists(asset_path): + shutil.rmtree(asset_path) + + os.makedirs(asset_path) + + return asset_path diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/fixture_template.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/fixture_template.xml new file mode 100644 index 0000000000000000000000000000000000000000..6fece8297569124359e7a06a52348eb425c018bc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/fixture_template.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/install_vhacd.sh b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/install_vhacd.sh new file mode 100644 index 0000000000000000000000000000000000000000..f4bc7c6684b15f865b1bccc30edfca5f552d0a9c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/install_vhacd.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Install V-HACD 4.0. +# Adapted from https://github.com/kevinzakka/obj2mjcf/blob/main/install_vhacd.sh + +# Check that cmake is installed. +t=`which cmake` +if [ -z "$t" ]; then + echo "You need cmake to install V-HACD." 1>&2 + exit 1 +fi + +# Clone and build executable. +# TODO(kevin): Peg to a 4.0 release when available, see #113. +git clone https://github.com/kmammou/v-hacd.git +cd v-hacd/app +cmake CMakeLists.txt +cmake --build . + +# Add executable to /usr/local/bin. +sudo ln -s "$PWD/TestVHACD" /usr/local/bin/TestVHACD diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/log_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/log_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..31e05dd43ffa5931351888412b949eb2636e95ef --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/log_utils.py @@ -0,0 +1,46 @@ +import json +import numpy as np +from termcolor import colored +from copy import deepcopy +import os +import sys +import textwrap + + +class NumpyEncoder(json.JSONEncoder): + """ + Special json encoder for numpy types + From https://stackoverflow.com/a/49677241 + """ + + def default(self, obj): + if isinstance(obj, np.integer): + return int(obj) + elif isinstance(obj, np.floating): + return float(obj) + elif isinstance(obj, np.ndarray): + return obj.tolist() + return json.JSONEncoder.default(self, obj) + + +def maybe_log_info(message, log=False, color="yellow", indent=False): + if log: + if indent: + message = textwrap.indent(message, " " * 5) + print(colored(message, color)) + + +def save_meta(args, asset_path): + # get args + meta = vars(args) + + # get relative path of running script + script_path = os.path.abspath(sys.argv[0]) + path_list = script_path.split("/") + # idx = len(path_list) - 1 - path_list[::-1].index("robosuite_model_zoo") + # meta["script"] = "/".join(path_list[idx:]) + meta["cmd"] = "python " + " ".join(sys.argv) + + # save meta data + with open(os.path.join(asset_path, "meta.json"), "w") as outfile: + json.dump(meta, outfile, indent=4) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mjcf_gen_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mjcf_gen_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..fd6905bbf12f5dbc61d9964c43f4dd796ac373e8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mjcf_gen_utils.py @@ -0,0 +1,805 @@ +import numpy as np +import trimesh +import os +import robosuite +import xml.etree.ElementTree as ET +import shutil +import json +from termcolor import colored +from copy import deepcopy +from pathlib import Path + +# import robosuite_model_zoo +from robosuite.utils.transform_utils import mat2quat +import robocasa.utils.model_zoo.log_utils as LogUtils +import robocasa.utils.model_zoo.mtl_utils as MtlUtils + +from robosuite.utils.mjcf_utils import array_to_string, string_to_array + + +def parse_model_info( + model_path, + model_name, + coll_model_path, + asset_path, + obj_path=None, + verbose=False, + center=False, + prescale=False, + rot=None, + transform=None, +): + """ + Extract visual and collision geoms from + main model file and collision model file + """ + + LogUtils.maybe_log_info("Parsing input models...", log=verbose) + + geoms, textures, materials, transform = parse_model( + model_path, + model_name, + asset_path, + obj_path=obj_path, + center=center, + prescale=prescale, + rot=rot, + transform=transform, + # visual_only=(coll_model_path is None), + visual_only=True, + verbose=verbose, + ) + + coll_geoms, bb_info = parse_coll_model( + coll_model_path, + asset_path, + verbose=verbose, + transform=transform, + ) + + if coll_geoms is not None: + geoms = geoms + coll_geoms + + geoms_to_print = deepcopy(geoms) + for g in geoms_to_print: + if "rot_orig" in g: + del g["rot_orig"] + LogUtils.maybe_log_info( + "parsed geoms:\n" + + json.dumps(geoms_to_print, indent=4, cls=LogUtils.NumpyEncoder), + log=verbose, + indent=True, + ) + + model_info = dict( + geoms=geoms, + textures=textures, + materials=materials, + bb=bb_info, + ) + + return model_info + + +def parse_model( + model_path, + model_name, + asset_path, + obj_path=None, + visual_only=False, + center=False, + prescale=False, + rot=None, + transform=None, + verbose=False, +): + """ + Extract meshes from main model file + """ + + LogUtils.maybe_log_info( + "parsing (main) model: {}".format(model_path), + log=verbose, + indent=True, + ) + + # load the model + if obj_path is None: + obj_files = [ + os.path.join(model_path, name) + for name in os.listdir(model_path) + if name.endswith(".obj") + ] + obj_file = obj_files[0] + else: + obj_file = obj_path + + geoms, textures, materials = [], [], [] + vis_path = os.path.join(asset_path, "visual") + coll_path = os.path.join(asset_path, "collision") + + if not os.path.isdir(vis_path): + os.makedirs(vis_path) + if not os.path.isdir(coll_path): + os.makedirs(coll_path) + + resolver = trimesh.resolvers.FilePathResolver(os.path.dirname(obj_file)) + model = trimesh.load( + obj_file, + resolver=resolver, + split_object=True, + # group_material=True, + process=False, + maintain_order=False, + ) + + # If transform is passed as an argument, center and prescale must be False. Rotation is applied afterward regardless. + if transform is not None: + assert center is False and prescale is False + + if center: + mat_t = np.eye((4)) + center = (model.bounds[0] + model.bounds[1]) / 2 + mat_t[:3, 3] = -center + transform = mat_t + + if prescale: + mat_s = np.eye((4)) + scale_factor = 1 / np.max(model.bounds[1] - model.bounds[0]) + mat_s *= scale_factor + + if transform is None: + transform = mat_s + else: + transform = np.matmul(mat_s, transform) + + rot = rot or [] + for r in rot: + mat_R = np.eye(4) + + if r in ["x", "x90"]: + mat_R[:3, :3] = [[1, 0, 0], [0, 0, -1], [0, 1, 0]] + elif r in ["x180"]: + mat_R[:3, :3] = [[1, 0, 0], [0, -1, 0], [0, 0, -1]] + elif r in ["x270"]: + mat_R[:3, :3] = [[1, 0, 0], [0, 0, 1], [0, -1, 0]] + + elif r in ["y", "y90"]: + mat_R[:3, :3] = [[0, 0, 1], [0, 1, 0], [-1, 0, 0]] + elif r in ["y180"]: + mat_R[:3, :3] = [[-1, 0, 0], [0, 1, 0], [0, 0, -1]] + elif r in ["y270"]: + mat_R[:3, :3] = [[0, 0, -1], [0, 1, 0], [1, 0, 0]] + + elif r in ["z", "z90"]: + mat_R[:3, :3] = [[0, -1, 0], [1, 0, 0], [0, 0, 1]] + elif r in ["z180"]: + mat_R[:3, :3] = [[-1, 0, 0], [0, -1, 0], [0, 0, 1]] + elif r in ["z270"]: + mat_R[:3, :3] = [[0, 1, 0], [-1, 0, 0], [0, 0, 1]] + elif r in ["z60"]: + mat_R[:3, :3] = [ + [0.5000000, -0.8660254, 0.0000000], + [0.8660254, 0.5000000, 0.0000000], + [0, 0, 1], + ] + + else: + raise ValueError("Invalid choice of rotation {}".format(r)) + + if transform is None: + transform = mat_R + else: + transform = np.matmul(mat_R, transform) + + if transform is not None: + if isinstance(model, trimesh.base.Trimesh): + model.apply_transform(transform) + else: + for k in model.geometry: + model.geometry[k].apply_transform(transform) + + # debugging + # model.show() + # exit() + + mtls = MtlUtils.get_mtls(obj_file, work_dir=vis_path) + + """ + save mtl info. this section adapted from obj2mjf (credit: Kevin Zakka) + """ + for mtl in mtls: + if mtl.map_Kd is not None: + # Create the texture asset. + texture_path = Path(mtl.map_Kd) + texture = dict( + type="2d", + name=texture_path.stem, + file=os.path.join("visual", texture_path.name), + ) + # Reference the texture asset in a material asset. + material = dict( + name=mtl.name, + texture=texture_path.stem, + specular=mtl.mjcf_specular(), + shininess=mtl.mjcf_shininess(), + ) + + textures.append(texture) + materials.append(material) + else: + material = dict( + name=mtl.name, + specular=mtl.mjcf_specular(), + shininess=mtl.mjcf_shininess(), + rgba=mtl.mjcf_rgba(), + ) + materials.append(material) + + submodels = [] + + if isinstance(model, trimesh.base.Trimesh): + submodels = [(materials[-1]["name"], model)] + else: + submodels = list(model.geometry.items()) + + for (sm_i, (sm_name, sm)) in enumerate(submodels): + # ch_mesh = sm.convex_hull + # bb_mesh = sm.bounding_box_oriented + + # set visual geom path, copy to visual folder + # model_file = os.path.basename(model_path) + obj_name = os.path.basename(obj_file)[:-4] + vis_geom_path = os.path.join(vis_path, "{}_{}.obj".format(obj_name, sm_i)) + # shutil.copyfile( + # obj_file, + # vis_geom_path, + # ) + sm.export(vis_geom_path) + + vis_geom = dict( + obj_type="visual", + geom_type="mesh", + path=vis_geom_path, + name="{}_{}_vis".format(obj_name, sm_i), + material=sm_name, + # **get_bb_info(sm.bounding_box_oriented) + ) + geoms.append(vis_geom) + + if visual_only: + continue + + ch_mesh = sm.convex_hull + # bb_mesh = ch_mesh.bounding_box_oriented + + # obj_name = os.path.basename(obj_file)[:-3] + coll_geom_path = os.path.join(coll_path, "{}_{}.obj".format(obj_name, sm_i)) + coll_geom = dict( + obj_type="collision", + geom_type="mesh", + # path=os.path.join(coll_path, "{}_ch.stl".format(model_name)), + path=coll_geom_path, + name="{}_{}_coll".format(obj_name, sm_i), + **get_bb_info(ch_mesh.bounding_box_oriented), + ) + geoms.append(coll_geom) + ch_mesh.export(coll_geom["path"]) + + return geoms, textures, materials, transform + + +def parse_coll_model( + coll_model_path, + asset_path, + verbose=False, + transform=None, +): + """ + Extract list of primitive geoms from collision model file + """ + + if coll_model_path is None: + return None, None + + LogUtils.maybe_log_info( + "parsing collision model: {}".format(coll_model_path), + log=verbose, + indent=True, + ) + + # load the model + obj_files = [ + os.path.join(coll_model_path, name) + for name in os.listdir(coll_model_path) + if name.endswith(".obj") + ] + + geoms = [] + coll_path = os.path.join(asset_path, "collision") + + scene = trimesh.scene.scene.Scene() + + for obj_file in obj_files: + resolver = trimesh.resolvers.FilePathResolver(os.path.dirname(obj_file)) + model = trimesh.load(obj_file, resolver=resolver) + + if transform is not None: + model.apply_transform(transform) + model.export(obj_file) + + # ch_mesh = model.convex_hull + # bb_mesh = ch_mesh.bounding_box_oriented + + scene.add_geometry(model) + + if not os.path.isdir(coll_path): + os.makedirs(coll_path) + + # set visual geom path, copy to visual folder + # model_file = os.path.basename(model_path) + obj_name = os.path.basename(obj_file)[:-3] + coll_geom_path = os.path.join(coll_path, os.path.basename(obj_file)) + # shutil.copyfile( + # obj_file, + # coll_geom_path, + # ) + + # obj_name = os.path.basename(obj_file)[:-3] + coll_geom = dict( + obj_type="collision", + geom_type="mesh", + # path=os.path.join(coll_path, "{}_ch.stl".format(model_name)), + path=coll_geom_path, + name="{}_coll".format(obj_name), + # **get_bb_info(bb_mesh) + ) + geoms.append(coll_geom) + + bb_info = get_bb_info(scene.bounding_box) + + # f = open(coll_model_path, "r") + # lines = f.readlines() + # f.close() + + # geoms = [] + + # start_inds = [i for (i, line) in enumerate(lines) if line.startswith("o ")] + + # num_coll_meshes = 0 + # for start, end in zip(start_inds, start_inds[1:] + [len(lines)]): + # obj_lines = lines[start:end] + + # # filter out lines corresponding to faces + # obj_lines_filtered = [line for line in obj_lines if not line.startswith("f ")] + + # geom = dict() + + # tmp = tempfile.NamedTemporaryFile(suffix=".obj") + # with open(tmp.name, "w") as f: + # [f.write(line) for line in obj_lines_filtered] + + # mesh = trimesh.load(tmp.name) + + # bb_mesh = mesh.bounding_box_oriented + + # geom.update( + # obj_name=obj_lines[0], + # obj_type="collision", + # **get_bb_info(bb_mesh) + # ) + + # obj_type_substr = obj_lines_filtered[0][2:] + # if obj_type_substr.startswith("Cube"): + # geom_type = "box" + # elif obj_type_substr.startswith("Cylinder"): + # geom_type = "cylinder" + + # """ + # post-process size and orientation of cylinder + # """ + + # pos = geom["pos"] + # quat = geom["quat"] + # size = geom["size"] + + # T = bb_mesh.primitive.transform + + # trans_mesh = mesh.copy() + # trans_mesh.apply_transform(np.linalg.inv(T)) + + # V = np.array(trans_mesh.vertices) + # n = len(V) # number of vertices + # th = 1e-5 # threshold for checking vertices + + # upright_axis = None + # for idx in [0, 1, 2]: + # V = np.take(V, indices=np.argsort(V, axis=0)[:,idx], axis=0) + + # if np.std(V[:n//2,idx]) < th and np.std(V[-n//2:,idx]) < th: + # upright_axis = idx + + # assert upright_axis is not None + # circle_axes = np.delete(np.arange(3), upright_axis) + # assert np.abs(size[circle_axes][1] - size[circle_axes][0]) < 0.01, ( + # "Detected elliptic cylinder! " + # "Mujoco only accepts circular cylinders." + # ) + + # if upright_axis == 0: + # geom["quat"] = mat2quat( + # np.linalg.inv( + # np.matmul( + # np.array([ + # [0, 0, 1], + # [0, 1, 0], + # [-1, 0, 0], + # ]), + # np.linalg.inv(geom["rot_orig"]) + # ) + # ) + # )[[3,0,1,2]] + # elif upright_axis == 1: + # raise NotImplementedError + + # geom["size"] = [np.mean(size[circle_axes]), size[upright_axis]] + + # elif obj_type_substr.startswith("Sphere"): + # geom_type = "ellipsoid" + # else: + # raise ValueError( + # "Detected non-primitive object in collision model:", + # obj_lines_filtered[0] + # ) + + # geom["geom_type"] = geom_type + + # geoms.append(geom) + + return geoms, bb_info + + +def get_geom_element(model_name, geom_info, sc=1.0, show_if_coll_geom=False): + """ + Generate xml element for mjcf geom + """ + + if geom_info.get("hide", False): + return None + + elem = ET.Element("geom") + + elem.attrib["solimp"] = "0.998 0.998 0.001" + elem.attrib["solref"] = "0.001 1" + elem.attrib["density"] = "100" + elem.attrib["friction"] = "0.95 0.3 0.1" + + if geom_info["geom_type"] == "mesh": + elem.attrib["type"] = "mesh" + elem.attrib["mesh"] = geom_info["name"] + else: + raise NotImplementedError + elem.attrib["type"] = geom_info["geom_type"] + elem.attrib["pos"] = " ".join( + ["{:.5f}".format(v * sc) for v in geom_info["pos"]] + ) + elem.attrib["quat"] = " ".join(["{:.5f}".format(v) for v in geom_info["quat"]]) + size = geom_info["size"] + elem.attrib["size"] = " ".join(["{:.5f}".format(v * sc / 2) for v in size]) + + if geom_info["obj_type"] == "visual": + elem.attrib["conaffinity"] = "0" + elem.attrib["contype"] = "0" + elem.attrib["group"] = "1" + elem.attrib["material"] = geom_info.get("material", model_name) + elif geom_info["obj_type"] == "collision": + elem.attrib["group"] = "0" + # elem.attrib["condim"] = "4" + + if show_if_coll_geom: + elem.attrib["rgba"] = "0.8 0.8 0.8 0.3" + else: + elem.attrib["rgba"] = "0.8 0.8 0.8 0.0" + + return elem + + +def get_texture_element(texture_info): + elem = ET.Element("texture") + + for (k, v) in texture_info.items(): + elem.attrib[k] = str(v) + + return elem + + +def get_material_element(material_info): + elem = ET.Element("material") + + for (k, v) in material_info.items(): + elem.attrib[k] = str(v) + + return elem + + +def get_mesh_element(geom_info, sc=1.0): + """ + Generate xml element for mjcf mesh asset + """ + assert geom_info["geom_type"] == "mesh" + + if geom_info.get("hide", False): + return None + + elem = ET.Element("mesh") + + elem.attrib["file"] = "/".join(geom_info["path"].split("/")[-2:]) + elem.attrib["name"] = geom_info["name"] + elem.attrib["scale"] = "{sc} {sc} {sc}".format(sc=sc) + + return elem + + +def generate_mjcf( + asset_path, + model_name, + model_info, + sc=1.0, + texture_path=None, + hide_vis_geoms=False, + show_coll_geoms=False, + show_sites=False, + verbose=False, +): + """ + Generate mjcf model for object + """ + + LogUtils.maybe_log_info("Generating MJCF...", log=verbose) + + geoms = model_info["geoms"] + textures = model_info["textures"] + materials = model_info["materials"] + bb_info = model_info["bb"] + + ### for now, assume mtl doesn't contain texture #### + # texture_from_mtl = False + # if texture_path is None: + # # get the texture used in the mtl file + # mtl_path = model_path[:-3] + 'mtl' + # texture_dict = {} + # with open(mtl_path, "r") as f: + # for i, line in enumerate(f.readlines()): + # if len(line) > 1: + # key, value = line.split(" ", 1) + # texture_dict[key] = value.strip() + # + # if "map_Kd" in texture_dict: + # texture_path = texture_dict["map_Kd"] + # texture_from_mtl = True + + # load template xml + tree = ET.parse( + os.path.join(os.path.dirname(os.path.realpath(__file__)), "object_template.xml") + ) + root = tree.getroot() + + # set model name + root.attrib["model"] = model_name + + # add mesh assets + asset = root.find("asset") + for geom in geoms: + if geom["geom_type"] == "mesh": + mesh_elem = get_mesh_element(geom, sc=sc) + if mesh_elem is not None: + asset.append(mesh_elem) + + # update default texture and material assets + texture = asset.find("texture") + texture.attrib["name"] = texture.attrib["name"].replace("template", model_name) + if texture_path is not None: + texture.attrib["file"] = "/".join(texture_path.split("/")[-1:]) + else: + texture.attrib["file"] = os.path.join( + os.path.dirname(robosuite.__file__), "models/assets/textures/ceramic.png" + ) + material = asset.find("material") + for k in ["name", "texture"]: + material.attrib[k] = material.attrib[k].replace("template", model_name) + + # add textures + for texture in textures: + texture_elem = get_texture_element(texture) + if texture_elem is not None: + asset.append(texture_elem) + + # add materials + for material in materials: + material_elem = get_material_element(material) + if material_elem is not None: + asset.append(material_elem) + + # add geoms + worldbody = root.find("worldbody") + body = worldbody.find("body").find("body") + for geom in geoms: + if geom["obj_type"] == "visual" and hide_vis_geoms: + continue + + geom_elem = get_geom_element( + model_name, + geom, + sc=sc, + show_if_coll_geom=show_coll_geoms, + ) + if geom_elem is not None: + body.append(geom_elem) + + sites = worldbody.find("body").findall("site") + + if show_sites: + object_body = worldbody.find("body").find("body") + vis_site_strings = [ + """""", + """""", + """""", + ] + for s in vis_site_strings: + object_body.append(ET.fromstring(s)) + + # for debugging + vis_sites = object_body.findall("site") + sites = sites + vis_sites + + if bb_info is not None: + for site in sites: + if site.get("name") == "horizontal_radius_site": + pos = bb_info["pos"].copy() + pos[0] += bb_info["size"][0] / 2 + pos[1] += bb_info["size"][1] / 2 + pos = np.array([pos[0], pos[1], pos[2]]) + site.set("pos", array_to_string(pos * sc)) + elif site.get("name") == "bottom_site": + pos = bb_info["pos"].copy() + pos[2] -= bb_info["size"][2] / 2 + pos = np.array([pos[0], pos[1], pos[2]]) + site.set("pos", array_to_string(pos * sc)) + elif site.get("name") == "top_site": + pos = bb_info["pos"].copy() + pos[2] += bb_info["size"][2] / 2 + pos = np.array([pos[0], pos[1], pos[2]]) + site.set("pos", array_to_string(pos * sc)) + + # save xml for new model + mjcf_path = os.path.join(asset_path, "model.xml") + tree.write(mjcf_path, encoding="utf-8") + LogUtils.maybe_log_info( + "Wrote MJCF to: {}".format(mjcf_path), log=verbose, indent=True + ) + + # LogUtils.maybe_log_info( + # "\nTest generated MJCF with robosuite:\npython {base_path}/scripts/object_play.py --device spacemouse --mjcf_path {mjcf_path}".format( + # base_path=os.path.dirname(robosuite_model_zoo.__file__), + # mjcf_path=mjcf_path, + # ), + # log=True, + # color="green" + # ) + + return mjcf_path + + +def get_file_name_and_type(path): + """ + Extract name of object model file and file format + """ + split_name = os.path.basename(path).split(".") + assert len(split_name) == 2 + return split_name[0], split_name[1] + + +def get_bb_info(bb_mesh): + """ + Extract size, position, and orientation (quat) from bounding box mesh + """ + ext = np.array(bb_mesh.primitive.extents) + transform = np.array(bb_mesh.primitive.transform) + + center = transform[:-1, 3] + rot = transform[:3, :3] + quat = mat2quat(rot)[[3, 0, 1, 2]] + + return dict( + pos=center, + quat=quat, + size=ext, + rot_orig=rot, + ) + + +def decompose_convex( + filename, + work_dir, + # V-HACD params + max_output_convex_hulls=32, + voxel_resolution=100000, + volume_error_percent=1.0, + max_hull_vert_count=64, +): + """ + Adapted from https://github.com/kevinzakka/obj2mjcf/blob/main/obj2mjcf/_cli.py + """ + + _VHACD_EXECUTABLE = shutil.which("TestVHACD") + _VHACD_OUTPUTS = ["decomp.obj", "decomp.stl"] + + obj_file = filename.resolve() + + import tempfile + import subprocess + from pathlib import Path + import enum + + with tempfile.TemporaryDirectory() as tmpdirname: + prev_dir = os.getcwd() + os.chdir(tmpdirname) + + # Copy the obj file to the temporary directory. + shutil.copy(obj_file, tmpdirname) + + # Call V-HACD, suppressing output. + ret = subprocess.run( + [ + f"{_VHACD_EXECUTABLE}", + obj_file.name, + "-o", + "obj", + "-h", + f"{max_output_convex_hulls}", # max_output_convex_hulls + "-r", + f"{voxel_resolution}", # voxel_resolution + "-e", + f"{volume_error_percent}", # volume_error_percent + "-d", + f"{14}", # max_recursion_depth + "-s", + f"{int(not False)}", # disable_shrink_wrap + # "-f", + # f"{enum.auto().name.lower()}", # fill_mode.name.lower() + "-v", + f"{max_hull_vert_count}", # max_hull_vert_count + "-a", + f"{int(not False)}", # disable_async + "-l", + f"{2}", # min_edge_length + "-p", + f"{int(False)}", # split_hull + ], + # stdout=subprocess.DEVNULL, + # stderr=subprocess.STDOUT, + check=True, + ) + # if ret.returncode != 0: + # logging.error(f"V-HACD failed on {filename}") + # return False + + # Remove the original obj file and the V-HACD output files. + for name in _VHACD_OUTPUTS + [obj_file.name]: + file_to_delete = Path(tmpdirname) / name + if file_to_delete.exists(): + file_to_delete.unlink() + + os.chdir(prev_dir) + + # Get list of sorted collisions. + collisions = list(Path(tmpdirname).glob("*.obj")) + collisions.sort(key=lambda x: x.stem) + + os.makedirs(work_dir.resolve(), exist_ok=True) + + for i, filename in enumerate(collisions): + savename = str(work_dir / f"{obj_file.stem}_collision_{i}.obj") + shutil.move(str(filename), savename) + + return True diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mjcf_obj.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mjcf_obj.py new file mode 100644 index 0000000000000000000000000000000000000000..e54ebd8503dadb7c5d12cad88e4595636ce27333 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mjcf_obj.py @@ -0,0 +1,255 @@ +import os +import time +import numpy as np +import tempfile +import random +import string +import xml.etree.ElementTree as ET + +import robosuite + +from robosuite.models.objects import MujocoXMLObject +from robosuite.utils.mjcf_utils import array_to_string, string_to_array + +import robosuite.utils.transform_utils as T + +import robosuite_model_zoo + + +def postprocess_model_xml(xml_str): + """ + New version of postprocess model xml that only replaces robosuite file paths if necessary (otherwise + there is an error with the "max" operation), and also replaces robosuite-model-zoo file paths + if necessary. + """ + + path = os.path.split(robosuite.__file__)[0] + path_split = path.split("/") + + # replace mesh and texture file paths + tree = ET.fromstring(xml_str) + root = tree + asset = root.find("asset") + meshes = asset.findall("mesh") + textures = asset.findall("texture") + all_elements = meshes + textures + + for elem in all_elements: + old_path = elem.get("file") + if old_path is None: + continue + + old_path_split = old_path.split("/") + # maybe replace all paths to robosuite assets + check_lst = [ + loc for loc, val in enumerate(old_path_split) if val == "robosuite" + ] + if len(check_lst) > 0: + ind = max(check_lst) # last occurrence index + new_path_split = path_split + old_path_split[ind + 1 :] + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + # maybe replace all paths to robosuite model zoo assets + check_lst = [ + loc + for loc, val in enumerate(old_path_split) + if val == "robosuite-model-zoo-dev" + ] + if len(check_lst) > 0: + ind = max(check_lst) # last occurrence index + new_path_split = ( + os.path.split(robosuite_model_zoo.__file__)[0].split("/")[:-1] + + old_path_split[ind + 1 :] + ) + new_path = "/".join(new_path_split) + elem.set("file", new_path) + + return ET.tostring(root, encoding="utf8").decode("utf8") + + +class MJCFObject(MujocoXMLObject): + """ + Blender object with support for changing the scaling + """ + + def __init__( + self, + name, + mjcf_path, + scale=1.0, + solimp=(0.998, 0.998, 0.001), + solref=(0.001, 1), + density=100, + friction=(0.95, 0.3, 0.1), + margin=None, + rgba=None, + priority=None, + ): + # get scale in x, y, z + if isinstance(scale, float): + scale = [scale, scale, scale] + elif isinstance(scale, tuple) or isinstance(scale, list): + assert len(scale) == 3 + scale = tuple(scale) + else: + raise Exception("got invalid scale: {}".format(scale)) + scale = np.array(scale) + + self.solimp = solimp + self.solref = solref + self.density = density + self.friction = friction + self.margin = margin + + self.priority = priority + + self.rgba = rgba + + # read default xml + xml_path = mjcf_path + folder = os.path.dirname(xml_path) + tree = ET.parse(xml_path) + root = tree.getroot() + + # modify mesh scales + asset = root.find("asset") + meshes = asset.findall("mesh") + for mesh in meshes: + # if a scale already exists, multiply the scales + scale_to_set = scale + existing_scale = mesh.get("scale") + if existing_scale is not None: + scale_to_set = string_to_array(existing_scale) * scale + mesh.set("scale", array_to_string(scale_to_set)) + + # modify sites for collision (assumes we can just scale up the locations - may or may not work) + for n in ["bottom_site", "top_site", "horizontal_radius_site"]: + site = root.find("worldbody/body/site[@name='{}']".format(n)) + pos = string_to_array(site.get("pos")) + pos = scale * pos + site.set("pos", array_to_string(pos)) + + """ + # disable collision geoms + worldbody = root.find("worldbody") + from robosuite.utils.mjcf_utils import find_elements + geoms = find_elements( + root=worldbody, + tags="geom", + attribs={"group": "0"}, + return_first=False + ) + for g in geoms: + # g.set("group", "1") + g.set("mass", "0.0001") + g.set("conaffinity", "2") + g.set("contype", "2") + """ + + # write modified xml (and make sure to postprocess any paths just in case) + xml_str = ET.tostring(root, encoding="utf8").decode("utf8") + xml_str = postprocess_model_xml(xml_str) + time_str = str(time.time()).replace(".", "_") + new_xml_path = os.path.join(folder, "{}_{}.xml".format(time_str, os.getpid())) + f = open(new_xml_path, "w") + f.write(xml_str) + f.close() + # print(f"Write to {new_xml_path}") + + # initialize object with new xml we wrote + super().__init__( + # xml_path_completion("objects/{}.xml".format(obj_name)), + fname=new_xml_path, + name=name, + joints=[dict(type="free", damping="0.0005")], + # joints=None, + obj_type="all", + duplicate_collision_geoms=False, + ) + + # clean up xml - we don't need it anymore + if os.path.exists(new_xml_path): + os.remove(new_xml_path) + + def _get_geoms(self, root, _parent=None): + """ + Helper function to recursively search through element tree starting at @root and returns + a list of (parent, child) tuples where the child is a geom element + + Args: + root (ET.Element): Root of xml element tree to start recursively searching through + _parent (ET.Element): Parent of the root element tree. Should not be used externally; only set + during the recursive call + + Returns: + list: array of (parent, child) tuples where the child element is a geom type + """ + geom_pairs = super(MJCFObject, self)._get_geoms(root=root, _parent=_parent) + + # modify geoms according to the attributes + for i, (parent, element) in enumerate(geom_pairs): + element.set("solref", array_to_string(self.solref)) + element.set("solimp", array_to_string(self.solimp)) + element.set("density", str(self.density)) + element.set("friction", array_to_string(self.friction)) + if self.margin is not None: + element.set("margin", str(self.margin)) + + if (self.rgba is not None) and (element.get("group") == "1"): + element.set("rgba", array_to_string(self.rgba)) + + if self.priority is not None: + # set high priorit + element.set("priority", str(self.priority)) + + return geom_pairs + + @property + def horizontal_radius(self): + horizontal_radius_site = self.worldbody.find( + "./body/site[@name='{}horizontal_radius_site']".format(self.naming_prefix) + ) + site_values = string_to_array(horizontal_radius_site.get("pos")) + return np.linalg.norm(site_values[0:2]) + + def get_bbox_points(self, trans=None, rot=None): + """ + Get the full 8 bounding box points of the object + rot: a rotation matrix + """ + bbox_offsets = [] + + bottom_offset = self.bottom_offset + top_offset = self.top_offset + horizontal_radius_site = self.worldbody.find( + "./body/site[@name='{}horizontal_radius_site']".format(self.naming_prefix) + ) + horiz_radius = string_to_array(horizontal_radius_site.get("pos"))[:2] + + center = np.mean([bottom_offset, top_offset], axis=0) + half_size = [horiz_radius[0], horiz_radius[1], top_offset[2] - center[2]] + + # center = np.array([0, 0, 0]) + # half_size = np.array([0.01, 0.01, 0.01]) + + bbox_offsets = [ + center + half_size * np.array([-1, -1, -1]), # p0 + center + half_size * np.array([1, -1, -1]), # px + center + half_size * np.array([-1, 1, -1]), # py + center + half_size * np.array([-1, -1, 1]), # pz + center + half_size * np.array([1, 1, 1]), + center + half_size * np.array([-1, 1, 1]), + center + half_size * np.array([1, -1, 1]), + center + half_size * np.array([1, 1, -1]), + ] + + if trans is None: + trans = np.array([0, 0, 0]) + if rot is not None: + rot = T.quat2mat(rot) + else: + rot = np.eye(3) + + points = [(np.matmul(rot, p) + trans) for p in bbox_offsets] + return points diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mtl_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mtl_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..d5176049778be9fbfe2ace60d374a93128740146 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/mtl_utils.py @@ -0,0 +1,198 @@ +""" +Much of this code is directly copied from obj2mjcf: +https://github.com/kevinzakka/obj2mjcf/blob/main/obj2mjcf/_cli.py + +Credit: Kevin Zakka +""" + +from dataclasses import dataclass +from typing import Optional, Sequence +from PIL import Image +from pathlib import Path + +import os +import shutil + +# MTL fields relevant to MuJoCo. +_MTL_FIELDS = ( + # Ambient, diffuse and specular colors. + "Ka", + "Kd", + "Ks", + # d or Tr are used for the rgba transparency. + "d", + "Tr", + # Shininess. + "Ns", + # References a texture file. + "map_Kd", +) + +# Character used to denote a comment in an MTL file. +_MTL_COMMENT_CHAR = "#" + + +@dataclass +class Material: + name: str + Ka: Optional[str] = None + Kd: Optional[str] = None + Ks: Optional[str] = None + d: Optional[str] = None + Tr: Optional[str] = None + Ns: Optional[str] = None + map_Kd: Optional[str] = None + + @staticmethod + def from_string(lines: Sequence[str]) -> "Material": + """Construct a Material object from a string.""" + attrs = {"name": lines[0].split(" ")[1].strip()} + for line in lines[1:]: + for attr in _MTL_FIELDS: + if line.startswith(attr): + elems = line.split(" ")[1:] + elems = [elem for elem in elems if elem != ""] + attrs[attr] = " ".join(elems) + break + return Material(**attrs) + + def mjcf_rgba(self) -> str: + Kd = self.Kd or "1.0 1.0 1.0" + if self.d is not None: # alpha + alpha = self.d + elif self.Tr is not None: # 1 - alpha + alpha = str(1.0 - float(self.Tr)) + else: + alpha = "1.0" + # alpha = "1.0" + # TODO(kevin): Figure out how to use Ka for computing rgba. + return f"{Kd} {alpha}" + + def mjcf_shininess(self) -> str: + if self.Ns is not None: + # Normalize Ns value to [0, 1]. Ns values normally range from 0 to 1000. + Ns = float(self.Ns) / 1_000 + else: + Ns = 0.5 + return f"{Ns}" + + def mjcf_specular(self) -> str: + if self.Ks is not None: + # Take the average of the specular RGB values. + Ks = sum(list(map(float, self.Ks.split(" ")))) / 3 + else: + Ks = 0.5 + return f"{Ks}" + + +def get_mtls(filename, work_dir): + filename = Path(filename) + work_dir = Path(work_dir) + + process_mtl = False + with open(filename, "r") as f: + for line in f.readlines(): + if line.startswith("mtllib"): # Deals with commented out lines. + process_mtl = True + name = line.split()[1] + break + + sub_mtls: List[List[str]] = [] + mtls: List[Material] = [] + if process_mtl: + # Make sure the MTL file exists. The MTL filepath is relative to the OBJ's. + mtl_filename = filename.parent / name + if not mtl_filename.exists(): + raise RuntimeError( + f"The MTL file {mtl_filename.resolve()} referenced in the OBJ file " + f"{filename} does not exist" + ) + # logging.info(f"Found MTL file: {mtl_filename}") + + # Parse the MTL file into separate materials. + with open(mtl_filename, "r") as f: + lines = f.readlines() + # Remove comments. + lines = [line for line in lines if not line.startswith(_MTL_COMMENT_CHAR)] + # Remove empty lines. + lines = [line for line in lines if line.strip()] + # Remove trailing whitespace. + lines = [line.strip() for line in lines] + # Split at each new material definition. + for line in lines: + if line.startswith("newmtl"): + sub_mtls.append([]) + sub_mtls[-1].append(line) + for sub_mtl in sub_mtls: + mtls.append(Material.from_string(sub_mtl)) + + # Process each material. + for mtl in mtls: + # logging.info(f"Found material: {mtl.name}") + if mtl.map_Kd is not None: + texture_path = Path(mtl.map_Kd) + texture_name = texture_path.name + src_filename = filename.parent / texture_path + if not src_filename.exists(): + raise RuntimeError( + f"The texture file {src_filename} referenced in the MTL file " + f"{mtl.name} does not exist" + ) + # We want a flat directory structure in work_dir. + dst_filename = work_dir / texture_name + shutil.copy(src_filename, dst_filename) + # MuJoCo only supports PNG textures ¯\_(ツ)_/¯. + if texture_path.suffix.lower() in [".jpg", ".jpeg"]: + image = Image.open(dst_filename) + os.remove(dst_filename) + dst_filename = (work_dir / texture_path.stem).with_suffix(".png") + image.save(dst_filename) + texture_name = dst_filename.name + mtl.map_Kd = texture_name + resize_texture(dst_filename, 1.0) + # logging.info("Done processing MTL file") + + return mtls + + +def resize_texture(filename: Path, resize_percent) -> None: + """Resize a texture to a percentage of its original size.""" + if resize_percent == 1.0: + return + image = Image.open(filename) + new_width = int(image.size[0] * resize_percent) + new_height = int(image.size[1] * resize_percent) + logging.info(f"Resizing {filename} to {new_width}x{new_height}") + image = image.resize((new_width, new_height), Image.LANCZOS) + image.save(filename) + + +def get_image_paths(mtl_path): + image_paths = [] + + # Parse the MTL file into separate materials. + with open(mtl_path, "r") as f: + lines = f.readlines() + # Remove comments. + lines = [line for line in lines if not line.startswith(_MTL_COMMENT_CHAR)] + # Remove empty lines. + lines = [line for line in lines if line.strip()] + # Remove trailing whitespace. + lines = [line.strip() for line in lines] + # Split at each new material definition. + + sub_mtls = [] + + for line in lines: + if line.startswith("newmtl"): + sub_mtls.append([]) + sub_mtls[-1].append(line) + for sub_mtl in sub_mtls: + # print(sub_mtl) + + path = Material.from_string(sub_mtl).map_Kd + + if path is not None: + image_paths.append(path) + + return image_paths diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/object_play_env.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/object_play_env.py new file mode 100644 index 0000000000000000000000000000000000000000..63b5598af73ea5f772831d66669c639984884823 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/object_play_env.py @@ -0,0 +1,250 @@ +import numpy as np + +from robosuite.environments.manipulation.single_arm_env import SingleArmEnv +from robosuite.models.arenas import TableArena +from robosuite.models.tasks import ManipulationTask +from robosuite.utils.placement_samplers import UniformRandomSampler + +from robocasa.utils.model_zoo.mjcf_obj import MJCFObject +from robosuite.models.objects import BoxObject + +import robosuite.utils.transform_utils as T + + +class ObjectPlayEnv(SingleArmEnv): + def __init__( + self, + robots, + obj_mjcf_path, + obj_scale=1.0, + env_configuration="default", + controller_configs=None, + gripper_types="default", + initialization_noise="default", + table_full_size=(0.8, 0.8, 0.05), + table_friction=(1.0, 5e-3, 1e-4), + use_camera_obs=True, + use_object_obs=True, + reward_scale=1.0, + reward_shaping=False, + placement_initializer=None, + has_renderer=False, + has_offscreen_renderer=True, + render_camera="frontview", + render_collision_mesh=False, + render_visual_mesh=True, + render_gpu_device_id=-1, + control_freq=20, + horizon=1000, + ignore_done=False, + hard_reset=True, + camera_names="agentview", + camera_heights=256, + camera_widths=256, + camera_depths=False, + x_range=(-0.03, 0.03), + y_range=(-0.03, 0.03), + rotation=None, + num_objects=1, + ): + # settings for table top + self.table_full_size = table_full_size + self.table_friction = table_friction + self.table_offset = np.array((0, 0, 0.8)) + + # reward configuration + self.reward_scale = reward_scale + self.reward_shaping = reward_shaping + + # whether to use ground-truth object states + self.use_object_obs = use_object_obs + + # object placement initializer + self.placement_initializer = placement_initializer + + self._obj_mjcf_path = obj_mjcf_path + self._obj_scale = obj_scale + self._x_range = x_range + self._y_range = y_range + self._rotation = rotation + self._num_objects = num_objects + + self._cam_configs = dict( + agentview=dict( + pos=[0, -0.5, 1.35], + quat=T.convert_quat( + np.array([0.3826834, 0, 0, 0.9238795]), + to="wxyz", + ), + ), + ) + + super().__init__( + robots=robots, + env_configuration=env_configuration, + controller_configs=controller_configs, + mount_types="default", + gripper_types=gripper_types, + initialization_noise=initialization_noise, + use_camera_obs=use_camera_obs, + has_renderer=has_renderer, + has_offscreen_renderer=has_offscreen_renderer, + render_camera=render_camera, + render_collision_mesh=render_collision_mesh, + render_visual_mesh=render_visual_mesh, + render_gpu_device_id=render_gpu_device_id, + control_freq=control_freq, + horizon=horizon, + ignore_done=ignore_done, + hard_reset=hard_reset, + camera_names=camera_names, + camera_heights=camera_heights, + camera_widths=camera_widths, + camera_depths=camera_depths, + ) + + def reward(self, action=None): + reward = 0.0 + + return reward + + def _load_model(self): + """ + Loads an xml model, puts it in self.model + """ + super()._load_model() + + # Adjust base pose accordingly + # xpos = self.robots[0].robot_model.base_xpos_offset["table"](self.table_full_size[0]) + # self.robots[0].robot_model.set_base_xpos(xpos) + ### logic copied from kitchen.py to rotate robot around ### + for robot, rotation, offset in zip(self.robots, (-np.pi / 2,), (0,)): + xpos = robot.robot_model.base_xpos_offset["table"](self.table_full_size[0]) + rot = np.array((0, 0, rotation)) + xpos = T.euler2mat(rot) @ np.array(xpos) + xpos += np.array((0, offset, 0)) + robot.robot_model.set_base_xpos(xpos) + robot.robot_model.set_base_ori(rot) + + # load model for table top workspace + self.mujoco_arena = TableArena( + table_full_size=self.table_full_size, + table_friction=self.table_friction, + table_offset=self.table_offset, + ) + + # Arena always gets set to zero origin + self.mujoco_arena.set_origin([0, 0, 0]) + + self.set_cameras() + + objects = [] + for obj_num in range(self._num_objects): + if self._obj_mjcf_path == "cube": + # debugging case using primitive geom + obj = BoxObject( + name="cube_{}".format(obj_num), + size_min=[0.020, 0.020, 0.020], # [0.015, 0.015, 0.015], + size_max=[0.022, 0.022, 0.022], # [0.018, 0.018, 0.018]) + rgba=[1, 0, 0, 1], + ) + else: + obj = MJCFObject( + name="MCJFObj_{}".format(obj_num), + mjcf_path=self._obj_mjcf_path, + scale=self._obj_scale, + ) + + objects.append(obj) + + # Create placement initializer + if self.placement_initializer is not None: + self.placement_initializer.reset() + self.placement_initializer.add_objects(objects) + else: + self.placement_initializer = UniformRandomSampler( + name="ObjectSampler", + mujoco_objects=objects, + x_range=self._x_range, + y_range=self._y_range, + rotation=self._rotation, + ensure_object_boundary_in_range=False, + ensure_valid_placement=True, + reference_pos=self.table_offset, + z_offset=0.01, + # # for debugging + # x_range=(0, 0), + # y_range=(0, 0), + # rotation=(0, 0), + ) + + # task includes arena, robot, and objects of interest + self.model = ManipulationTask( + mujoco_arena=self.mujoco_arena, + mujoco_robots=[robot.robot_model for robot in self.robots], + mujoco_objects=objects, + ) + + # def _setup_references(self): + # """ + # Sets up references to important components. A reference is typically an + # index or a list of indices that point to the corresponding elements + # in a flatten array, which is how MuJoCo stores physical simulation data. + # """ + # super()._setup_references() + + # # Additional object references from this env + # self.obj_body_id = self.sim.model.body_name2id(self.mjcf_obj.root_body) + + def set_cameras(self): + """ + copied from environments/manipulation/kitchen.py + """ + for (cam_name, cam_cfg) in self._cam_configs.items(): + if cam_cfg.get("parent_body", None) is not None: + continue + + self.mujoco_arena.set_camera( + camera_name=cam_name, pos=cam_cfg["pos"], quat=cam_cfg["quat"] + ) + + def _reset_internal(self): + """ + Resets simulation internal configurations. + """ + super()._reset_internal() + + # Reset all object positions using initializer sampler if we're not directly loading from an xml + if not self.deterministic_reset: + + # Sample from the placement initializer for all objects + object_placements = self.placement_initializer.sample() + + # Loop through all objects and reset their positions + for obj_pos, obj_quat, obj in object_placements.values(): + # self.sim.model.body_pos[self.sim.model.body_name2id(obj.root_body)] = obj_pos + # self.sim.model.body_quat[self.sim.model.body_name2id(obj.root_body)] = obj_quat + + self.sim.data.set_joint_qpos( + obj.joints[0], + np.concatenate([np.array(obj_pos), np.array(obj_quat)]), + ) + + # def visualize(self, vis_settings): + # """ + # In addition to super call, visualize gripper site proportional to the distance to the cube. + # + # Args: + # vis_settings (dict): Visualization keywords mapped to T/F, determining whether that specific + # component should be visualized. Should have "grippers" keyword as well as any other relevant + # options specified. + # """ + # # Run superclass method first + # super().visualize(vis_settings=vis_settings) + # + # # Color the gripper visualization site according to its distance to the cube + # if vis_settings["grippers"]: + # self._visualize_gripper_to_target(gripper=self.robots[0].gripper, target=self.cube) + + def _check_success(self): + return False diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/object_template.xml b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/object_template.xml new file mode 100644 index 0000000000000000000000000000000000000000..986e66ffb6df37968b604ab9b39926be136c95ca --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/object_template.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/parser_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/parser_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..37a5bd601b151c4caf5b4e23a217b2449c718f42 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/model_zoo/parser_utils.py @@ -0,0 +1,63 @@ +import argparse + + +def get_base_parser(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--base_asset_path", + type=str, + help="(optional) base asset path where model files are stored. " + "Defaults to robosuite_model_zoo/assets_private folder.", + ) + parser.add_argument( + "--model_folder", + type=str, + help="(optional) folder to store model (relative to base asset path). " + "Defaults to None.", + ) + parser.add_argument( + "--model_name", + type=str, + help="(optional) name of saved mjcf model. " + "Defaults to name from --model_path.", + ) + parser.add_argument( + "--scale", + type=float, + default=1.0, + help="1d scaling of input model", + ) + parser.add_argument( + "--show_sites", + action="store_true", + help="show model bounds sites", + ) + parser.add_argument( + "--verbose", + action="store_true", + help="print detailed information for debugging", + ) + + ### V-HACD settings ### + parser.add_argument( + "--vhacd_max_output_convex_hulls", + type=float, + default=32, + ) + parser.add_argument( + "--vhacd_voxel_resolution", + type=float, + default=100000, + ) + parser.add_argument( + "--vhacd_volume_error_percent", + type=float, + default=1.0, + ) + parser.add_argument( + "--vhacd_max_hull_vert_count", + type=float, + default=64, + ) + + return parser diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/object_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/object_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..6523e0ff9736255ac5a58e37ff27f5f88c90f4d8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/object_utils.py @@ -0,0 +1,367 @@ +import numpy as np +import robosuite.utils.transform_utils as T +from robosuite.utils.mjcf_utils import ( + array_to_string, + string_to_array, + xml_path_completion, +) + +from robocasa.models.objects.objects import MJCFObject + + +def obj_inside_of(env, obj_name, fixture_id, partial_check=False): + """ + whether an object (another mujoco object) is inside of fixture. applies for most fixtures + """ + from robocasa.models.fixtures import Fixture + + obj = env.objects[obj_name] + fixture = env.get_fixture(fixture_id) + assert isinstance(obj, MJCFObject) + assert isinstance(fixture, Fixture) + + # step 1: calculate fxiture points + fixtr_p0, fixtr_px, fixtr_py, fixtr_pz = fixture.get_int_sites(relative=False) + u = fixtr_px - fixtr_p0 + v = fixtr_py - fixtr_p0 + w = fixtr_pz - fixtr_p0 + + # get the position and quaternion of object + obj_pos = np.array(env.sim.data.body_xpos[env.obj_body_id[obj.name]]) + obj_quat = T.convert_quat( + env.sim.data.body_xquat[env.obj_body_id[obj.name]], to="xyzw" + ) + + if partial_check: + obj_points_to_check = [obj_pos] + th = 0.0 + else: + # calculate 8 boundary points of object + obj_points_to_check = obj.get_bbox_points(trans=obj_pos, rot=obj_quat) + # threshold to mitigate false negatives: even if the bounding box point is out of bounds, + th = 0.05 + + inside_of = True + for obj_p in obj_points_to_check: + check1 = ( + np.dot(u, fixtr_p0) - th <= np.dot(u, obj_p) <= np.dot(u, fixtr_px) + th + ) + check2 = ( + np.dot(v, fixtr_p0) - th <= np.dot(v, obj_p) <= np.dot(v, fixtr_py) + th + ) + check3 = ( + np.dot(w, fixtr_p0) - th <= np.dot(w, obj_p) <= np.dot(w, fixtr_pz) + th + ) + + if not (check1 and check2 and check3): + inside_of = False + break + + return inside_of + + +# used for cabinets, cabinet panels, counters, etc. +def set_geom_dimensions(sizes, positions, geoms, rotated=False): + """ + set the dimensions of geoms in a fixture + + Args: + sizes (dict): dictionary of sizes for each side + + positions (dict): dictionary of positions for each side + + geoms (dict): dictionary of geoms for each side + + rotated (bool): whether the fixture is rotated. Fixture may be rotated to make texture appear uniform + due to mujoco texture conventions + """ + if rotated: + # rotation trick to make texture appear uniform + # see .xml file + for side in sizes.keys(): + # not the best detection method, TODO: check euler + if "door" in side or "trim" in side: + sizes[side] = [sizes[side][i] for i in [0, 2, 1]] + + # set sizes and positions of all geoms + for side in positions.keys(): + for geom in geoms[side]: + if geom is None: + raise ValueError("Did not find geom:", side) + geom.set("pos", array_to_string(positions[side])) + geom.set("size", array_to_string(sizes[side])) + + +def get_rel_transform(fixture_A, fixture_B): + """ + Gets fixture_B's position and rotation relative to fixture_A's frame + """ + A_trans = np.array(fixture_A.pos) + B_trans = np.array(fixture_B.pos) + + A_rot = np.array([0, 0, fixture_A.rot]) + B_rot = np.array([0, 0, fixture_B.rot]) + + A_mat = T.euler2mat(A_rot) + B_mat = T.euler2mat(B_rot) + + T_WA = np.vstack((np.hstack((A_mat, A_trans[:, None])), [0, 0, 0, 1])) + T_WB = np.vstack((np.hstack((B_mat, B_trans[:, None])), [0, 0, 0, 1])) + + T_AB = np.matmul(np.linalg.inv(T_WA), T_WB) + + return T_AB[:3, 3], T_AB[:3, :3] + + +def compute_rel_transform(A_pos, A_mat, B_pos, B_mat): + """ + Gets B's position and rotation relative to A's frame + """ + T_WA = np.vstack((np.hstack((A_mat, A_pos[:, None])), [0, 0, 0, 1])) + T_WB = np.vstack((np.hstack((B_mat, B_pos[:, None])), [0, 0, 0, 1])) + + T_AB = np.matmul(np.linalg.inv(T_WA), T_WB) + + return T_AB[:3, 3], T_AB[:3, :3] + + +def get_fixture_to_point_rel_offset(fixture, point): + """ + get offset relative to fixture's frame, given a global point + """ + global_offset = point - fixture.pos + T_WF = T.euler2mat([0, 0, fixture.rot]) + rel_offset = np.matmul(np.linalg.inv(T_WF), global_offset) + return rel_offset + + +def get_pos_after_rel_offset(fixture, offset): + """ + get global position of a fixture, after applying offset relative to center of fixture + """ + fixture_rot = np.array([0, 0, fixture.rot]) + fixture_mat = T.euler2mat(fixture_rot) + + return fixture.pos + np.dot(fixture_mat, offset) + + +def project_point_to_line(P, A, B): + """ + logic copied from here: https://stackoverflow.com/a/61342198 + """ + AP = P - A + AB = B - A + result = A + np.dot(AP, AB) / np.dot(AB, AB) * AB + + return result + + +def point_in_fixture(point, fixture, only_2d=False): + """ + check if point is inside of the exterior bounding boxes of the fixture + + Args: + point (np.array): point to check + + fixture (Fixture): fixture object + + only_2d (bool): whether to check only in 2D + """ + p0, px, py, pz = fixture.get_ext_sites(relative=False) + th = 0.00 + u = px - p0 + v = py - p0 + w = pz - p0 + check1 = np.dot(u, p0) - th <= np.dot(u, point) <= np.dot(u, px) + th + check2 = np.dot(v, p0) - th <= np.dot(v, point) <= np.dot(v, py) + th + check3 = np.dot(w, p0) - th <= np.dot(w, point) <= np.dot(w, pz) + th + + if only_2d: + return check1 and check2 + else: + return check1 and check2 and check3 + + +def obj_in_region( + obj, + obj_pos, + obj_quat, + p0, + px, + py, + pz=None, +): + """ + check if object is in the region defined by the points. + Uses either the objects bounding box or the object's horizontal radius + """ + from robocasa.models.fixtures import Fixture + + if isinstance(obj, MJCFObject) or isinstance(obj, Fixture): + obj_points = obj.get_bbox_points(trans=obj_pos, rot=obj_quat) + else: + radius = obj.horizontal_radius + obj_points = obj_pos + np.array( + [ + [radius, 0, 0], + [-radius, 0, 0], + [0, radius, 0], + [0, -radius, 0], + ] + ) + + u = px - p0 + v = py - p0 + w = pz - p0 if pz is not None else None + + for point in obj_points: + check1 = np.dot(u, p0) <= np.dot(u, point) <= np.dot(u, px) + check2 = np.dot(v, p0) <= np.dot(v, point) <= np.dot(v, py) + + if not check1 or not check2: + return False + + if w is not None: + check3 = np.dot(w, p0) <= np.dot(w, point) <= np.dot(w, pz) + if not check3: + return False + + return True + + +def fixture_pairwise_dist(f1, f2): + """ + Gets the distance between two fixtures by finding the minimum distance between their exterior bounding box points + """ + f1_points = f1.get_ext_sites(all_points=True, relative=False) + f2_points = f2.get_ext_sites(all_points=True, relative=False) + + all_dists = [np.linalg.norm(p1 - p2) for p1 in f1_points for p2 in f2_points] + return np.min(all_dists) + + +def objs_intersect( + obj, + obj_pos, + obj_quat, + other_obj, + other_obj_pos, + other_obj_quat, +): + """ + check if two objects intersect + """ + from robocasa.models.fixtures import Fixture + + bbox_check = (isinstance(obj, MJCFObject) or isinstance(obj, Fixture)) and ( + isinstance(other_obj, MJCFObject) or isinstance(other_obj, Fixture) + ) + if bbox_check: + obj_points = obj.get_bbox_points(trans=obj_pos, rot=obj_quat) + other_obj_points = other_obj.get_bbox_points( + trans=other_obj_pos, rot=other_obj_quat + ) + + face_normals = [ + obj_points[1] - obj_points[0], + obj_points[2] - obj_points[0], + obj_points[3] - obj_points[0], + other_obj_points[1] - other_obj_points[0], + other_obj_points[2] - other_obj_points[0], + other_obj_points[3] - other_obj_points[0], + ] + + intersect = True + + # noramlize length of normals + for normal in face_normals: + normal = np.array(normal) / np.linalg.norm(normal) + + obj_projs = [np.dot(p, normal) for p in obj_points] + other_obj_projs = [np.dot(p, normal) for p in other_obj_points] + + # see if gap detected + if np.min(other_obj_projs) > np.max(obj_projs) or np.min( + obj_projs + ) > np.max(other_obj_projs): + intersect = False + break + else: + """ + old code from placement_samplers.py + """ + obj_x, obj_y, obj_z = obj_pos + other_obj_x, other_obj_y, other_obj_z = other_obj_pos + xy_collision = ( + np.linalg.norm((obj_x - other_obj_x, obj_y - other_obj_y)) + <= other_obj.horizontal_radius + obj.horizontal_radius + ) + if obj_z > other_obj_z: + z_collision = ( + obj_z - other_obj_z <= other_obj.top_offset[-1] - obj.bottom_offset[-1] + ) + else: + z_collision = ( + other_obj_z - obj_z <= obj.top_offset[-1] - other_obj.bottom_offset[-1] + ) + + if xy_collision and z_collision: + intersect = True + else: + intersect = False + + return intersect + + +def normalize_joint_value(raw, joint_min, joint_max): + """ + normalize raw value to be between 0 and 1 + """ + return (raw - joint_min) / (joint_max - joint_min) + + +def check_obj_in_receptacle(env, obj_name, receptacle_name, th=None): + """ + check if object is in receptacle object based on threshold + """ + obj = env.objects[obj_name] + recep = env.objects[receptacle_name] + obj_pos = np.array(env.sim.data.body_xpos[env.obj_body_id[obj_name]]) + recep_pos = np.array(env.sim.data.body_xpos[env.obj_body_id[receptacle_name]]) + if th is None: + th = recep.horizontal_radius * 0.7 + obj_in_recep = ( + env.check_contact(obj, recep) + and np.linalg.norm(obj_pos[:2] - recep_pos[:2]) < th + ) + return obj_in_recep + + +def check_obj_fixture_contact(env, obj_name, fixture_name): + """ + check if object is in contact with fixture + """ + obj = env.objects[obj_name] + fixture = env.get_fixture(fixture_name) + return env.check_contact(obj, fixture) + + +def gripper_obj_far(env, obj_name="obj", th=0.25): + """ + check if gripper is far from object based on distance defined by threshold + """ + obj_pos = env.sim.data.body_xpos[env.obj_body_id[obj_name]] + gripper_site_pos = env.sim.data.site_xpos[env.robots[0].eef_site_id["right"]] + gripper_obj_far = np.linalg.norm(gripper_site_pos - obj_pos) > th + return gripper_obj_far + + +def obj_cos(env, obj_name="obj", ref=(0, 0, 1)): + def cos(u, v): + return np.dot(u, v) / max(np.linalg.norm(u) * np.linalg.norm(v), 1e-10) + + obj_id = env.obj_body_id[obj_name] + obj_quat = T.convert_quat(np.array(env.sim.data.body_xquat[obj_id]), to="xyzw") + obj_mat = T.quat2mat(obj_quat) + + return cos(obj_mat[:, 2], np.array(ref)) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/placement_samplers.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/placement_samplers.py new file mode 100644 index 0000000000000000000000000000000000000000..9380c7dc84e52681df6c1d8271b568b3afbc2df4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/placement_samplers.py @@ -0,0 +1,622 @@ +import collections +import random +from copy import copy + +import numpy as np +from robosuite.models.objects import MujocoObject +from robosuite.utils import RandomizationError +from robosuite.utils.transform_utils import ( + convert_quat, + euler2mat, + mat2quat, + quat_multiply, + rotate_2d_point, +) + +from robocasa.utils.object_utils import obj_in_region, objs_intersect + + +class ObjectPositionSampler: + """ + Base class of object placement sampler. + + Args: + name (str): Name of this sampler. + + mujoco_objects (None or MujocoObject or list of MujocoObject): single model or list of MJCF object models + + ensure_object_boundary_in_range (bool): If True, will ensure that the object is enclosed within a given boundary + (should be implemented by subclass) + + ensure_valid_placement (bool): If True, will check for correct (valid) object placements + + reference_pos (3-array): global (x,y,z) position relative to which sampling will occur + + z_offset (float): Add a small z-offset to placements. This is useful for fixed objects + that do not move (i.e. no free joint) to place them above the table. + """ + + def __init__( + self, + name, + mujoco_objects=None, + ensure_object_boundary_in_range=True, + ensure_valid_placement=True, + reference_pos=(0, 0, 0), + reference_rot=0, + z_offset=0.0, + rng=None, + ): + if rng is None: + rng = np.random.default_rng() + self.rng = rng + + # Setup attributes + self.name = name + if mujoco_objects is None: + self.mujoco_objects = [] + else: + # Shallow copy the list so we don't modify the inputted list but still keep the object references + self.mujoco_objects = ( + [mujoco_objects] + if isinstance(mujoco_objects, MujocoObject) + else copy(mujoco_objects) + ) + self.ensure_object_boundary_in_range = ensure_object_boundary_in_range + self.ensure_valid_placement = ensure_valid_placement + self.reference_pos = reference_pos + self.reference_rot = reference_rot + self.z_offset = z_offset + + def add_objects(self, mujoco_objects): + """ + Add additional objects to this sampler. Checks to make sure there's no identical objects already stored. + + Args: + mujoco_objects (MujocoObject or list of MujocoObject): single model or list of MJCF object models + """ + mujoco_objects = ( + [mujoco_objects] + if isinstance(mujoco_objects, MujocoObject) + else mujoco_objects + ) + for obj in mujoco_objects: + assert ( + obj not in self.mujoco_objects + ), "Object '{}' already in sampler!".format(obj.name) + self.mujoco_objects.append(obj) + + def reset(self): + """ + Resets this sampler. Removes all mujoco objects from this sampler. + """ + self.mujoco_objects = [] + + def sample(self, fixtures=None, reference=None, on_top=True): + """ + Uniformly sample on a surface (not necessarily table surface). + + Args: + fixtures (dict): dictionary of current object placements in the scene as well as any other relevant + obstacles that should not be in contact with newly sampled objects. Used to make sure newly + generated placements are valid. Should be object names mapped to (pos, quat, MujocoObject) + + reference (str or 3-tuple or None): if provided, sample relative placement. Can either be a string, which + corresponds to an existing object found in @fixtures, or a direct (x,y,z) value. If None, will sample + relative to this sampler's `'reference_pos'` value. + + on_top (bool): if True, sample placement on top of the reference object. + + Return: + dict: dictionary of all object placements, mapping object_names to (pos, quat, obj), including the + placements specified in @fixtures. Note quat is in (w,x,y,z) form + """ + raise NotImplementedError + + @property + def sides_combinations(self): + return { + "left": ["front_left", "back_left"], + "right": ["front_right", "back_right"], + "front": ["front_left", "front_right"], + "back": ["back_left", "back_right"], + "all": ["front_left", "front_right", "back_left", "back_right"], + } + + @property + def valid_sides(self): + return set( + [ + "left", + "right", + "front", + "back", + "all", + "front_left", + "front_right", + "back_left", + "back_right", + ] + ) + + +class UniformRandomSampler(ObjectPositionSampler): + """ + Places all objects within the table uniformly random. + + Args: + name (str): Name of this sampler. + + mujoco_objects (None or MujocoObject or list of MujocoObject): single model or list of MJCF object models + + x_range (2-array of float): Specify the (min, max) relative x_range used to uniformly place objects + + y_range (2-array of float): Specify the (min, max) relative y_range used to uniformly place objects + + rotation (None or float or Iterable): + :`None`: Add uniform random random rotation + :`Iterable (a,b)`: Uniformly randomize rotation angle between a and b (in radians) + :`value`: Add fixed angle rotation + + rotation_axis (str): Can be 'x', 'y', or 'z'. Axis about which to apply the requested rotation + + ensure_object_boundary_in_range (bool): + :`True`: The center of object is at position: + [uniform(min x_range + radius, max x_range - radius)], [uniform(min x_range + radius, max x_range - radius)] + :`False`: + [uniform(min x_range, max x_range)], [uniform(min x_range, max x_range)] + + ensure_valid_placement (bool): If True, will check for correct (valid) object placements + + reference_pos (3-array): global (x,y,z) position relative to which sampling will occur + + z_offset (float): Add a small z-offset to placements. This is useful for fixed objects + that do not move (i.e. no free joint) to place them above the table. + """ + + def __init__( + self, + name, + mujoco_objects=None, + x_range=(0, 0), + y_range=(0, 0), + rotation=None, + rotation_axis="z", + ensure_object_boundary_in_range=True, + ensure_valid_placement=True, + reference_pos=(0, 0, 0), + reference_rot=0, + z_offset=0.0, + rng=None, + side="all", + ): + self.x_range = x_range + self.y_range = y_range + self.rotation = rotation + self.rotation_axis = rotation_axis + + if side not in self.valid_sides: + raise ValueError( + "Invalid value for side, must be one of:", self.valid_sides + ) + + super().__init__( + name=name, + mujoco_objects=mujoco_objects, + ensure_object_boundary_in_range=ensure_object_boundary_in_range, + ensure_valid_placement=ensure_valid_placement, + reference_pos=reference_pos, + reference_rot=reference_rot, + z_offset=z_offset, + rng=rng, + ) + + def _sample_x(self): + """ + Samples the x location for a given object + + Returns: + float: sampled x position + """ + minimum, maximum = self.x_range + return self.rng.uniform(high=maximum, low=minimum) + + def _sample_y(self): + """ + Samples the y location for a given object + + Returns: + float: sampled y position + """ + minimum, maximum = self.y_range + return self.rng.uniform(high=maximum, low=minimum) + + def _sample_quat(self): + """ + Samples the orientation for a given object + + Returns: + np.array: sampled object quaternion in (w,x,y,z) form + + Raises: + ValueError: [Invalid rotation axis] + """ + if self.rotation is None: + rot_angle = self.rng.uniform(high=2 * np.pi, low=0) + elif isinstance(self.rotation, collections.abc.Iterable): + if isinstance(self.rotation[0], collections.abc.Iterable): + rotation = self.rng.choice(self.rotation) + else: + rotation = self.rotation + rot_angle = self.rng.uniform(high=max(rotation), low=min(rotation)) + else: + rot_angle = self.rotation + + # Return angle based on axis requested + if self.rotation_axis == "x": + return np.array([np.cos(rot_angle / 2), np.sin(rot_angle / 2), 0, 0]) + elif self.rotation_axis == "y": + return np.array([np.cos(rot_angle / 2), 0, np.sin(rot_angle / 2), 0]) + elif self.rotation_axis == "z": + return np.array([np.cos(rot_angle / 2), 0, 0, np.sin(rot_angle / 2)]) + else: + # Invalid axis specified, raise error + raise ValueError( + "Invalid rotation axis specified. Must be 'x', 'y', or 'z'. Got: {}".format( + self.rotation_axis + ) + ) + + def sample(self, placed_objects=None, reference=None, on_top=True): + """ + Uniformly sample relative to this sampler's reference_pos or @reference (if specified). + + Args: + placed_objects (dict): dictionary of current object placements in the scene as well as any other relevant + obstacles that should not be in contact with newly sampled objects. Used to make sure newly + generated placements are valid. Should be object names mapped to (pos, quat, MujocoObject) + + reference (str or 3-tuple or None): if provided, sample relative placement. Can either be a string, which + corresponds to an existing object found in @fixtures, or a direct (x,y,z) value. If None, will sample + relative to this sampler's `'reference_pos'` value. + + on_top (bool): if True, sample placement on top of the reference object. This corresponds to a sampled + z-offset of the current sampled object's bottom_offset + the reference object's top_offset + (if specified) + + Return: + dict: dictionary of all object placements, mapping object_names to (pos, quat, obj), including the + placements specified in @fixtures. Note quat is in (w,x,y,z) form + + Raises: + RandomizationError: [Cannot place all objects] + AssertionError: [Reference object name does not exist, invalid inputs] + """ + # Standardize inputs + placed_objects = {} if placed_objects is None else copy(placed_objects) + + if reference is None: + base_offset = self.reference_pos + elif type(reference) is str: + assert ( + reference in placed_objects + ), "Invalid reference received. Current options are: {}, requested: {}".format( + placed_objects.keys(), reference + ) + ref_pos, _, ref_obj = placed_objects[reference] + base_offset = np.array(ref_pos) + if on_top: + base_offset += np.array((0, 0, ref_obj.top_offset[-1])) + else: + base_offset = np.array(reference) + assert ( + base_offset.shape[0] == 3 + ), "Invalid reference received. Should be (x,y,z) 3-tuple, but got: {}".format( + base_offset + ) + + # Sample pos and quat for all objects assigned to this sampler + for obj in self.mujoco_objects: + # First make sure the currently sampled object hasn't already been sampled + assert ( + obj.name not in placed_objects + ), "Object '{}' has already been sampled!".format(obj.name) + + success = False + + # get reference rotation + ref_quat = convert_quat( + mat2quat(euler2mat([0, 0, self.reference_rot])), to="wxyz" + ) + + ### get boundary points ### + region_points = np.array( + [ + [self.x_range[0], self.y_range[0], 0], + [self.x_range[1], self.y_range[0], 0], + [self.x_range[0], self.y_range[1], 0], + ] + ) + for i in range(len(region_points)): + region_points[i][0:2] = rotate_2d_point( + region_points[i][0:2], rot=self.reference_rot + ) + region_points += base_offset + + for i in range(5000): # 5000 retries + # sample object coordinates + relative_x = self._sample_x() + relative_y = self._sample_y() + + # apply rotation + object_x, object_y = rotate_2d_point( + [relative_x, relative_y], rot=self.reference_rot + ) + + object_x = object_x + base_offset[0] + object_y = object_y + base_offset[1] + object_z = self.z_offset + base_offset[2] + if on_top: + object_z -= obj.bottom_offset[-1] + + # random rotation + quat = self._sample_quat() + # multiply this quat by the object's initial rotation if it has the attribute specified + if hasattr(obj, "init_quat"): + quat = quat_multiply(quat, obj.init_quat) + quat = convert_quat( + quat_multiply( + convert_quat(ref_quat, to="xyzw"), + convert_quat(quat, to="xyzw"), + ), + to="wxyz", + ) + + location_valid = True + + # ensure object placed fully in region + if self.ensure_object_boundary_in_range and not obj_in_region( + obj, + obj_pos=[object_x, object_y, object_z], + obj_quat=convert_quat(quat, to="xyzw"), + p0=region_points[0], + px=region_points[1], + py=region_points[2], + ): + location_valid = False + continue + + # objects cannot overlap + if self.ensure_valid_placement: + for (x, y, z), other_quat, other_obj in placed_objects.values(): + if objs_intersect( + obj=obj, + obj_pos=[object_x, object_y, object_z], + obj_quat=convert_quat(quat, to="xyzw"), + other_obj=other_obj, + other_obj_pos=[x, y, z], + other_obj_quat=convert_quat(other_quat, to="xyzw"), + ): + location_valid = False + break + + if location_valid: + # location is valid, put the object down + pos = (object_x, object_y, object_z) + placed_objects[obj.name] = (pos, quat, obj) + success = True + break + + if not success: + raise RandomizationError("Cannot place all objects ):") + + return placed_objects + + +class SequentialCompositeSampler(ObjectPositionSampler): + """ + Samples position for each object sequentially. Allows chaining + multiple placement initializers together - so that object locations can + be sampled on top of other objects or relative to other object placements. + + Args: + name (str): Name of this sampler. + """ + + def __init__(self, name, rng=None): + # Samplers / args will be filled in later + self.samplers = collections.OrderedDict() + self.sample_args = collections.OrderedDict() + + super().__init__(name=name, rng=rng) + + def append_sampler(self, sampler, sample_args=None): + """ + Adds a new placement initializer with corresponding @sampler and arguments + + Args: + sampler (ObjectPositionSampler): sampler to add + sample_args (None or dict): If specified, should be additional arguments to pass to @sampler's sample() + call. Should map corresponding sampler's arguments to values (excluding @fixtures argument) + + Raises: + AssertionError: [Object name in samplers] + """ + # Verify that all added mujoco objects haven't already been added, and add to this sampler's objects dict + for obj in sampler.mujoco_objects: + assert ( + obj not in self.mujoco_objects + ), f"Object '{obj.name}' already has sampler associated with it!" + self.mujoco_objects.append(obj) + self.samplers[sampler.name] = sampler + self.sample_args[sampler.name] = sample_args + + def hide(self, mujoco_objects): + """ + Helper method to remove an object from the workspace. + + Args: + mujoco_objects (MujocoObject or list of MujocoObject): Object(s) to hide + """ + sampler = UniformRandomSampler( + name="HideSampler", + mujoco_objects=mujoco_objects, + x_range=[-10, -20], + y_range=[-10, -20], + rotation=[0, 0], + rotation_axis="z", + z_offset=10, + ensure_object_boundary_in_range=False, + ensure_valid_placement=False, + rng=self.rng, + ) + self.append_sampler(sampler=sampler) + + def add_objects(self, mujoco_objects): + """ + Override super method to make sure user doesn't call this (all objects should implicitly belong to sub-samplers) + """ + raise AttributeError( + "add_objects() should not be called for SequentialCompsiteSamplers!" + ) + + def add_objects_to_sampler(self, sampler_name, mujoco_objects): + """ + Adds specified @mujoco_objects to sub-sampler with specified @sampler_name. + + Args: + sampler_name (str): Existing sub-sampler name + mujoco_objects (MujocoObject or list of MujocoObject): Object(s) to add + """ + # First verify that all mujoco objects haven't already been added, and add to this sampler's objects dict + mujoco_objects = ( + [mujoco_objects] + if isinstance(mujoco_objects, MujocoObject) + else mujoco_objects + ) + for obj in mujoco_objects: + assert ( + obj not in self.mujoco_objects + ), f"Object '{obj.name}' already has sampler associated with it!" + self.mujoco_objects.append(obj) + # Make sure sampler_name exists + assert sampler_name in self.samplers.keys(), ( + "Invalid sub-sampler specified, valid options are: {}, " + "requested: {}".format(self.samplers.keys(), sampler_name) + ) + # Add the mujoco objects to the requested sub-sampler + self.samplers[sampler_name].add_objects(mujoco_objects) + + def reset(self): + """ + Resets this sampler. In addition to base method, iterates over all sub-samplers and resets them + """ + super().reset() + for sampler in self.samplers.values(): + sampler.reset() + + def sample(self, placed_objects=None, reference=None, on_top=True): + """ + Sample from each placement initializer sequentially, in the order + that they were appended. + + Args: + placed_objects (dict): dictionary of current object placements in the scene as well as any other relevant + obstacles that should not be in contact with newly sampled objects. Used to make sure newly + generated placements are valid. Should be object names mapped to (pos, quat, MujocoObject) + + reference (str or 3-tuple or None): if provided, sample relative placement. This will override each + sampler's @reference argument if not already specified. Can either be a string, which + corresponds to an existing object found in @fixtures, or a direct (x,y,z) value. If None, will sample + relative to this sampler's `'reference_pos'` value. + + on_top (bool): if True, sample placement on top of the reference object. This will override each + sampler's @on_top argument if not already specified. This corresponds to a sampled + z-offset of the current sampled object's bottom_offset + the reference object's top_offset + (if specified) + + Return: + dict: dictionary of all object placements, mapping object_names to (pos, quat, obj), including the + placements specified in @fixtures. Note quat is in (w,x,y,z) form + + Raises: + RandomizationError: [Cannot place all objects] + """ + # Standardize inputs + placed_objects = {} if placed_objects is None else copy(placed_objects) + + # Iterate through all samplers to sample + for sampler, s_args in zip(self.samplers.values(), self.sample_args.values()): + # Pre-process sampler args + if s_args is None: + s_args = {} + for arg_name, arg in zip(("reference", "on_top"), (reference, on_top)): + if arg_name not in s_args: + s_args[arg_name] = arg + # Run sampler + new_placements = sampler.sample(placed_objects=placed_objects, **s_args) + # Update placements + placed_objects.update(new_placements) + + # only return placements for newly placed objects + sampled_obj_names = [ + obj.name + for sampler in self.samplers.values() + for obj in sampler.mujoco_objects + ] + return {k: v for (k, v) in placed_objects.items() if k in sampled_obj_names} + + +class MultiRegionSampler(ObjectPositionSampler): + def __init__( + self, + name, + regions, + side="all", + mujoco_objects=None, + rotation=None, + rotation_axis="z", + ensure_object_boundary_in_range=True, + ensure_valid_placement=True, + rng=None, + z_offset=0.0, + ): + if len(regions) != 4: + raise ValueError( + "Exactly four sites (one for each quadrant) must be provided." + ) + if side not in self.valid_sides: + raise ValueError( + "Invalid value for side, must be one of:", self.valid_sides + ) + + # initialize sides and regions + if side in self.sides_combinations: + self.sides = self.sides_combinations[side] + else: + self.sides = [side] + self.regions = regions + + # create a list of uniform samplers (one for each site) + self.samplers = list() + for s in self.sides: + site = self.regions[s] + sampler = UniformRandomSampler( + name=name, + mujoco_objects=mujoco_objects, + reference_pos=site["pos"], + x_range=site["x_range"], + y_range=site["y_range"], + rotation=rotation, + rotation_axis=rotation_axis, + ensure_object_boundary_in_range=ensure_object_boundary_in_range, + ensure_valid_placement=ensure_valid_placement, + z_offset=z_offset, + rng=rng, + ) + self.samplers.append(sampler) + + def sample(self, fixtures=None, reference=None, on_top=True): + # randomly picks a sampler and calls its sample function + sampler = self.rng.choice(self.samplers) + return sampler.sample(fixtures=fixtures, reference=reference, on_top=on_top) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/postprocess_xml_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/postprocess_xml_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..242daf7daf2eb6fff3e5745241a3f837afda7b7f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/postprocess_xml_utils.py @@ -0,0 +1,78 @@ +import h5py +import json +import argparse +import os +from shutil import copyfile +import robosuite +import xml.etree.ElementTree as ET +from tqdm import tqdm +import numpy as np + + +def get_eef_panda_site(prefix): + """ + Helper function for new element added in robosuite v1.5 + """ + + eef_panda_site = """ """ + + tree = ET.ElementTree(ET.fromstring(eef_panda_site)) + root = tree.getroot() + for elem in root.iter(): + elem.attrib["name"] = "{}_{}".format(prefix, elem.get("name")) + + return tree + + +def update_gripper_name(gripper_name: str): + tokens = gripper_name.split("_") + tokens.insert(1, "right") + return "_".join(tokens) + + +def convert_xml(xml_str): + """ + Postprocess xml string generated by robosuite to be compatible with robosuite v1.5 + This script should not the xml string if it was already generated using robosuite v1.5 + Args: + xml_str (str): xml string to process (from robosuite v1.4.1) + """ + + root = ET.fromstring(xml_str) + worldbody = root.find("worldbody") + bodies_to_process = [] + + for body in worldbody.iter("body"): + body_name = body.get("name") + if "link0" in body_name: + if body not in bodies_to_process: + bodies_to_process.append(body) + + # add elements introduced in v1.5 + for body in bodies_to_process: + prefix = body.get("name").split("_")[0] + eef_tree = get_eef_panda_site(prefix) + body.append(eef_tree.getroot()) + + assets = root.find("asset") + + # change path from mounts to bases + for asset in assets.iter("mesh"): + path = asset.get("file") + assert ( + "robosuite/models/assets" in path or "robocasa/models/assets" in path + ), print(path) + if "mounts" in path: + assert not "robot" in path + new_path = path.replace( + "robosuite/models/assets/mounts", "robosuite/models/assets/bases" + ) + asset.set("file", new_path) + + # update naming prefixes + for elem in root.iter(): + for attr, value in elem.attrib.items(): + if value.startswith("mount"): + elem.set(attr, value.replace("mount", "fixed_base", 1)) + elif value.startswith("gripper"): + elem.set(attr, update_gripper_name(value)) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_dataset_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_dataset_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..8d69653105fe97bde5c45bc5e6108274656717fe --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_dataset_utils.py @@ -0,0 +1,340 @@ +import os +import h5py +import json +import torch +import numpy as np + +import robocasa.utils.robomimic.robomimic_torch_utils as TorchUtils + + +def get_env_metadata_from_dataset(dataset_path): + """ + Retrieves env metadata from dataset. + + Args: + dataset_path (str): path to dataset + + Returns: + env_meta (dict): environment metadata. Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + """ + dataset_path = os.path.expanduser(dataset_path) + f = h5py.File(dataset_path, "r") + env_meta = json.loads(f["data"].attrs["env_args"]) + f.close() + return env_meta + + +def extract_action_dict(dataset): + # find files + f = h5py.File(os.path.expanduser(dataset), mode="r+") + + SPECS = [ + dict( + key="actions", + is_absolute=False, + ), + dict( + key="actions_abs", + is_absolute=True, + ), + ] + + # execute + for spec in SPECS: + input_action_key = spec["key"] + is_absolute = spec["is_absolute"] + + if is_absolute: + prefix = "abs_" + else: + prefix = "rel_" + + for demo in f["data"].values(): + if str(input_action_key) not in demo.keys(): + continue + in_action = demo[str(input_action_key)][:] + in_pos = in_action[:, :3].astype(np.float32) + in_rot = in_action[:, 3:6].astype(np.float32) + in_grip = in_action[:, 6:7].astype(np.float32) + + rot_6d = TorchUtils.axis_angle_to_rot_6d( + axis_angle=torch.from_numpy(in_rot) + ) + rot_6d = rot_6d.numpy().astype(np.float32) # convert to numpy + + this_action_dict = { + prefix + "pos": in_pos, + prefix + "rot_axis_angle": in_rot, + prefix + "rot_6d": rot_6d, + "gripper": in_grip, + } + + # special case: 8 dim actions mean there is a mobile base mode in the action space + if in_action.shape[1] == 8: + this_action_dict["base_mode"] = in_action[:, 7:8].astype(np.float32) + + action_dict_group = demo.require_group("action_dict") + for key, data in this_action_dict.items(): + if key in action_dict_group: + del action_dict_group[key] + action_dict_group.create_dataset(key, data=data) + + f.close() + + +def create_hdf5_filter_key(hdf5_path, demo_keys, key_name): + """ + Creates a new hdf5 filter key in hdf5 file @hdf5_path with + name @key_name that corresponds to the demonstrations + @demo_keys. Filter keys are generally useful to create + named subsets of the demonstrations in an hdf5, making it + easy to train, test, or report statistics on a subset of + the trajectories in a file. + + Returns the list of episode lengths that correspond to the filtering. + + Args: + hdf5_path (str): path to hdf5 file + demo_keys ([str]): list of demonstration keys which should + correspond to this filter key. For example, ["demo_0", + "demo_1"]. + key_name (str): name of filter key to create + + Returns: + ep_lengths ([int]): list of episode lengths that corresponds to + each demonstration in the new filter key + """ + f = h5py.File(hdf5_path, "a") + demos = sorted(list(f["data"].keys())) + + # collect episode lengths for the keys of interest + ep_lengths = [] + for ep in demos: + ep_data_grp = f["data/{}".format(ep)] + if ep in demo_keys: + ep_lengths.append(ep_data_grp.attrs["num_samples"]) + + # store list of filtered keys under mask group + k = "mask/{}".format(key_name) + if k in f: + del f[k] + f[k] = np.array(demo_keys, dtype="S") + + f.close() + return ep_lengths + + +def filter_dataset_size( + hdf5_path, num_demos, input_filter_key=None, output_filter_key=None +): + # retrieve number of demos + f = h5py.File(hdf5_path, "r") + if input_filter_key is not None: + print("using filter key: {}".format(input_filter_key)) + demos = sorted( + [ + elem.decode("utf-8") + for elem in np.array(f["mask/{}".format(input_filter_key)]) + ] + ) + else: + demos = sorted(list(f["data"].keys())) + f.close() + + # get random split + total_num_demos = len(demos) + mask = np.zeros(total_num_demos) + mask[:num_demos] = 1.0 + np.random.shuffle(mask) + mask = mask.astype(int) + subset_inds = mask.nonzero()[0] + subset_keys = [demos[i] for i in subset_inds] + + # pass mask to generate split + if output_filter_key is not None: + name = output_filter_key + else: + name = "{}_demos".format(num_demos) + + if input_filter_key is not None: + name = "{}_{}".format(input_filter_key, name) + + subset_lengths = create_hdf5_filter_key( + hdf5_path=hdf5_path, demo_keys=subset_keys, key_name=name + ) + + +def move_demo_to_new_key(f, old_demo_key, new_demo_key, delete_old_demo=True): + print(f"Moving {old_demo_key} -> {new_demo_key}") + + src_ep = f["data"][old_demo_key] + + if new_demo_key not in f["data"]: + f["data"].create_group(new_demo_key) + + targ_ep = f["data"][new_demo_key] + + targ_ep.attrs.update(src_ep.attrs) + + # write the datasets + for k in src_ep: + if isinstance(src_ep[k], h5py.Dataset): + targ_ep.create_dataset(k, data=np.array(src_ep[k])) + else: + for m in src_ep[k]: + targ_ep.create_dataset( + "{}/{}".format(k, m), + data=np.array(src_ep["{}/{}".format(k, m)]), + ) + + # write the metadata present in attributes as well + for k in src_ep.attrs: + targ_ep.attrs[k] = src_ep.attrs[k] + + if delete_old_demo is True: + del f["data"][old_demo_key] + + +def make_demo_ids_contiguous(dataset): + f = h5py.File(dataset, "a") # edit mode + + num_old_demos = max([int(demo_key.split("_")[-1]) for demo_key in f["data"]]) + 1 + missing_demo_inds = [ + i for i in range(num_old_demos) if f"demo_{i}" not in f["data"] + ] + num_new_demos = num_old_demos - len(missing_demo_inds) + + old_idx = num_old_demos - 1 + num_demos_changed = 0 + while num_demos_changed < len(missing_demo_inds): + if f"demo_{old_idx}" not in f["data"]: + old_idx -= 1 + continue + + new_idx = missing_demo_inds[num_demos_changed] + + if old_idx <= new_idx: + break + + old_demo_key = f"demo_{old_idx}" + new_demo_key = f"demo_{new_idx}" + + move_demo_to_new_key(f, old_demo_key, new_demo_key, delete_old_demo=True) + + old_idx -= 1 + num_demos_changed += 1 + + f.close() + + +def convert_to_robomimic_format( + dataset, + filter_num_demos=( + 10, + 20, + 30, + 40, + 50, + 60, + 70, + 75, + 80, + 90, + 100, + 125, + 150, + 200, + 250, + 300, + 400, + 500, + 600, + 700, + 800, + 900, + 1000, + 1500, + 2000, + 2500, + 3000, + 4000, + 5000, + 10000, + ), + verbose=False, +): + f = h5py.File(dataset, "a") # edit mode + + # store env meta + env_name = f["data"].attrs.get("env", None) + if "env_info" in f["data"].attrs: + env_info = json.loads(f["data"].attrs["env_info"]) + + # switch to using solid robot + env_info["translucent_robot"] = False + + if env_name is not None and env_info is not None: + env_meta = dict( + type=1, # hardcode as robosuite dataset type + env_name=env_name, + env_version=f["data"].attrs["robocasa_version"], + robosuite_version=f["data"].attrs["robosuite_version"], + mujoco_version=f["data"].attrs["mujoco_version"], + env_kwargs=env_info, + ) + if "env_args" in f["data"].attrs: + del f["data"].attrs["env_args"] + f["data"].attrs["env_args"] = json.dumps(env_meta, indent=4) + else: + # assume env_args already present + assert "env_args" in f["data"].attrs + + if verbose: + print("====== Stored env meta ======") + print(f["data"].attrs["env_args"]) + + # store metadata about number of samples + total_samples = 0 + for ep in f["data"]: + # ensure model-xml is in per-episode metadata + assert "model_file" in f["data/{}".format(ep)].attrs + + # add "num_samples" into per-episode metadata + if "num_samples" in f["data/{}".format(ep)].attrs: + del f["data/{}".format(ep)].attrs["num_samples"] + n_sample = f["data/{}/actions".format(ep)].shape[0] + f["data/{}".format(ep)].attrs["num_samples"] = n_sample + total_samples += n_sample + + # add total samples to global metadata + if "total" in f["data"].attrs: + del f["data"].attrs["total"] + f["data"].attrs["total"] = total_samples + + f.close() + + # # create 90-10 train-validation split in the dataset + # split_train_val_from_hdf5(hdf5_path=dataset, val_ratio=0.1) + + ### note: don't need this anymore! absolute actions are already extracted ### + # # add absolute actions to dataset + # add_absolute_actions_to_dataset( + # dataset=args.dataset, + # eval_dir=None, + # num_workers=1, + # ) + + # extract corresponding action keys into action_dict + extract_action_dict(dataset=dataset) + + # create filter keys according to number of demos + if filter_num_demos is not None: + for n in filter_num_demos: + filter_dataset_size( + dataset, + num_demos=n, + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_env_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_env_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f00cafa3c4222cba91f270be3488b7309a243078 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_env_utils.py @@ -0,0 +1,301 @@ +""" +This file contains several utility functions for working with environment +wrappers provided by the repository, and with environment metadata saved +in dataset files. +""" +from copy import deepcopy + +# import robomimic.envs.env_base as EB +# from robomimic.utils.log_utils import log_warning + + +def get_env_class(env_meta=None, env_type=None, env=None): + """ + Return env class from either env_meta, env_type, or env. + Note the use of lazy imports - this ensures that modules are only + imported when the corresponding env type is requested. This can + be useful in practice. For example, a training run that only + requires access to gym environments should not need to import + robosuite. + + Args: + env_meta (dict): environment metadata, which should be loaded from demonstration + hdf5 with @FileUtils.get_env_metadata_from_dataset or from checkpoint (see + @FileUtils.env_from_checkpoint). Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + + env_type (int): the type of environment, which determines the env class that will + be instantiated. Should be a value in EB.EnvType. + + env (instance of EB.EnvBase): environment instance + """ + env_type = get_env_type(env_meta=env_meta, env_type=env_type, env=env) + assert env_type == 1 + from robocasa.utils.robomimic.robomimic_env_wrapper import EnvRobocasa + + return EnvRobocasa + + +def get_env_type(env_meta=None, env_type=None, env=None): + """ + Helper function to get env_type from a variety of inputs. + + Args: + env_meta (dict): environment metadata, which should be loaded from demonstration + hdf5 with @FileUtils.get_env_metadata_from_dataset or from checkpoint (see + @FileUtils.env_from_checkpoint). Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + + env_type (int): the type of environment, which determines the env class that will + be instantiated. Should be a value in EB.EnvType. + + env (instance of EB.EnvBase): environment instance + """ + checks = [(env_meta is not None), (env_type is not None), (env is not None)] + assert sum(checks) == 1, "should provide only one of env_meta, env_type, env" + if env_meta is not None: + env_type = env_meta["type"] + elif env is not None: + env_type = env.type + return env_type + + +def check_env_type(type_to_check, env_meta=None, env_type=None, env=None): + """ + Checks whether the passed env_meta, env_type, or env is of type @type_to_check. + Type corresponds to EB.EnvType. + + Args: + type_to_check (int): type to check equality against + + env_meta (dict): environment metadata, which should be loaded from demonstration + hdf5 with @FileUtils.get_env_metadata_from_dataset or from checkpoint (see + @FileUtils.env_from_checkpoint). Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + + env_type (int): the type of environment, which determines the env class that will + be instantiated. Should be a value in EB.EnvType. + + env (instance of EB.EnvBase): environment instance + """ + env_type = get_env_type(env_meta=env_meta, env_type=env_type, env=env) + return env_type == type_to_check + + +def check_env_version(env, env_meta): + """ + Checks whether the passed env and env_meta dictionary having matching environment versions. + Logs warning if cannot find version or versions do not match. + + Args: + env (instance of EB.EnvBase): environment instance + + env_meta (dict): environment metadata, which should be loaded from demonstration + hdf5 with @FileUtils.get_env_metadata_from_dataset or from checkpoint (see + @FileUtils.env_from_checkpoint). Contains following key: + + :`'env_version'`: environment version, type str + """ + env_system_version = env.version + env_meta_version = env_meta.get("env_version", None) + + # if env_meta_version is None: + # log_warning( + # "No environment version found in dataset!"\ + # "\nCannot verify if dataset and installed environment versions match"\ + # ) + # elif env_system_version != env_meta_version: + # log_warning( + # "Dataset and installed environment version mismatch!"\ + # "\nDataset environment version: {meta}"\ + # "\nInstalled environment version: {sys}".format( + # sys=env_system_version, + # meta=env_meta_version, + # ) + # ) + + +# def is_robosuite_env(env_meta=None, env_type=None, env=None): +# """ +# Determines whether the environment is a robosuite environment. Accepts +# either env_meta, env_type, or env. +# """ +# return check_env_type(type_to_check=1, env_meta=env_meta, env_type=env_type, env=env) + + +def create_env( + env_type, + env_name, + render=False, + render_offscreen=False, + use_image_obs=False, + env_lang=None, + **kwargs, +): + """ + Create environment. + + Args: + env_type (int): the type of environment, which determines the env class that will + be instantiated. Should be a value in EB.EnvType. + + env_name (str): name of environment + + render (bool): if True, environment supports on-screen rendering + + render_offscreen (bool): if True, environment supports off-screen rendering. This + is forced to be True if @use_image_obs is True. + + use_image_obs (bool): if True, environment is expected to render rgb image observations + on every env.step call. Set this to False for efficiency reasons, if image + observations are not required. + + env_lang: TODO documentation + """ + + # note: pass @postprocess_visual_obs True, to make sure images are processed for network inputs + env_class = get_env_class(env_type=env_type) + env = env_class( + env_name=env_name, + render=render, + render_offscreen=render_offscreen, + use_image_obs=use_image_obs, + postprocess_visual_obs=True, + env_lang=env_lang, + **kwargs, + ) + print("Created environment with name {}".format(env_name)) + print("Action size is {}".format(env.action_dimension)) + return env + + +def create_env_from_metadata( + env_meta, + env_name=None, + render=False, + render_offscreen=False, + use_image_obs=False, + seed=None, +): + """ + Create environment. + + Args: + env_meta (dict): environment metadata, which should be loaded from demonstration + hdf5 with @FileUtils.get_env_metadata_from_dataset or from checkpoint (see + @FileUtils.env_from_checkpoint). Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + + env_name (str): name of environment. Only needs to be provided if making a different + environment from the one in @env_meta. + + render (bool): if True, environment supports on-screen rendering + + render_offscreen (bool): if True, environment supports off-screen rendering. This + is forced to be True if @use_image_obs is True. + + use_image_obs (bool): if True, environment is expected to render rgb image observations + on every env.step call. Set this to False for efficiency reasons, if image + observations are not required. + """ + if env_name is None: + env_name = env_meta["env_name"] + env_type = get_env_type(env_meta=env_meta) + env_kwargs = env_meta["env_kwargs"] + env_kwargs["env_name"] = env_name + env_lang = env_meta.get("env_lang", None) + + if seed is not None: + env_kwargs["seed"] = seed + + env = create_env( + env_type=env_type, + render=render, + render_offscreen=render_offscreen, + use_image_obs=use_image_obs, + env_lang=env_lang, + **env_kwargs, + ) + check_env_version(env, env_meta) + return env + + +def create_env_for_data_processing( + env_meta, + camera_names, + camera_height, + camera_width, + reward_shaping, + seed=None, +): + """ + Creates environment for processing dataset observations and rewards. + + Args: + env_meta (dict): environment metadata, which should be loaded from demonstration + hdf5 with @FileUtils.get_env_metadata_from_dataset or from checkpoint (see + @FileUtils.env_from_checkpoint). Contains 3 keys: + + :`'env_name'`: name of environment + :`'type'`: type of environment, should be a value in EB.EnvType + :`'env_kwargs'`: dictionary of keyword arguments to pass to environment constructor + + camera_names (list of st): list of camera names that correspond to image observations + + camera_height (int): camera height for all cameras + + camera_width (int): camera width for all cameras + + reward_shaping (bool): if True, use shaped environment rewards, else use sparse task completion rewards + """ + env_name = env_meta["env_name"] + env_type = get_env_type(env_meta=env_meta) + env_kwargs = env_meta["env_kwargs"] + env_class = get_env_class(env_type=env_type) + + # remove possibly redundant values in kwargs + env_kwargs = deepcopy(env_kwargs) + env_kwargs.pop("env_name", None) + env_kwargs.pop("camera_names", None) + env_kwargs.pop("camera_height", None) + env_kwargs.pop("camera_width", None) + env_kwargs.pop("reward_shaping", None) + + if seed is not None: + env_kwargs["seed"] = seed + + env = env_class.create_for_data_processing( + env_name=env_name, + camera_names=camera_names, + camera_height=camera_height, + camera_width=camera_width, + reward_shaping=reward_shaping, + **env_kwargs, + ) + check_env_version(env, env_meta) + return env + + +def wrap_env_from_config(env, config): + """ + Wraps environment using the provided Config object to determine which wrappers + to use (if any). + """ + if config.train.frame_stack > 1: + from robomimic.envs.wrappers import FrameStackWrapper + + env = FrameStackWrapper(env, num_frames=config.train.frame_stack) + + return env diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_env_wrapper.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_env_wrapper.py new file mode 100644 index 0000000000000000000000000000000000000000..4a3a835ee02ddab35cc58c16698ed31862a8aa9f --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_env_wrapper.py @@ -0,0 +1,474 @@ +""" +This file contains the robosuite environment wrapper that is used +to provide a standardized environment API for training policies and interacting +with metadata present in datasets. +""" +import json +import numpy as np +from copy import deepcopy + +import robosuite +import robocasa.utils.robomimic.robomimic_obs_utils as ObsUtils + + +class EnvRobocasa: + """Wrapper class for robosuite environments (https://github.com/ARISE-Initiative/robosuite)""" + + def __init__( + self, + env_name, + render=False, + render_offscreen=False, + use_image_obs=False, + postprocess_visual_obs=True, + env_lang=None, + **kwargs, + ): + """ + Args: + env_name (str): name of environment. Only needs to be provided if making a different + environment from the one in @env_meta. + + render (bool): if True, environment supports on-screen rendering + + render_offscreen (bool): if True, environment supports off-screen rendering. This + is forced to be True if @env_meta["use_images"] is True. + + use_image_obs (bool): if True, environment is expected to render rgb image observations + on every env.step call. Set this to False for efficiency reasons, if image + observations are not required. + + postprocess_visual_obs (bool): if True, postprocess image observations + to prepare for learning. This should only be False when extracting observations + for saving to a dataset (to save space on RGB images for example). + + lang: TODO add documentation + """ + self.postprocess_visual_obs = postprocess_visual_obs + + # robosuite version check + self._is_v1 = robosuite.__version__.split(".")[0] == "1" + if self._is_v1: + assert ( + int(robosuite.__version__.split(".")[1]) >= 2 + ), "only support robosuite v0.3 and v1.2+" + + kwargs = deepcopy(kwargs) + + # update kwargs based on passed arguments + update_kwargs = dict( + has_renderer=render, + has_offscreen_renderer=(render_offscreen or use_image_obs), + ignore_done=True, + use_object_obs=True, + use_camera_obs=use_image_obs, + camera_depths=False, + ) + kwargs.update(update_kwargs) + + if self._is_v1: + if kwargs["has_offscreen_renderer"]: + """ + remove reliance on egl_probe, may cause issues + # ensure that we select the correct GPU device for rendering by testing for EGL rendering + # NOTE: this package should be installed from this link (https://github.com/StanfordVL/egl_probe) + import egl_probe + valid_gpu_devices = egl_probe.get_available_devices() + if len(valid_gpu_devices) > 0: + kwargs["render_gpu_device_id"] = valid_gpu_devices[0] + """ + pass + else: + # make sure gripper visualization is turned off (we almost always want this for learning) + kwargs["gripper_visualization"] = False + del kwargs["camera_depths"] + kwargs["camera_depth"] = False # rename kwarg + + self._env_name = env_name + self._init_kwargs = deepcopy(kwargs) + self.env = robosuite.make(self._env_name, **kwargs) + self.base_env = self.env # for mimicgen + self.env_lang = env_lang + + if self._is_v1: + # Make sure joint position observations and eef vel observations are active + for ob_name in self.env.observation_names: + if ("joint_pos" in ob_name) or ("eef_vel" in ob_name): + self.env.modify_observable( + observable_name=ob_name, attribute="active", modifier=True + ) + + def step(self, action): + """ + Step in the environment with an action. + + Args: + action (np.array): action to take + + Returns: + observation (dict): new observation dictionary + reward (float): reward for this step + done (bool): whether the task is done + info (dict): extra information + """ + obs, r, done, info = self.env.step(action) + obs = self.get_observation(obs) + info["is_success"] = self.is_success() + return obs, r, self.is_done(), info + + def reset(self, unset_ep_meta=True): + """ + Reset environment. + + Args: + unset_ep_meta (np.array): whether to unset any episode meta data + + Returns: + observation (dict): initial observation dictionary. + """ + if unset_ep_meta and hasattr(self.env, "unset_ep_meta"): + # unset the ep meta to clear out any ep meta that was previously set + self.env.unset_ep_meta() + + di = self.env.reset() + + # keep track of episode language and embedding + if self.env_lang is not None: + self._ep_lang_str = self.env_lang + elif hasattr(self.env, "get_ep_meta"): + # get ep_meta if applicable + ep_meta = self.env.get_ep_meta() + self._ep_lang_str = ep_meta.get("lang", "dummy") + else: + self._ep_lang_str = "dummy" + + # self._ep_lang_emb = LangUtils.get_lang_emb(self._ep_lang_str) + + return self.get_observation(di) + + # notifies the environment whether or not the next environemnt testing object should update its category + def update_env(self, attr, value): + setattr(self.env, attr, value) + + def reset_to(self, state): + """ + Reset to a specific simulator state. + + Args: + state (dict): current simulator state that contains one or more of: + - states (np.ndarray): initial state of the mujoco environment + - model (str): mujoco scene xml + + Returns: + observation (dict): observation dictionary after setting the simulator state (only + if "states" is in @state) + """ + should_ret = False + if "model" in state: + if state.get("ep_meta", None) is not None: + # set relevant episode information + ep_meta = json.loads(state["ep_meta"]) + else: + ep_meta = {} + + if hasattr( + self.env, "set_attrs_from_ep_meta" + ): # older versions had this function + self.env.set_attrs_from_ep_meta(ep_meta) + elif hasattr(self.env, "set_ep_meta"): # newer versions + self.env.set_ep_meta(ep_meta) + # this reset is necessary. + # while the call to env.reset_from_xml_string does call reset, + # that is only a "soft" reset that doesn't actually reload the model. + self.reset(unset_ep_meta=False) + robosuite_version_id = int(robosuite.__version__.split(".")[1]) + if robosuite_version_id <= 3: + from robosuite.utils.mjcf_utils import postprocess_model_xml + + xml = postprocess_model_xml(state["model"]) + else: + # v1.4 and above use the class-based edit_model_xml function + xml = self.env.edit_model_xml(state["model"]) + + self.env.reset_from_xml_string(xml) + self.env.sim.reset() + if not self._is_v1: + # hide teleop visualization after restoring from model + self.env.sim.model.site_rgba[self.env.eef_site_id] = np.array( + [0.0, 0.0, 0.0, 0.0] + ) + self.env.sim.model.site_rgba[self.env.eef_cylinder_id] = np.array( + [0.0, 0.0, 0.0, 0.0] + ) + if "states" in state: + self.env.sim.set_state_from_flattened(state["states"]) + self.env.sim.forward() + should_ret = True + + # update state as needed + if hasattr(self.env, "update_sites"): + # older versions of environment had update_sites function + self.env.update_sites() + if hasattr(self.env, "update_state"): + # later versions renamed this to update_state + self.env.update_state() + + if "goal" in state: + self.set_goal(**state["goal"]) + if should_ret: + # only return obs if we've done a forward call - otherwise the observations will be garbage + return self.get_observation() + return None + + def render(self, mode="human", height=None, width=None, camera_name=None): + """ + Render from simulation to either an on-screen window or off-screen to RGB array. + + Args: + mode (str): pass "human" for on-screen rendering or "rgb_array" for off-screen rendering + height (int): height of image to render - only used if mode is "rgb_array" + width (int): width of image to render - only used if mode is "rgb_array" + camera_name (str): camera name to use for rendering + """ + # if camera_name is None, infer from initial env kwargs + if camera_name is None: + camera_name = self._init_kwargs.get("camera_names", ["agentview"])[0] + + if mode == "human": + cam_id = self.env.sim.model.camera_name2id(camera_name) + self.env.viewer.set_camera(cam_id) + return self.env.render() + elif mode == "rgb_array": + return self.env.sim.render( + height=height, width=width, camera_name=camera_name + )[::-1] + else: + raise NotImplementedError("mode={} is not implemented".format(mode)) + + def get_observation(self, di=None): + """ + Get current environment observation dictionary. + + Args: + di (dict): current raw observation dictionary from robosuite to wrap and provide + as a dictionary. If not provided, will be queried from robosuite. + """ + if di is None: + di = ( + self.env._get_observations(force_update=True) + if self._is_v1 + else self.env._get_observation() + ) + ret = {} + for k in di: + if (k in ObsUtils.OBS_KEYS_TO_MODALITIES) and ObsUtils.key_is_obs_modality( + key=k, obs_modality="rgb" + ): + ret[k] = di[k][::-1] + if self.postprocess_visual_obs: + ret[k] = ObsUtils.process_obs(obs=ret[k], obs_key=k) + + # "object" key contains object information + if "object-state" in di: + ret["object"] = np.array(di["object-state"]) + + if self._is_v1: + for robot in self.env.robots: + # add all robot-arm-specific observations. Note the (k not in ret) check + # ensures that we don't accidentally add robot wrist images a second time + pf = robot.robot_model.naming_prefix + for k in di: + if ( + k.startswith(pf) + and (k not in ret) + and (not k.endswith("proprio-state")) + ): + ret[k] = np.array(di[k]) + else: + # minimal proprioception for older versions of robosuite + ret["proprio"] = np.array(di["robot-state"]) + ret["eef_pos"] = np.array(di["eef_pos"]) + ret["eef_quat"] = np.array(di["eef_quat"]) + ret["gripper_qpos"] = np.array(di["gripper_qpos"]) + + # ret["lang_emb"] = np.array(self._ep_lang_emb) + return ret + + def get_state(self): + """ + Get current environment simulator state as a dictionary. Should be compatible with @reset_to. + """ + xml = self.env.sim.model.get_xml() # model xml file + state = np.array(self.env.sim.get_state().flatten()) # simulator state + info = dict(model=xml, states=state) + if hasattr(self.env, "get_ep_meta"): + # get ep_meta if applicable + info["ep_meta"] = json.dumps(self.env.get_ep_meta(), indent=4) + return info + + def get_reward(self): + """ + Get current reward. + """ + return self.env.reward() + + def get_goal(self): + """ + Get goal observation. Not all environments support this. + """ + return self.get_observation(self.env._get_goal()) + + def set_goal(self, **kwargs): + """ + Set goal observation with external specification. Not all environments support this. + """ + return self.env.set_goal(**kwargs) + + def is_done(self): + """ + Check if the task is done (not necessarily successful). + """ + + # Robosuite envs always rollout to fixed horizon. + return False + + def is_success(self): + """ + Check if the task condition(s) is reached. Should return a dictionary + { str: bool } with at least a "task" key for the overall task success, + and additional optional keys corresponding to other task criteria. + """ + succ = self.env._check_success() + if isinstance(succ, dict): + assert "task" in succ + return succ + return {"task": succ} + + @property + def action_dimension(self): + """ + Returns dimension of actions (int). + """ + return self.env.action_spec[0].shape[0] + + @property + def name(self): + """ + Returns name of environment name (str). + """ + return self._env_name + + @property + def type(self): + """ + Returns environment type (int) for this kind of environment. + This helps identify this env class. + """ + # return EB.EnvType.ROBOSUITE_TYPE + return 1 # hardcode value for now + + @property + def version(self): + """ + Returns version of robosuite used for this environment, eg. 1.2.0 + """ + return robosuite.__version__ + + def serialize(self): + """ + Save all information needed to re-instantiate this environment in a dictionary. + This is the same as @env_meta - environment metadata stored in hdf5 datasets, + and used in utils/env_utils.py. + """ + return dict( + env_name=self.name, + env_version=self.version, + type=self.type, + env_kwargs=deepcopy(self._init_kwargs), + ) + + @classmethod + def create_for_data_processing( + cls, + env_name, + camera_names, + camera_height, + camera_width, + reward_shaping, + **kwargs, + ): + """ + Create environment for processing datasets, which includes extracting + observations, labeling dense / sparse rewards, and annotating dones in + transitions. + + Args: + env_name (str): name of environment + camera_names (list of str): list of camera names that correspond to image observations + camera_height (int): camera height for all cameras + camera_width (int): camera width for all cameras + reward_shaping (bool): if True, use shaped environment rewards, else use sparse task completion rewards + """ + is_v1 = robosuite.__version__.split(".")[0] == "1" + has_camera = len(camera_names) > 0 + + new_kwargs = { + "reward_shaping": reward_shaping, + } + + if has_camera: + if is_v1: + new_kwargs["camera_names"] = list(camera_names) + new_kwargs["camera_heights"] = camera_height + new_kwargs["camera_widths"] = camera_width + else: + assert len(camera_names) == 1 + if has_camera: + new_kwargs["camera_name"] = camera_names[0] + new_kwargs["camera_height"] = camera_height + new_kwargs["camera_width"] = camera_width + + kwargs.update(new_kwargs) + + # also initialize obs utils so it knows which modalities are image modalities + image_modalities = list(camera_names) + if is_v1: + image_modalities = ["{}_image".format(cn) for cn in camera_names] + elif has_camera: + # v0.3 only had support for one image, and it was named "rgb" + assert len(image_modalities) == 1 + image_modalities = ["rgb"] + obs_modality_specs = { + "obs": { + "low_dim": [], # technically unused, so we don't have to specify all of them + "rgb": image_modalities, + } + } + ObsUtils.initialize_obs_utils_with_obs_specs(obs_modality_specs) + + # note that @postprocess_visual_obs is False since this env's images will be written to a dataset + return cls( + env_name=env_name, + render=False, + render_offscreen=has_camera, + use_image_obs=has_camera, + postprocess_visual_obs=False, + **kwargs, + ) + + @property + def rollout_exceptions(self): + """ + Return tuple of exceptions to except when doing rollouts. This is useful to ensure + that the entire training run doesn't crash because of a bad policy that causes unstable + simulation computations. + """ + return Exception + + def __repr__(self): + """ + Pretty-print env description. + """ + return ( + self.name + "\n" + json.dumps(self._init_kwargs, sort_keys=True, indent=4) + ) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_obs_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_obs_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..273eda6013ce083bde03abb0f06c228edc6d82d4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_obs_utils.py @@ -0,0 +1,1072 @@ +""" +A collection of utilities for working with observation dictionaries and +different kinds of modalities such as images. +""" +import numpy as np +from copy import deepcopy +from collections import OrderedDict + +import torch +import torch.nn.functional as F + +import robocasa.utils.robomimic.robomimic_tensor_utils as TU + +# MACRO FOR VALID IMAGE CHANNEL SIZES +VALID_IMAGE_CHANNEL_DIMS = {1, 3} # depth, rgb + +# DO NOT MODIFY THIS! +# This keeps track of observation types (modalities) - and is populated on call to @initialize_obs_utils_with_obs_specs. +# This will be a dictionary that maps observation modality (e.g. low_dim, rgb) to a list of observation +# keys under that observation modality. +OBS_MODALITIES_TO_KEYS = None + +# DO NOT MODIFY THIS! +# This keeps track of observation types (modalities) - and is populated on call to @initialize_obs_utils_with_obs_specs. +# This will be a dictionary that maps observation keys to their corresponding observation modality +# (e.g. low_dim, rgb) +OBS_KEYS_TO_MODALITIES = None + +# DO NOT MODIFY THIS +# This holds the default encoder kwargs that will be used if none are passed at runtime for any given network +DEFAULT_ENCODER_KWARGS = None + +# DO NOT MODIFY THIS +# This holds the registered observation modality classes +OBS_MODALITY_CLASSES = {} + +# DO NOT MODIFY THIS +# This global dict stores mapping from observation encoder / randomizer network name to class. +# We keep track of these registries to enable automated class inference at runtime, allowing +# users to simply extend our base encoder / randomizer class and refer to that class in string form +# in their config, without having to manually register their class internally. +# This also future-proofs us for any additional encoder / randomizer classes we would +# like to add ourselves. +OBS_ENCODER_CORES = {"None": None} # Include default None +OBS_RANDOMIZERS = {"None": None} # Include default None + + +def register_obs_key(target_class): + assert ( + target_class not in OBS_MODALITY_CLASSES + ), f"Already registered modality {target_class}!" + OBS_MODALITY_CLASSES[target_class.name] = target_class + + +def register_encoder_core(target_class): + assert ( + target_class not in OBS_ENCODER_CORES + ), f"Already registered obs encoder core {target_class}!" + OBS_ENCODER_CORES[target_class.__name__] = target_class + + +def register_randomizer(target_class): + assert ( + target_class not in OBS_RANDOMIZERS + ), f"Already registered obs randomizer {target_class}!" + OBS_RANDOMIZERS[target_class.__name__] = target_class + + +class ObservationKeyToModalityDict(dict): + """ + Custom dictionary class with the sole additional purpose of automatically registering new "keys" at runtime + without breaking. This is mainly for backwards compatibility, where certain keys such as "latent", "actions", etc. + are used automatically by certain models (e.g.: VAEs) but were never specified by the user externally in their + config. Thus, this dictionary will automatically handle those keys by implicitly associating them with the low_dim + modality. + """ + + def __getitem__(self, item): + # If a key doesn't already exist, warn the user and add default mapping + if item not in self.keys(): + print( + f"ObservationKeyToModalityDict: {item} not found," + f" adding {item} to mapping with assumed low_dim modality!" + ) + self.__setitem__(item, "low_dim") + return super(ObservationKeyToModalityDict, self).__getitem__(item) + + +def obs_encoder_kwargs_from_config(obs_encoder_config): + """ + Generate a set of args used to create visual backbones for networks + from the observation encoder config. + + Args: + obs_encoder_config (Config): Config object containing relevant encoder information. Should be equivalent to + config.observation.encoder + + Returns: + dict: Processed encoder kwargs + """ + # Loop over each obs modality + # Unlock encoder config + obs_encoder_config.unlock() + for obs_modality, encoder_kwargs in obs_encoder_config.items(): + ### TODO: fix sanity checks. Disabling this code snippet to allow chaining multiple randomizers. + # # First run some sanity checks and store the classes + # for cls_name, cores in zip(("core", "obs_randomizer"), (OBS_ENCODER_CORES, OBS_RANDOMIZERS)): + # # Make sure the requested encoder for each obs_modality exists + # cfg_cls = encoder_kwargs[f"{cls_name}_class"] + # if cfg_cls is not None: + # assert cfg_cls in cores, f"No {cls_name} class with name {cfg_cls} found, must register this class before" \ + # f"creating model!" + # # encoder_kwargs[f"{cls_name}_class"] = cores[cfg_cls] + + # Process core and randomizer kwargs + encoder_kwargs.core_kwargs = ( + dict() + if encoder_kwargs.core_kwargs is None + else deepcopy(encoder_kwargs.core_kwargs) + ) + encoder_kwargs.obs_randomizer_kwargs = ( + dict() + if encoder_kwargs.obs_randomizer_kwargs is None + else deepcopy(encoder_kwargs.obs_randomizer_kwargs) + ) + + # Re-lock keys + obs_encoder_config.lock() + + return dict(obs_encoder_config) + + +def initialize_obs_modality_mapping_from_dict(modality_mapping): + """ + This function is an alternative to @initialize_obs_utils_with_obs_specs, that allows manually setting of modalities. + NOTE: Only one of these should be called at runtime -- not both! (Note that all training scripts that use a config) + automatically handle obs modality mapping, so using this function is usually unnecessary) + + Args: + modality_mapping (dict): Maps modality string names (e.g.: rgb, low_dim, etc.) to a list of observation + keys that should belong to that modality + """ + global OBS_KEYS_TO_MODALITIES, OBS_MODALITIES_TO_KEYS + + OBS_KEYS_TO_MODALITIES = ObservationKeyToModalityDict() + OBS_MODALITIES_TO_KEYS = dict() + + for mod, keys in modality_mapping.items(): + OBS_MODALITIES_TO_KEYS[mod] = deepcopy(keys) + OBS_KEYS_TO_MODALITIES.update({k: mod for k in keys}) + + +def initialize_obs_utils_with_obs_specs(obs_modality_specs): + """ + This function should be called before using any observation key-specific + functions in this file, in order to make sure that all utility + functions are aware of the observation modalities (e.g. which ones + are low-dimensional, which ones are rgb, etc.). + + It constructs two dictionaries: (1) that map observation modality (e.g. low_dim, rgb) to + a list of observation keys under that modality, and (2) that maps the inverse, specific + observation keys to their corresponding observation modality. + + Input should be a nested dictionary (or list of such dicts) with the following structure: + + obs_variant (str): + obs_modality (str): observation keys (list) + ... + ... + + Example: + { + "obs": { + "low_dim": ["robot0_eef_pos", "robot0_eef_quat"], + "rgb": ["agentview_image", "robot0_eye_in_hand"], + } + "goal": { + "low_dim": ["robot0_eef_pos"], + "rgb": ["agentview_image"] + } + } + + In the example, raw observations consist of low-dim and rgb modalities, with + the robot end effector pose under low-dim, and the agentview and wrist camera + images under rgb, while goal observations also consist of low-dim and rgb modalities, + with a subset of the raw observation keys per modality. + + Args: + obs_modality_specs (dict or list): A nested dictionary (see docstring above for an example) + or a list of nested dictionaries. Accepting a list as input makes it convenient for + situations where multiple modules may each have their own modality spec. + """ + global OBS_KEYS_TO_MODALITIES, OBS_MODALITIES_TO_KEYS + + OBS_KEYS_TO_MODALITIES = ObservationKeyToModalityDict() + + # accept one or more spec dictionaries - if it's just one, account for this + if isinstance(obs_modality_specs, dict): + obs_modality_spec_list = [obs_modality_specs] + else: + obs_modality_spec_list = obs_modality_specs + + # iterates over observation specs + obs_modality_mapping = {} + for obs_modality_spec in obs_modality_spec_list: + # iterates over observation variants (e.g. observations, goals, subgoals) + for obs_modalities in obs_modality_spec.values(): + for obs_modality, obs_keys in obs_modalities.items(): + # add all keys for each obs modality to the corresponding list in obs_modality_mapping + if obs_modality not in obs_modality_mapping: + obs_modality_mapping[obs_modality] = [] + obs_modality_mapping[obs_modality] += obs_keys + # loop over each modality, and add to global dict if it doesn't exist yet + for obs_key in obs_keys: + if obs_key not in OBS_KEYS_TO_MODALITIES: + OBS_KEYS_TO_MODALITIES[obs_key] = obs_modality + # otherwise, run sanity check to make sure we don't have conflicting, duplicate entries + else: + assert OBS_KEYS_TO_MODALITIES[obs_key] == obs_modality, ( + f"Cannot register obs key {obs_key} with modality {obs_modality}; " + f"already exists with corresponding modality {OBS_KEYS_TO_MODALITIES[obs_key]}" + ) + + # remove duplicate entries and store in global mapping + OBS_MODALITIES_TO_KEYS = { + obs_modality: list(set(obs_modality_mapping[obs_modality])) + for obs_modality in obs_modality_mapping + } + + print("\n============= Initialized Observation Utils with Obs Spec =============\n") + for obs_modality, obs_keys in OBS_MODALITIES_TO_KEYS.items(): + print("using obs modality: {} with keys: {}".format(obs_modality, obs_keys)) + + +def initialize_default_obs_encoder(obs_encoder_config): + """ + Initializes the default observation encoder kwarg information to be used by all networks if no values are manually + specified at runtime. + + Args: + obs_encoder_config (Config): Observation encoder config to use. + Should be equivalent to config.observation.encoder + """ + global DEFAULT_ENCODER_KWARGS + DEFAULT_ENCODER_KWARGS = obs_encoder_kwargs_from_config(obs_encoder_config) + + +def initialize_obs_utils_with_config(config): + """ + Utility function to parse config and call @initialize_obs_utils_with_obs_specs and + @initialize_default_obs_encoder_kwargs with the correct arguments. + + Args: + config (BaseConfig instance): config object + """ + if config.algo_name == "hbc": + obs_modality_specs = [ + config.observation.planner.modalities, + config.observation.actor.modalities, + ] + obs_encoder_config = config.observation.actor.encoder + elif config.algo_name == "iris": + obs_modality_specs = [ + config.observation.value_planner.planner.modalities, + config.observation.value_planner.value.modalities, + config.observation.actor.modalities, + ] + obs_encoder_config = config.observation.actor.encoder + else: + obs_modality_specs = [config.observation.modalities] + obs_encoder_config = config.observation.encoder + initialize_obs_utils_with_obs_specs(obs_modality_specs=obs_modality_specs) + initialize_default_obs_encoder(obs_encoder_config=obs_encoder_config) + + +def key_is_obs_modality(key, obs_modality): + """ + Check if observation key corresponds to modality @obs_modality. + + Args: + key (str): obs key name to check + obs_modality (str): observation modality - e.g.: "low_dim", "rgb" + """ + assert ( + OBS_KEYS_TO_MODALITIES is not None + ), "error: must call ObsUtils.initialize_obs_utils_with_obs_config first" + return OBS_KEYS_TO_MODALITIES[key] == obs_modality + + +def center_crop(im, t_h, t_w): + """ + Takes a center crop of an image. + + Args: + im (np.array or torch.Tensor): image of shape (..., height, width, channel) + t_h (int): height of crop + t_w (int): width of crop + + Returns: + im (np.array or torch.Tensor): center cropped image + """ + assert im.shape[-3] >= t_h and im.shape[-2] >= t_w + assert im.shape[-1] in [1, 3] + crop_h = int((im.shape[-3] - t_h) / 2) + crop_w = int((im.shape[-2] - t_w) / 2) + return im[..., crop_h : crop_h + t_h, crop_w : crop_w + t_w, :] + + +def batch_image_hwc_to_chw(im): + """ + Channel swap for images - useful for preparing images for + torch training. + + Args: + im (np.array or torch.Tensor): image of shape (batch, height, width, channel) + or (height, width, channel) + + Returns: + im (np.array or torch.Tensor): image of shape (batch, channel, height, width) + or (channel, height, width) + """ + start_dims = np.arange(len(im.shape) - 3).tolist() + s = start_dims[-1] if len(start_dims) > 0 else -1 + if isinstance(im, np.ndarray): + return im.transpose(start_dims + [s + 3, s + 1, s + 2]) + else: + return im.permute(start_dims + [s + 3, s + 1, s + 2]) + + +def batch_image_chw_to_hwc(im): + """ + Inverse of channel swap in @batch_image_hwc_to_chw. + + Args: + im (np.array or torch.Tensor): image of shape (batch, channel, height, width) + or (channel, height, width) + + Returns: + im (np.array or torch.Tensor): image of shape (batch, height, width, channel) + or (height, width, channel) + """ + start_dims = np.arange(len(im.shape) - 3).tolist() + s = start_dims[-1] if len(start_dims) > 0 else -1 + if isinstance(im, np.ndarray): + return im.transpose(start_dims + [s + 2, s + 3, s + 1]) + else: + return im.permute(start_dims + [s + 2, s + 3, s + 1]) + + +def process_obs(obs, obs_modality=None, obs_key=None): + """ + Process observation @obs corresponding to @obs_modality modality (or implicitly inferred from @obs_key) + to prepare for network input. + + Note that either obs_modality OR obs_key must be specified! + + If both are specified, obs_key will override obs_modality + + Args: + obs (np.array or torch.Tensor): Observation to process. Leading batch dimension is optional + obs_modality (str): Observation modality (e.g.: depth, image, low_dim, etc.) + obs_key (str): Name of observation from which to infer @obs_modality + + Returns: + processed_obs (np.array or torch.Tensor): processed observation + """ + assert ( + obs_modality is not None or obs_key is not None + ), "Either obs_modality or obs_key must be specified!" + if obs_key is not None: + obs_modality = OBS_KEYS_TO_MODALITIES[obs_key] + return OBS_MODALITY_CLASSES[obs_modality].process_obs(obs) + + +def process_obs_dict(obs_dict): + """ + Process observations in observation dictionary to prepare for network input. + + Args: + obs_dict (dict): dictionary mapping observation keys to np.array or + torch.Tensor. Leading batch dimensions are optional. + + Returns: + new_dict (dict): dictionary where observation keys have been processed by their corresponding processors + """ + return { + k: process_obs(obs=obs, obs_key=k) for k, obs in obs_dict.items() + } # shallow copy + + +def process_frame(frame, channel_dim, scale): + """ + Given frame fetched from dataset, process for network input. Converts array + to float (from uint8), normalizes pixels from range [0, @scale] to [0, 1], and channel swaps + from (H, W, C) to (C, H, W). + + Args: + frame (np.array or torch.Tensor): frame array + channel_dim (int): Number of channels to sanity check for + scale (float): Value to normalize inputs by + + Returns: + processed_frame (np.array or torch.Tensor): processed frame + """ + # Channel size should either be 3 (RGB) or 1 (depth) + assert frame.shape[-1] == channel_dim + frame = TU.to_float(frame) + frame /= scale + frame = frame.clip(0.0, 1.0) + frame = batch_image_hwc_to_chw(frame) + + return frame + + +def unprocess_obs(obs, obs_modality=None, obs_key=None): + """ + Prepare observation @obs corresponding to @obs_modality modality (or implicitly inferred from @obs_key) + to prepare for deployment. + + Note that either obs_modality OR obs_key must be specified! + + If both are specified, obs_key will override obs_modality + + Args: + obs (np.array or torch.Tensor): Observation to unprocess. Leading batch dimension is optional + obs_modality (str): Observation modality (e.g.: depth, image, low_dim, etc.) + obs_key (str): Name of observation from which to infer @obs_modality + + Returns: + unprocessed_obs (np.array or torch.Tensor): unprocessed observation + """ + assert ( + obs_modality is not None or obs_key is not None + ), "Either obs_modality or obs_key must be specified!" + if obs_key is not None: + obs_modality = OBS_KEYS_TO_MODALITIES[obs_key] + return OBS_MODALITY_CLASSES[obs_modality].unprocess_obs(obs) + + +def unprocess_obs_dict(obs_dict): + """ + Prepare processed observation dictionary for saving to dataset. Inverse of + @process_obs. + + Args: + obs_dict (dict): dictionary mapping observation keys to np.array or + torch.Tensor. Leading batch dimensions are optional. + + Returns: + new_dict (dict): dictionary where observation keys have been unprocessed by + their respective unprocessor methods + """ + return { + k: unprocess_obs(obs=obs, obs_key=k) for k, obs in obs_dict.items() + } # shallow copy + + +def unprocess_frame(frame, channel_dim, scale): + """ + Given frame prepared for network input, prepare for saving to dataset. + Inverse of @process_frame. + + Args: + frame (np.array or torch.Tensor): frame array + channel_dim (int): What channel dimension should be (used for sanity check) + scale (float): Scaling factor to apply during denormalization + + Returns: + unprocessed_frame (np.array or torch.Tensor): frame passed through + inverse operation of @process_frame + """ + assert frame.shape[-3] == channel_dim # check for channel dimension + frame = batch_image_chw_to_hwc(frame) + frame *= scale + return frame + + +def get_processed_shape(obs_modality, input_shape): + """ + Given observation modality @obs_modality and expected inputs of shape @input_shape (excluding batch dimension), return the + expected processed observation shape resulting from process_{obs_modality}. + + Args: + obs_modality (str): Observation modality to use (e.g.: low_dim, rgb, depth, etc...) + input_shape (list of int): Expected input dimensions, excluding the batch dimension + + Returns: + list of int: expected processed input shape + """ + return list(process_obs(obs=np.zeros(input_shape), obs_modality=obs_modality).shape) + + +def normalize_dict(dict, normalization_stats): + """ + Normalize dict using the provided "offset" and "scale" entries + for each observation key. The dictionary will be + modified in-place. + + Args: + dict (dict): dictionary mapping key to np.array or + torch.Tensor. Leading batch dimensions are optional. + + normalization_stats (dict): this should map keys to dicts + with a "offset" and "scale" of shape (1, ...) where ... is the default + shape for the dict value. + + Returns: + dict (dict): obs dict with normalized arrays + """ + + # ensure we have statistics for each modality key in the dict + assert set(dict.keys()).issubset(normalization_stats) + + for m in dict: + offset = normalization_stats[m]["offset"] + scale = normalization_stats[m]["scale"] + + # check shape consistency + shape_len_diff = len(offset.shape) - len(dict[m].shape) + assert shape_len_diff in [0, 1], "shape length mismatch in @normalize_dict" + # if dict has no leading batch dim, check shapes match exactly, else allow first dim to broadcast + assert ( + offset.shape[1:] == dict[m].shape[(1 - shape_len_diff) :] + ), "shape mismatch in @normalize_dict" + + # handle case where obs dict is not batched by removing stats batch dimension + if shape_len_diff == 1: + offset = offset[0] + scale = scale[0] + + dict[m] = (dict[m] - offset) / scale + + return dict + + +def unnormalize_dict(dict, normalization_stats): + """ + Unnormalize dict using the provided "offset" and "scale" entries + for each observation key. The dictionary will be + modified in-place. + + Args: + dict (dict): dictionary mapping key to np.array or + torch.Tensor. Leading batch dimensions are optional. + + normalization_stats (dict): this should map keys to dicts + with a "offset" and "scale" of shape (1, ...) where ... is the default + shape for the dict value. + + Returns: + dict (dict): obs dict with normalized arrays + """ + + # ensure we have statistics for each modality key in the dict + assert set(dict.keys()).issubset(normalization_stats) + + for m in dict: + offset = normalization_stats[m]["offset"] + scale = normalization_stats[m]["scale"] + + # check shape consistency + shape_len_diff = len(offset.shape) - len(dict[m].shape) + assert shape_len_diff in [0, 1], "shape length mismatch in @unnormalize_dict" + # if dict has no leading batch dim, check shapes match exactly, else allow first dim to broadcast + assert ( + offset.shape[1:] == dict[m].shape[(1 - shape_len_diff) :] + ), "shape mismatch in @unnormalize_dict" + + # handle case where obs dict is not batched by removing stats batch dimension + if shape_len_diff == 1: + offset = offset[0] + scale = scale[0] + + dict[m] = (dict[m] * scale) + offset + + return dict + + +def has_modality(modality, obs_keys): + """ + Returns True if @modality is present in the list of observation keys @obs_keys. + + Args: + modality (str): modality to check for, e.g.: rgb, depth, etc. + obs_keys (list): list of observation keys + """ + for k in obs_keys: + if key_is_obs_modality(k, obs_modality=modality): + return True + return False + + +def repeat_and_stack_observation(obs_dict, n): + """ + Given an observation dictionary and a desired repeat value @n, + this function will return a new observation dictionary where + each modality is repeated @n times and the copies are + stacked in the first dimension. + + For example, if a batch of 3 observations comes in, and n is 2, + the output will look like [ob1; ob1; ob2; ob2; ob3; ob3] in + each modality. + + Args: + obs_dict (dict): dictionary mapping observation key to np.array or + torch.Tensor. Leading batch dimensions are optional. + + n (int): number to repeat by + + Returns: + repeat_obs_dict (dict): repeated obs dict + """ + return TU.repeat_by_expand_at(obs_dict, repeats=n, dim=0) + + +def crop_image_from_indices(images, crop_indices, crop_height, crop_width): + """ + Crops images at the locations specified by @crop_indices. Crops will be + taken across all channels. + + Args: + images (torch.Tensor): batch of images of shape [..., C, H, W] + + crop_indices (torch.Tensor): batch of indices of shape [..., N, 2] where + N is the number of crops to take per image and each entry corresponds + to the pixel height and width of where to take the crop. Note that + the indices can also be of shape [..., 2] if only 1 crop should + be taken per image. Leading dimensions must be consistent with + @images argument. Each index specifies the top left of the crop. + Values must be in range [0, H - CH - 1] x [0, W - CW - 1] where + H and W are the height and width of @images and CH and CW are + @crop_height and @crop_width. + + crop_height (int): height of crop to take + + crop_width (int): width of crop to take + + Returns: + crops (torch.Tesnor): cropped images of shape [..., C, @crop_height, @crop_width] + """ + + # make sure length of input shapes is consistent + assert crop_indices.shape[-1] == 2 + ndim_im_shape = len(images.shape) + ndim_indices_shape = len(crop_indices.shape) + assert (ndim_im_shape == ndim_indices_shape + 1) or ( + ndim_im_shape == ndim_indices_shape + 2 + ) + + # maybe pad so that @crop_indices is shape [..., N, 2] + is_padded = False + if ndim_im_shape == ndim_indices_shape + 2: + crop_indices = crop_indices.unsqueeze(-2) + is_padded = True + + # make sure leading dimensions between images and indices are consistent + assert images.shape[:-3] == crop_indices.shape[:-2] + + device = images.device + image_c, image_h, image_w = images.shape[-3:] + num_crops = crop_indices.shape[-2] + + # make sure @crop_indices are in valid range + assert (crop_indices[..., 0] >= 0).all().item() + assert (crop_indices[..., 0] < (image_h - crop_height)).all().item() + assert (crop_indices[..., 1] >= 0).all().item() + assert (crop_indices[..., 1] < (image_w - crop_width)).all().item() + + # convert each crop index (ch, cw) into a list of pixel indices that correspond to the entire window. + + # 2D index array with columns [0, 1, ..., CH - 1] and shape [CH, CW] + crop_ind_grid_h = torch.arange(crop_height).to(device) + crop_ind_grid_h = TU.unsqueeze_expand_at(crop_ind_grid_h, size=crop_width, dim=-1) + # 2D index array with rows [0, 1, ..., CW - 1] and shape [CH, CW] + crop_ind_grid_w = torch.arange(crop_width).to(device) + crop_ind_grid_w = TU.unsqueeze_expand_at(crop_ind_grid_w, size=crop_height, dim=0) + # combine into shape [CH, CW, 2] + crop_in_grid = torch.cat( + (crop_ind_grid_h.unsqueeze(-1), crop_ind_grid_w.unsqueeze(-1)), dim=-1 + ) + + # Add above grid with the offset index of each sampled crop to get 2d indices for each crop. + # After broadcasting, this will be shape [..., N, CH, CW, 2] and each crop has a [CH, CW, 2] + # shape array that tells us which pixels from the corresponding source image to grab. + grid_reshape = [1] * len(crop_indices.shape[:-1]) + [crop_height, crop_width, 2] + all_crop_inds = crop_indices.unsqueeze(-2).unsqueeze(-2) + crop_in_grid.reshape( + grid_reshape + ) + + # For using @torch.gather, convert to flat indices from 2D indices, and also + # repeat across the channel dimension. To get flat index of each pixel to grab for + # each sampled crop, we just use the mapping: ind = h_ind * @image_w + w_ind + all_crop_inds = ( + all_crop_inds[..., 0] * image_w + all_crop_inds[..., 1] + ) # shape [..., N, CH, CW] + all_crop_inds = TU.unsqueeze_expand_at( + all_crop_inds, size=image_c, dim=-3 + ) # shape [..., N, C, CH, CW] + all_crop_inds = TU.flatten( + all_crop_inds, begin_axis=-2 + ) # shape [..., N, C, CH * CW] + + # Repeat and flatten the source images -> [..., N, C, H * W] and then use gather to index with crop pixel inds + images_to_crop = TU.unsqueeze_expand_at(images, size=num_crops, dim=-4) + images_to_crop = TU.flatten(images_to_crop, begin_axis=-2) + crops = torch.gather(images_to_crop, dim=-1, index=all_crop_inds) + # [..., N, C, CH * CW] -> [..., N, C, CH, CW] + reshape_axis = len(crops.shape) - 1 + crops = TU.reshape_dimensions( + crops, + begin_axis=reshape_axis, + end_axis=reshape_axis, + target_dims=(crop_height, crop_width), + ) + + if is_padded: + # undo padding -> [..., C, CH, CW] + crops = crops.squeeze(-4) + return crops + + +def sample_random_image_crops( + images, crop_height, crop_width, num_crops, pos_enc=False +): + """ + For each image, randomly sample @num_crops crops of size (@crop_height, @crop_width), from + @images. + + Args: + images (torch.Tensor): batch of images of shape [..., C, H, W] + + crop_height (int): height of crop to take + + crop_width (int): width of crop to take + + num_crops (n): number of crops to sample + + pos_enc (bool): if True, also add 2 channels to the outputs that gives a spatial + encoding of the original source pixel locations. This means that the + output crops will contain information about where in the source image + it was sampled from. + + Returns: + crops (torch.Tensor): crops of shape (..., @num_crops, C, @crop_height, @crop_width) + if @pos_enc is False, otherwise (..., @num_crops, C + 2, @crop_height, @crop_width) + + crop_inds (torch.Tensor): sampled crop indices of shape (..., N, 2) + """ + device = images.device + + # maybe add 2 channels of spatial encoding to the source image + source_im = images + if pos_enc: + # spatial encoding [y, x] in [0, 1] + h, w = source_im.shape[-2:] + pos_y, pos_x = torch.meshgrid(torch.arange(h), torch.arange(w)) + pos_y = pos_y.float().to(device) / float(h) + pos_x = pos_x.float().to(device) / float(w) + position_enc = torch.stack((pos_y, pos_x)) # shape [C, H, W] + + # unsqueeze and expand to match leading dimensions -> shape [..., C, H, W] + leading_shape = source_im.shape[:-3] + position_enc = position_enc[(None,) * len(leading_shape)] + position_enc = position_enc.expand(*leading_shape, -1, -1, -1) + + # concat across channel dimension with input + source_im = torch.cat((source_im, position_enc), dim=-3) + + # make sure sample boundaries ensure crops are fully within the images + image_c, image_h, image_w = source_im.shape[-3:] + max_sample_h = image_h - crop_height + max_sample_w = image_w - crop_width + + # Sample crop locations for all tensor dimensions up to the last 3, which are [C, H, W]. + # Each gets @num_crops samples - typically this will just be the batch dimension (B), so + # we will sample [B, N] indices, but this supports having more than one leading dimension, + # or possibly no leading dimension. + # + # Trick: sample in [0, 1) with rand, then re-scale to [0, M) and convert to long to get sampled ints + crop_inds_h = ( + max_sample_h * torch.rand(*source_im.shape[:-3], num_crops).to(device) + ).long() + crop_inds_w = ( + max_sample_w * torch.rand(*source_im.shape[:-3], num_crops).to(device) + ).long() + crop_inds = torch.cat( + (crop_inds_h.unsqueeze(-1), crop_inds_w.unsqueeze(-1)), dim=-1 + ) # shape [..., N, 2] + + crops = crop_image_from_indices( + images=source_im, + crop_indices=crop_inds, + crop_height=crop_height, + crop_width=crop_width, + ) + + return crops, crop_inds + + +class Modality: + """ + Observation Modality class to encapsulate necessary functions needed to + process observations of this modality + """ + + # observation keys to associate with this modality + keys = set() + + # Custom processing function that should prepare raw observations of this modality for training + _custom_obs_processor = None + + # Custom unprocessing function that should prepare observations of this modality used during training for deployment + _custom_obs_unprocessor = None + + # Name of this modality -- must be set by subclass! + name = None + + def __init_subclass__(cls, **kwargs): + """ + Hook method to automatically register all valid subclasses so we can keep track of valid modalities + """ + assert ( + cls.name is not None + ), f"Name of modality {cls.__name__} must be specified!" + register_obs_key(cls) + + @classmethod + def set_keys(cls, keys): + """ + Sets the observation keys associated with this modality. + + Args: + keys (list or set): observation keys to associate with this modality + """ + cls.keys = {k for k in keys} + + @classmethod + def add_keys(cls, keys): + """ + Adds the observation @keys associated with this modality to the current set of keys. + + Args: + keys (list or set): observation keys to add to associate with this modality + """ + for key in keys: + cls.keys.add(key) + + @classmethod + def set_obs_processor(cls, processor=None): + """ + Sets the processor for this observation modality. If @processor is set to None, then + the obs processor will use the default one (self.process_obs(...)). Otherwise, @processor + should be a function to process this corresponding observation modality. + + Args: + processor (function or None): If not None, should be function that takes in either a + np.array or torch.Tensor and output the processed array / tensor. If None, will reset + to the default processor (self.process_obs(...)) + """ + cls._custom_obs_processor = processor + + @classmethod + def set_obs_unprocessor(cls, unprocessor=None): + """ + Sets the unprocessor for this observation modality. If @unprocessor is set to None, then + the obs unprocessor will use the default one (self.unprocess_obs(...)). Otherwise, @unprocessor + should be a function to process this corresponding observation modality. + + Args: + unprocessor (function or None): If not None, should be function that takes in either a + np.array or torch.Tensor and output the unprocessed array / tensor. If None, will reset + to the default unprocessor (self.unprocess_obs(...)) + """ + cls._custom_obs_unprocessor = unprocessor + + @classmethod + def _default_obs_processor(cls, obs): + """ + Default processing function for this obs modality. + + Note that this function is overridden by self.custom_obs_processor (a function with identical inputs / outputs) + if it is not None. + + Args: + obs (np.array or torch.Tensor): raw observation, which may include a leading batch dimension + + Returns: + np.array or torch.Tensor: processed observation + """ + raise NotImplementedError + + @classmethod + def _default_obs_unprocessor(cls, obs): + """ + Default unprocessing function for this obs modality. + + Note that this function is overridden by self.custom_obs_unprocessor + (a function with identical inputs / outputs) if it is not None. + + Args: + obs (np.array or torch.Tensor): processed observation, which may include a leading batch dimension + + Returns: + np.array or torch.Tensor: unprocessed observation + """ + raise NotImplementedError + + @classmethod + def process_obs(cls, obs): + """ + Prepares an observation @obs of this modality for network input. + + Args: + obs (np.array or torch.Tensor): raw observation, which may include a leading batch dimension + + Returns: + np.array or torch.Tensor: processed observation + """ + processor = ( + cls._custom_obs_processor + if cls._custom_obs_processor is not None + else cls._default_obs_processor + ) + return processor(obs) + + @classmethod + def unprocess_obs(cls, obs): + """ + Prepares an observation @obs of this modality for deployment. + + Args: + obs (np.array or torch.Tensor): processed observation, which may include a leading batch dimension + + Returns: + np.array or torch.Tensor: unprocessed observation + """ + unprocessor = ( + cls._custom_obs_unprocessor + if cls._custom_obs_unprocessor is not None + else cls._default_obs_unprocessor + ) + return unprocessor(obs) + + @classmethod + def process_obs_from_dict(cls, obs_dict, inplace=True): + """ + Receives a dictionary of keyword mapped observations @obs_dict, and processes the observations with keys + corresponding to this modality. A copy will be made of the received dictionary unless @inplace is True + + Args: + obs_dict (dict): Dictionary mapping observation keys to observations + inplace (bool): If True, will modify @obs_dict in place, otherwise, will create a copy + + Returns: + dict: observation dictionary with processed observations corresponding to this modality + """ + if inplace: + obs_dict = deepcopy(obs_dict) + # Loop over all keys and process the ones corresponding to this modality + for key, obs in obs_dict.values(): + if key in cls.keys: + obs_dict[key] = cls.process_obs(obs) + + return obs_dict + + +class ImageModality(Modality): + """ + Modality for RGB image observations + """ + + name = "rgb" + + @classmethod + def _default_obs_processor(cls, obs): + """ + Given image fetched from dataset, process for network input. Converts array + to float (from uint8), normalizes pixels from range [0, 255] to [0, 1], and channel swaps + from (H, W, C) to (C, H, W). + + Args: + obs (np.array or torch.Tensor): image array + + Returns: + processed_obs (np.array or torch.Tensor): processed image + """ + return process_frame(frame=obs, channel_dim=3, scale=255.0) + + @classmethod + def _default_obs_unprocessor(cls, obs): + """ + Given image prepared for network input, prepare for saving to dataset. + Inverse of @process_frame. + + Args: + obs (np.array or torch.Tensor): image array + + Returns: + unprocessed_obs (np.array or torch.Tensor): image passed through + inverse operation of @process_frame + """ + return TU.to_uint8(unprocess_frame(frame=obs, channel_dim=3, scale=255.0)) + + +class DepthModality(Modality): + """ + Modality for depth observations + """ + + name = "depth" + + @classmethod + def _default_obs_processor(cls, obs): + """ + Given depth fetched from dataset, process for network input. Converts array + to float (from uint8), normalizes pixels from range [0, 1] to [0, 1], and channel swaps + from (H, W, C) to (C, H, W). + + Args: + obs (np.array or torch.Tensor): depth array + + Returns: + processed_obs (np.array or torch.Tensor): processed depth + """ + return process_frame(frame=obs, channel_dim=1, scale=1.0) + + @classmethod + def _default_obs_unprocessor(cls, obs): + """ + Given depth prepared for network input, prepare for saving to dataset. + Inverse of @process_depth. + + Args: + obs (np.array or torch.Tensor): depth array + + Returns: + unprocessed_obs (np.array or torch.Tensor): depth passed through + inverse operation of @process_depth + """ + return unprocess_frame(frame=obs, channel_dim=1, scale=1.0) + + +class ScanModality(Modality): + """ + Modality for scan observations + """ + + name = "scan" + + @classmethod + def _default_obs_processor(cls, obs): + return obs + + @classmethod + def _default_obs_unprocessor(cls, obs): + return obs + + +class LowDimModality(Modality): + """ + Modality for low dimensional observations + """ + + name = "low_dim" + + @classmethod + def _default_obs_processor(cls, obs): + return obs + + @classmethod + def _default_obs_unprocessor(cls, obs): + return obs diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_tensor_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_tensor_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..9fc968448f1c70c0a555bfe3ce37d59a441d614c --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_tensor_utils.py @@ -0,0 +1,985 @@ +""" +A collection of utilities for working with nested tensor structures consisting +of numpy arrays and torch tensors. +""" +import collections +import numpy as np +import torch + + +def recursive_dict_list_tuple_apply(x, type_func_dict): + """ + Recursively apply functions to a nested dictionary or list or tuple, given a dictionary of + {data_type: function_to_apply}. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + type_func_dict (dict): a mapping from data types to the functions to be + applied for each data type. + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + assert list not in type_func_dict + assert tuple not in type_func_dict + assert dict not in type_func_dict + + if isinstance(x, (dict, collections.OrderedDict)): + new_x = ( + collections.OrderedDict() + if isinstance(x, collections.OrderedDict) + else dict() + ) + for k, v in x.items(): + new_x[k] = recursive_dict_list_tuple_apply(v, type_func_dict) + return new_x + elif isinstance(x, (list, tuple)): + ret = [recursive_dict_list_tuple_apply(v, type_func_dict) for v in x] + if isinstance(x, tuple): + ret = tuple(ret) + return ret + else: + for t, f in type_func_dict.items(): + if isinstance(x, t): + return f(x) + else: + raise NotImplementedError("Cannot handle data type %s" % str(type(x))) + + +def map_tensor(x, func): + """ + Apply function @func to torch.Tensor objects in a nested dictionary or + list or tuple. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + func (function): function to apply to each tensor + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: func, + type(None): lambda x: x, + }, + ) + + +def map_ndarray(x, func): + """ + Apply function @func to np.ndarray objects in a nested dictionary or + list or tuple. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + func (function): function to apply to each array + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + np.ndarray: func, + type(None): lambda x: x, + }, + ) + + +def map_tensor_ndarray(x, tensor_func, ndarray_func): + """ + Apply function @tensor_func to torch.Tensor objects and @ndarray_func to + np.ndarray objects in a nested dictionary or list or tuple. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + tensor_func (function): function to apply to each tensor + ndarray_Func (function): function to apply to each array + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: tensor_func, + np.ndarray: ndarray_func, + type(None): lambda x: x, + }, + ) + + +def clone(x): + """ + Clones all torch tensors and numpy arrays in nested dictionary or list + or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.clone(), + np.ndarray: lambda x: x.copy(), + type(None): lambda x: x, + }, + ) + + +def detach(x): + """ + Detaches all torch tensors in nested dictionary or list + or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.detach(), + }, + ) + + +def to_batch(x): + """ + Introduces a leading batch dimension of 1 for all torch tensors and numpy + arrays in nested dictionary or list or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x[None, ...], + np.ndarray: lambda x: x[None, ...], + type(None): lambda x: x, + }, + ) + + +def to_sequence(x): + """ + Introduces a time dimension of 1 at dimension 1 for all torch tensors and numpy + arrays in nested dictionary or list or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x[:, None, ...], + np.ndarray: lambda x: x[:, None, ...], + type(None): lambda x: x, + }, + ) + + +def index_at_time(x, ind): + """ + Indexes all torch tensors and numpy arrays in dimension 1 with index @ind in + nested dictionary or list or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + ind (int): index + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x[:, ind, ...], + np.ndarray: lambda x: x[:, ind, ...], + type(None): lambda x: x, + }, + ) + + +def unsqueeze(x, dim): + """ + Adds dimension of size 1 at dimension @dim in all torch tensors and numpy arrays + in nested dictionary or list or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + dim (int): dimension + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.unsqueeze(dim=dim), + np.ndarray: lambda x: np.expand_dims(x, axis=dim), + type(None): lambda x: x, + }, + ) + + +def contiguous(x): + """ + Makes all torch tensors and numpy arrays contiguous in nested dictionary or + list or tuple and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.contiguous(), + np.ndarray: lambda x: np.ascontiguousarray(x), + type(None): lambda x: x, + }, + ) + + +def to_device(x, device): + """ + Sends all torch tensors in nested dictionary or list or tuple to device + @device, and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + device (torch.Device): device to send tensors to + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x, d=device: x.to(d), + type(None): lambda x: x, + }, + ) + + +def to_tensor(x): + """ + Converts all numpy arrays in nested dictionary or list or tuple to + torch tensors (and leaves existing torch Tensors as-is), and returns + a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x, + np.ndarray: lambda x: torch.from_numpy(x), + type(None): lambda x: x, + }, + ) + + +def to_numpy(x): + """ + Converts all torch tensors in nested dictionary or list or tuple to + numpy (and leaves existing numpy arrays as-is), and returns + a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + + def f(tensor): + if tensor.is_cuda: + return tensor.detach().cpu().numpy() + else: + return tensor.detach().numpy() + + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: f, + np.ndarray: lambda x: x, + type(None): lambda x: x, + }, + ) + + +def to_list(x): + """ + Converts all torch tensors and numpy arrays in nested dictionary or list + or tuple to a list, and returns a new nested structure. Useful for + json encoding. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + + def f(tensor): + if tensor.is_cuda: + return tensor.detach().cpu().numpy().tolist() + else: + return tensor.detach().numpy().tolist() + + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: f, + np.ndarray: lambda x: x.tolist(), + type(None): lambda x: x, + }, + ) + + +def to_float(x): + """ + Converts all torch tensors and numpy arrays in nested dictionary or list + or tuple to float type entries, and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.float(), + np.ndarray: lambda x: x.astype(np.float32), + type(None): lambda x: x, + }, + ) + + +def to_uint8(x): + """ + Converts all torch tensors and numpy arrays in nested dictionary or list + or tuple to uint8 type entries, and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.byte(), + np.ndarray: lambda x: x.astype(np.uint8), + type(None): lambda x: x, + }, + ) + + +def to_torch(x, device): + """ + Converts all numpy arrays and torch tensors in nested dictionary or list or tuple to + torch tensors on device @device and returns a new nested structure. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + device (torch.Device): device to send tensors to + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return to_device(to_float(to_tensor(x)), device) + + +def to_one_hot_single(tensor, num_class): + """ + Convert tensor to one-hot representation, assuming a certain number of total class labels. + + Args: + tensor (torch.Tensor): tensor containing integer labels + num_class (int): number of classes + + Returns: + x (torch.Tensor): tensor containing one-hot representation of labels + """ + x = torch.zeros(tensor.size() + (num_class,)).to(tensor.device) + x.scatter_(-1, tensor.unsqueeze(-1), 1) + return x + + +def to_one_hot(tensor, num_class): + """ + Convert all tensors in nested dictionary or list or tuple to one-hot representation, + assuming a certain number of total class labels. + + Args: + tensor (dict or list or tuple): a possibly nested dictionary or list or tuple + num_class (int): number of classes + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return map_tensor(tensor, func=lambda x, nc=num_class: to_one_hot_single(x, nc)) + + +def flatten_single(x, begin_axis=1): + """ + Flatten a tensor in all dimensions from @begin_axis onwards. + + Args: + x (torch.Tensor): tensor to flatten + begin_axis (int): which axis to flatten from + + Returns: + y (torch.Tensor): flattened tensor + """ + fixed_size = x.size()[:begin_axis] + _s = list(fixed_size) + [-1] + return x.reshape(*_s) + + +def flatten(x, begin_axis=1): + """ + Flatten all tensors in nested dictionary or list or tuple, from @begin_axis onwards. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + begin_axis (int): which axis to flatten from + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x, b=begin_axis: flatten_single(x, begin_axis=b), + }, + ) + + +def reshape_dimensions_single(x, begin_axis, end_axis, target_dims): + """ + Reshape selected dimensions in a tensor to a target dimension. + + Args: + x (torch.Tensor): tensor to reshape + begin_axis (int): begin dimension + end_axis (int): end dimension (inclusive) + target_dims (tuple or list): target shape for the range of dimensions + (@begin_axis, @end_axis) + + Returns: + y (torch.Tensor): reshaped tensor + """ + assert begin_axis <= end_axis + assert begin_axis >= 0 + assert end_axis < len(x.shape) + assert isinstance(target_dims, (tuple, list)) + s = x.shape + final_s = [] + for i in range(len(s)): + if i == begin_axis: + final_s.extend(target_dims) + elif i < begin_axis or i > end_axis: + final_s.append(s[i]) + return x.reshape(*final_s) + + +def reshape_dimensions(x, begin_axis, end_axis, target_dims): + """ + Reshape selected dimensions for all tensors in nested dictionary or list or tuple + to a target dimension. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + begin_axis (int): begin dimension + end_axis (int): end dimension (inclusive) + target_dims (tuple or list): target shape for the range of dimensions + (@begin_axis, @end_axis) + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x, b=begin_axis, e=end_axis, t=target_dims: reshape_dimensions_single( + x, begin_axis=b, end_axis=e, target_dims=t + ), + np.ndarray: lambda x, b=begin_axis, e=end_axis, t=target_dims: reshape_dimensions_single( + x, begin_axis=b, end_axis=e, target_dims=t + ), + type(None): lambda x: x, + }, + ) + + +def join_dimensions(x, begin_axis, end_axis): + """ + Joins all dimensions between dimensions (@begin_axis, @end_axis) into a flat dimension, for + all tensors in nested dictionary or list or tuple. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + begin_axis (int): begin dimension + end_axis (int): end dimension + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x, b=begin_axis, e=end_axis: reshape_dimensions_single( + x, begin_axis=b, end_axis=e, target_dims=[-1] + ), + np.ndarray: lambda x, b=begin_axis, e=end_axis: reshape_dimensions_single( + x, begin_axis=b, end_axis=e, target_dims=[-1] + ), + type(None): lambda x: x, + }, + ) + + +def expand_at_single(x, size, dim): + """ + Expand a tensor at a single dimension @dim by @size + + Args: + x (torch.Tensor): input tensor + size (int): size to expand + dim (int): dimension to expand + + Returns: + y (torch.Tensor): expanded tensor + """ + assert dim < x.ndimension() + assert x.shape[dim] == 1 + expand_dims = [-1] * x.ndimension() + expand_dims[dim] = size + return x.expand(*expand_dims) + + +def expand_at(x, size, dim): + """ + Expand all tensors in nested dictionary or list or tuple at a single + dimension @dim by @size. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + size (int): size to expand + dim (int): dimension to expand + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return map_tensor(x, lambda t, s=size, d=dim: expand_at_single(t, s, d)) + + +def unsqueeze_expand_at(x, size, dim): + """ + Unsqueeze and expand a tensor at a dimension @dim by @size. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + size (int): size to expand + dim (int): dimension to unsqueeze and expand + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + x = unsqueeze(x, dim) + return expand_at(x, size, dim) + + +def repeat_by_expand_at(x, repeats, dim): + """ + Repeat a dimension by combining expand and reshape operations. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + repeats (int): number of times to repeat the target dimension + dim (int): dimension to repeat on + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + x = unsqueeze_expand_at(x, repeats, dim + 1) + return join_dimensions(x, dim, dim + 1) + + +def named_reduce_single(x, reduction, dim): + """ + Reduce tensor at a dimension by named reduction functions. + + Args: + x (torch.Tensor): tensor to be reduced + reduction (str): one of ["sum", "max", "mean", "flatten"] + dim (int): dimension to be reduced (or begin axis for flatten) + + Returns: + y (torch.Tensor): reduced tensor + """ + assert x.ndimension() > dim + assert reduction in ["sum", "max", "mean", "flatten"] + if reduction == "flatten": + x = flatten(x, begin_axis=dim) + elif reduction == "max": + x = torch.max(x, dim=dim)[0] # [B, D] + elif reduction == "sum": + x = torch.sum(x, dim=dim) + else: + x = torch.mean(x, dim=dim) + return x + + +def named_reduce(x, reduction, dim): + """ + Reduces all tensors in nested dictionary or list or tuple at a dimension + using a named reduction function. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + reduction (str): one of ["sum", "max", "mean", "flatten"] + dim (int): dimension to be reduced (or begin axis for flatten) + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return map_tensor( + x, func=lambda t, r=reduction, d=dim: named_reduce_single(t, r, d) + ) + + +def gather_along_dim_with_dim_single(x, target_dim, source_dim, indices): + """ + This function indexes out a target dimension of a tensor in a structured way, + by allowing a different value to be selected for each member of a flat index + tensor (@indices) corresponding to a source dimension. This can be interpreted + as moving along the source dimension, using the corresponding index value + in @indices to select values for all other dimensions outside of the + source and target dimensions. A common use case is to gather values + in target dimension 1 for each batch member (target dimension 0). + + Args: + x (torch.Tensor): tensor to gather values for + target_dim (int): dimension to gather values along + source_dim (int): dimension to hold constant and use for gathering values + from the other dimensions + indices (torch.Tensor): flat index tensor with same shape as tensor @x along + @source_dim + + Returns: + y (torch.Tensor): gathered tensor, with dimension @target_dim indexed out + """ + assert len(indices.shape) == 1 + assert x.shape[source_dim] == indices.shape[0] + + # unsqueeze in all dimensions except the source dimension + new_shape = [1] * x.ndimension() + new_shape[source_dim] = -1 + indices = indices.reshape(*new_shape) + + # repeat in all dimensions - but preserve shape of source dimension, + # and make sure target_dimension has singleton dimension + expand_shape = list(x.shape) + expand_shape[source_dim] = -1 + expand_shape[target_dim] = 1 + indices = indices.expand(*expand_shape) + + out = x.gather(dim=target_dim, index=indices) + return out.squeeze(target_dim) + + +def gather_along_dim_with_dim(x, target_dim, source_dim, indices): + """ + Apply @gather_along_dim_with_dim_single to all tensors in a nested + dictionary or list or tuple. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + target_dim (int): dimension to gather values along + source_dim (int): dimension to hold constant and use for gathering values + from the other dimensions + indices (torch.Tensor): flat index tensor with same shape as tensor @x along + @source_dim + + Returns: + y (dict or list or tuple): new nested dict-list-tuple + """ + return map_tensor( + x, + lambda y, t=target_dim, s=source_dim, i=indices: gather_along_dim_with_dim_single( + y, t, s, i + ), + ) + + +def gather_sequence_single(seq, indices): + """ + Given a tensor with leading dimensions [B, T, ...], gather an element from each sequence in + the batch given an index for each sequence. + + Args: + seq (torch.Tensor): tensor with leading dimensions [B, T, ...] + indices (torch.Tensor): tensor indices of shape [B] + + Return: + y (torch.Tensor): indexed tensor of shape [B, ....] + """ + return gather_along_dim_with_dim_single( + seq, target_dim=1, source_dim=0, indices=indices + ) + + +def gather_sequence(seq, indices): + """ + Given a nested dictionary or list or tuple, gathers an element from each sequence of the batch + for tensors with leading dimensions [B, T, ...]. + + Args: + seq (dict or list or tuple): a possibly nested dictionary or list or tuple with tensors + of leading dimensions [B, T, ...] + indices (torch.Tensor): tensor indices of shape [B] + + Returns: + y (dict or list or tuple): new nested dict-list-tuple with tensors of shape [B, ...] + """ + return gather_along_dim_with_dim(seq, target_dim=1, source_dim=0, indices=indices) + + +def pad_sequence_single(seq, padding, batched=False, pad_same=True, pad_values=None): + """ + Pad input tensor or array @seq in the time dimension (dimension 1). + + Args: + seq (np.ndarray or torch.Tensor): sequence to be padded + padding (tuple): begin and end padding, e.g. [1, 1] pads both begin and end of the sequence by 1 + batched (bool): if sequence has the batch dimension + pad_same (bool): if pad by duplicating + pad_values (scalar or (ndarray, Tensor)): values to be padded if not pad_same + + Returns: + padded sequence (np.ndarray or torch.Tensor) + """ + assert isinstance(seq, (np.ndarray, torch.Tensor)) + assert pad_same or pad_values is not None + if pad_values is not None: + assert isinstance(pad_values, float) + repeat_func = np.repeat if isinstance(seq, np.ndarray) else torch.repeat_interleave + concat_func = np.concatenate if isinstance(seq, np.ndarray) else torch.cat + ones_like_func = np.ones_like if isinstance(seq, np.ndarray) else torch.ones_like + seq_dim = 1 if batched else 0 + + begin_pad = [] + end_pad = [] + + if padding[0] > 0: + pad = seq[[0]] if pad_same else ones_like_func(seq[[0]]) * pad_values + begin_pad.append(repeat_func(pad, padding[0], seq_dim)) + if padding[1] > 0: + pad = seq[[-1]] if pad_same else ones_like_func(seq[[-1]]) * pad_values + end_pad.append(repeat_func(pad, padding[1], seq_dim)) + + return concat_func(begin_pad + [seq] + end_pad, seq_dim) + + +def pad_sequence(seq, padding, batched=False, pad_same=True, pad_values=None): + """ + Pad a nested dictionary or list or tuple of sequence tensors in the time dimension (dimension 1). + + Args: + seq (dict or list or tuple): a possibly nested dictionary or list or tuple with tensors + of leading dimensions [B, T, ...] + padding (tuple): begin and end padding, e.g. [1, 1] pads both begin and end of the sequence by 1 + batched (bool): if sequence has the batch dimension + pad_same (bool): if pad by duplicating + pad_values (scalar or (ndarray, Tensor)): values to be padded if not pad_same + + Returns: + padded sequence (dict or list or tuple) + """ + return recursive_dict_list_tuple_apply( + seq, + { + torch.Tensor: lambda x, p=padding, b=batched, ps=pad_same, pv=pad_values: pad_sequence_single( + x, p, b, ps, pv + ), + np.ndarray: lambda x, p=padding, b=batched, ps=pad_same, pv=pad_values: pad_sequence_single( + x, p, b, ps, pv + ), + type(None): lambda x: x, + }, + ) + + +def assert_size_at_dim_single(x, size, dim, msg): + """ + Ensure that array or tensor @x has size @size in dim @dim. + + Args: + x (np.ndarray or torch.Tensor): input array or tensor + size (int): size that tensors should have at @dim + dim (int): dimension to check + msg (str): text to display if assertion fails + """ + assert x.shape[dim] == size, msg + + +def assert_size_at_dim(x, size, dim, msg): + """ + Ensure that arrays and tensors in nested dictionary or list or tuple have + size @size in dim @dim. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + size (int): size that tensors should have at @dim + dim (int): dimension to check + """ + map_tensor(x, lambda t, s=size, d=dim, m=msg: assert_size_at_dim_single(t, s, d, m)) + + +def get_shape(x): + """ + Get all shapes of arrays and tensors in nested dictionary or list or tuple. + + Args: + x (dict or list or tuple): a possibly nested dictionary or list or tuple + + Returns: + y (dict or list or tuple): new nested dict-list-tuple that contains each array or + tensor's shape + """ + return recursive_dict_list_tuple_apply( + x, + { + torch.Tensor: lambda x: x.shape, + np.ndarray: lambda x: x.shape, + type(None): lambda x: x, + }, + ) + + +def list_of_flat_dict_to_dict_of_list(list_of_dict): + """ + Helper function to go from a list of flat dictionaries to a dictionary of lists. + By "flat" we mean that none of the values are dictionaries, but are numpy arrays, + floats, etc. + + Args: + list_of_dict (list): list of flat dictionaries + + Returns: + dict_of_list (dict): dictionary of lists + """ + assert isinstance(list_of_dict, list) + dic = collections.OrderedDict() + for i in range(len(list_of_dict)): + for k in list_of_dict[i]: + if k not in dic: + dic[k] = [] + dic[k].append(list_of_dict[i][k]) + return dic + + +def flatten_nested_dict_list(d, parent_key="", sep="_", item_key=""): + """ + Flatten a nested dict or list to a list. + + For example, given a dict + { + a: 1 + b: { + c: 2 + } + c: 3 + } + + the function would return [(a, 1), (b_c, 2), (c, 3)] + + Args: + d (dict, list): a nested dict or list to be flattened + parent_key (str): recursion helper + sep (str): separator for nesting keys + item_key (str): recursion helper + Returns: + list: a list of (key, value) tuples + """ + items = [] + if isinstance(d, (tuple, list)): + new_key = parent_key + sep + item_key if len(parent_key) > 0 else item_key + for i, v in enumerate(d): + items.extend(flatten_nested_dict_list(v, new_key, sep=sep, item_key=str(i))) + return items + elif isinstance(d, dict): + new_key = parent_key + sep + item_key if len(parent_key) > 0 else item_key + for k, v in d.items(): + assert isinstance(k, str) + items.extend(flatten_nested_dict_list(v, new_key, sep=sep, item_key=k)) + return items + else: + new_key = parent_key + sep + item_key if len(parent_key) > 0 else item_key + return [(new_key, d)] + + +def time_distributed( + inputs, op, activation=None, inputs_as_kwargs=False, inputs_as_args=False, **kwargs +): + """ + Apply function @op to all tensors in nested dictionary or list or tuple @inputs in both the + batch (B) and time (T) dimension, where the tensors are expected to have shape [B, T, ...]. + Will do this by reshaping tensors to [B * T, ...], passing through the op, and then reshaping + outputs to [B, T, ...]. + + Args: + inputs (list or tuple or dict): a possibly nested dictionary or list or tuple with tensors + of leading dimensions [B, T, ...] + op: a layer op that accepts inputs + activation: activation to apply at the output + inputs_as_kwargs (bool): whether to feed input as a kwargs dict to the op + inputs_as_args (bool) whether to feed input as a args list to the op + kwargs (dict): other kwargs to supply to the op + + Returns: + outputs (dict or list or tuple): new nested dict-list-tuple with tensors of leading dimension [B, T]. + """ + batch_size, seq_len = flatten_nested_dict_list(inputs)[0][1].shape[:2] + inputs = join_dimensions(inputs, 0, 1) + if inputs_as_kwargs: + outputs = op(**inputs, **kwargs) + elif inputs_as_args: + outputs = op(*inputs, **kwargs) + else: + outputs = op(inputs, **kwargs) + + if activation is not None: + outputs = map_tensor(outputs, activation) + outputs = reshape_dimensions( + outputs, begin_axis=0, end_axis=0, target_dims=(batch_size, seq_len) + ) + return outputs diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_torch_utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_torch_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..33a9f8d2dffbd8b6e3738ecfad5b63bfe4be5782 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/robomimic/robomimic_torch_utils.py @@ -0,0 +1,758 @@ +""" +This file contains some PyTorch utilities. +""" +import numpy as np +import torch +import torch.optim as optim +import torch.nn.functional as F + + +def soft_update(source, target, tau): + """ + Soft update from the parameters of a @source torch module to a @target torch module + with strength @tau. The update follows target = target * (1 - tau) + source * tau. + + Args: + source (torch.nn.Module): source network to push target network parameters towards + target (torch.nn.Module): target network to update + """ + for target_param, param in zip(target.parameters(), source.parameters()): + target_param.copy_(target_param * (1.0 - tau) + param * tau) + + +def hard_update(source, target): + """ + Hard update @target parameters to match @source. + + Args: + source (torch.nn.Module): source network to provide parameters + target (torch.nn.Module): target network to update parameters for + """ + for target_param, param in zip(target.parameters(), source.parameters()): + target_param.copy_(param) + + +def get_torch_device(try_to_use_cuda): + """ + Return torch device. If using cuda (GPU), will also set cudnn.benchmark to True + to optimize CNNs. + + Args: + try_to_use_cuda (bool): if True and cuda is available, will use GPU + + Returns: + device (torch.Device): device to use for models + """ + if try_to_use_cuda and torch.cuda.is_available(): + torch.backends.cudnn.benchmark = True + device = torch.device("cuda:0") + else: + device = torch.device("cpu") + return device + + +def reparameterize(mu, logvar): + """ + Reparameterize for the backpropagation of z instead of q. + This makes it so that we can backpropagate through the sampling of z from + our encoder when feeding the sampled variable to the decoder. + + (See "The reparameterization trick" section of https://arxiv.org/abs/1312.6114) + + Args: + mu (torch.Tensor): batch of means from the encoder distribution + logvar (torch.Tensor): batch of log variances from the encoder distribution + + Returns: + z (torch.Tensor): batch of sampled latents from the encoder distribution that + support backpropagation + """ + # logvar = \log(\sigma^2) = 2 * \log(\sigma) + # \sigma = \exp(0.5 * logvar) + + # clamped for numerical stability + logstd = (0.5 * logvar).clamp(-4, 15) + std = torch.exp(logstd) + + # Sample \epsilon from normal distribution + # use std to create a new tensor, so we don't have to care + # about running on GPU or not + eps = std.new(std.size()).normal_() + + # Then multiply with the standard deviation and add the mean + z = eps.mul(std).add_(mu) + + return z + + +def optimizer_from_optim_params(net_optim_params, net): + """ + Helper function to return a torch Optimizer from the optim_params + section of the config for a particular network. + + Args: + optim_params (Config): optim_params part of algo_config corresponding + to @net. This determines the optimizer that is created. + + net (torch.nn.Module): module whose parameters this optimizer will be + responsible + + Returns: + optimizer (torch.optim.Optimizer): optimizer + """ + optimizer_type = net_optim_params.get("optimizer_type", "adam") + lr = net_optim_params["learning_rate"]["initial"] + + if optimizer_type == "adam": + return optim.Adam( + params=net.parameters(), + lr=lr, + weight_decay=net_optim_params["regularization"]["L2"], + ) + elif optimizer_type == "adamw": + return optim.AdamW( + params=net.parameters(), + lr=lr, + weight_decay=net_optim_params["regularization"]["L2"], + ) + + +def lr_scheduler_from_optim_params( + net_optim_params, net, optimizer, num_training_steps +): + """ + Helper function to return a LRScheduler from the optim_params + section of the config for a particular network. Returns None + if a scheduler is not needed. + + Args: + optim_params (Config): optim_params part of algo_config corresponding + to @net. This determines whether a learning rate scheduler is created. + + net (torch.nn.Module): module whose parameters this optimizer will be + responsible + + optimizer (torch.optim.Optimizer): optimizer for this net + + Returns: + lr_scheduler (torch.optim.lr_scheduler or None): learning rate scheduler + """ + lr_scheduler_type = net_optim_params["learning_rate"]["scheduler_type"] + + from diffusers.optimization import ( + Union, + SchedulerType, + Optional, + Optimizer, + TYPE_TO_SCHEDULER_FUNCTION, + ) + + num_warmup_steps = net_optim_params["learning_rate"].get("num_warmup_steps", 10000) + + if lr_scheduler_type == "linear": + decay_factor = net_optim_params["learning_rate"]["decay_factor"] + + return torch.optim.lr_scheduler.LinearLR( + optimizer, + start_factor=1.0, + end_factor=decay_factor, + total_iters=num_warmup_steps, + ) + elif lr_scheduler_type == "multistep": + epoch_schedule = net_optim_params["learning_rate"]["epoch_schedule"] + decay_factor = net_optim_params["learning_rate"]["decay_factor"] + + assert len(epoch_schedule) > 0 + + return optim.lr_scheduler.MultiStepLR( + optimizer=optimizer, + milestones=epoch_schedule, + gamma=decay_factor, + ) + elif lr_scheduler_type == "constant": + name = SchedulerType(lr_scheduler_type) + schedule_func = TYPE_TO_SCHEDULER_FUNCTION[name] + return schedule_func( + optimizer, + ) + elif lr_scheduler_type == "constant_with_warmup": + name = SchedulerType(lr_scheduler_type) + schedule_func = TYPE_TO_SCHEDULER_FUNCTION[name] + return schedule_func( + optimizer, + num_warmup_steps=num_warmup_steps, + ) + elif lr_scheduler_type == "cosine": + name = SchedulerType(lr_scheduler_type) + schedule_func = TYPE_TO_SCHEDULER_FUNCTION[name] + return schedule_func( + optimizer, + num_warmup_steps=num_warmup_steps, + num_training_steps=num_training_steps, + ) + elif lr_scheduler_type is None: + return None + else: + raise ValueError("Invalid LR scheduler type: {}".format(lr_scheduler_type)) + + +def backprop_for_loss(net, optim, loss, max_grad_norm=None, retain_graph=False): + """ + Backpropagate loss and update parameters for network with + name @name. + + Args: + net (torch.nn.Module): network to update + + optim (torch.optim.Optimizer): optimizer to use + + loss (torch.Tensor): loss to use for backpropagation + + max_grad_norm (float): if provided, used to clip gradients + + retain_graph (bool): if True, graph is not freed after backward call + + Returns: + grad_norms (float): average gradient norms from backpropagation + """ + + # backprop + optim.zero_grad() + loss.backward(retain_graph=retain_graph) + + # gradient clipping + if max_grad_norm is not None: + torch.nn.utils.clip_grad_norm_(net.parameters(), max_grad_norm) + + # compute grad norms + grad_norms = 0.0 + for p in net.parameters(): + # only clip gradients for parameters for which requires_grad is True + if p.grad is not None: + grad_norms += p.grad.data.norm(2).pow(2).item() + + # step + optim.step() + + return grad_norms + + +def rot_6d_to_axis_angle(rot_6d): + """ + Converts tensor with rot_6d representation to axis-angle representation. + """ + rot_mat = rotation_6d_to_matrix(rot_6d) + rot = matrix_to_axis_angle(rot_mat) + return rot + + +def rot_6d_to_euler_angles(rot_6d, convention="XYZ"): + """ + Converts tensor with rot_6d representation to euler representation. + """ + rot_mat = rotation_6d_to_matrix(rot_6d) + rot = matrix_to_euler_angles(rot_mat, convention=convention) + return rot + + +def axis_angle_to_rot_6d(axis_angle): + """ + Converts tensor with rot_6d representation to axis-angle representation. + """ + rot_mat = axis_angle_to_matrix(axis_angle) + rot_6d = matrix_to_rotation_6d(rot_mat) + return rot_6d + + +def euler_angles_to_rot_6d(euler_angles, convention="XYZ"): + """ + Converts tensor with rot_6d representation to euler representation. + """ + rot_mat = euler_angles_to_matrix(euler_angles, convention="XYZ") + rot_6d = matrix_to_rotation_6d(rot_mat) + return rot_6d + + +def euler_angles_to_quat(euler_angles, convention="XYZ"): + """ + Converts tensor with rot_6d representation to euler representation. + """ + rot_mat = euler_angles_to_matrix(euler_angles, convention="XYZ") + quat = matrix_to_quaternion(rot_mat) + return quat + + +class dummy_context_mgr: + """ + A dummy context manager - useful for having conditional scopes (such + as @maybe_no_grad). Nothing happens in this scope. + """ + + def __enter__(self): + return None + + def __exit__(self, exc_type, exc_value, traceback): + return False + + +def maybe_no_grad(no_grad): + """ + Args: + no_grad (bool): if True, the returned context will be torch.no_grad(), otherwise + it will be a dummy context + """ + return torch.no_grad() if no_grad else dummy_context_mgr() + + +""" +The following utility functions were taken from PyTorch3D: +https://github.com/facebookresearch/pytorch3d/blob/d84f274a0822da969668d00e831870fd88327845/pytorch3d/transforms/rotation_conversions.py +""" + + +def _sqrt_positive_part(x: torch.Tensor) -> torch.Tensor: + """ + Returns torch.sqrt(torch.max(0, x)) + but with a zero subgradient where x is 0. + """ + ret = torch.zeros_like(x) + positive_mask = x > 0 + ret[positive_mask] = torch.sqrt(x[positive_mask]) + return ret + + +def quaternion_to_matrix(quaternions: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as quaternions to rotation matrices. + Args: + quaternions: quaternions with real part first, + as tensor of shape (..., 4). + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + r, i, j, k = torch.unbind(quaternions, -1) + # pyre-fixme[58]: `/` is not supported for operand types `float` and `Tensor`. + two_s = 2.0 / (quaternions * quaternions).sum(-1) + + o = torch.stack( + ( + 1 - two_s * (j * j + k * k), + two_s * (i * j - k * r), + two_s * (i * k + j * r), + two_s * (i * j + k * r), + 1 - two_s * (i * i + k * k), + two_s * (j * k - i * r), + two_s * (i * k - j * r), + two_s * (j * k + i * r), + 1 - two_s * (i * i + j * j), + ), + -1, + ) + return o.reshape(quaternions.shape[:-1] + (3, 3)) + + +def matrix_to_quaternion(matrix: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as rotation matrices to quaternions. + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + Returns: + quaternions with real part first, as tensor of shape (..., 4). + """ + if matrix.size(-1) != 3 or matrix.size(-2) != 3: + raise ValueError(f"Invalid rotation matrix shape {matrix.shape}.") + + batch_dim = matrix.shape[:-2] + m00, m01, m02, m10, m11, m12, m20, m21, m22 = torch.unbind( + matrix.reshape(batch_dim + (9,)), dim=-1 + ) + + q_abs = _sqrt_positive_part( + torch.stack( + [ + 1.0 + m00 + m11 + m22, + 1.0 + m00 - m11 - m22, + 1.0 - m00 + m11 - m22, + 1.0 - m00 - m11 + m22, + ], + dim=-1, + ) + ) + + # we produce the desired quaternion multiplied by each of r, i, j, k + quat_by_rijk = torch.stack( + [ + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([q_abs[..., 0] ** 2, m21 - m12, m02 - m20, m10 - m01], dim=-1), + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([m21 - m12, q_abs[..., 1] ** 2, m10 + m01, m02 + m20], dim=-1), + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([m02 - m20, m10 + m01, q_abs[..., 2] ** 2, m12 + m21], dim=-1), + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([m10 - m01, m20 + m02, m21 + m12, q_abs[..., 3] ** 2], dim=-1), + ], + dim=-2, + ) + + # We floor here at 0.1 but the exact level is not important; if q_abs is small, + # the candidate won't be picked. + flr = torch.tensor(0.1).to(dtype=q_abs.dtype, device=q_abs.device) + quat_candidates = quat_by_rijk / (2.0 * q_abs[..., None].max(flr)) + + # if not for numerical problems, quat_candidates[i] should be same (up to a sign), + # forall i; we pick the best-conditioned one (with the largest denominator) + + return quat_candidates[ + F.one_hot(q_abs.argmax(dim=-1), num_classes=4) > 0.5, : + ].reshape(batch_dim + (4,)) + + +def axis_angle_to_matrix(axis_angle: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as axis/angle to rotation matrices. + Args: + axis_angle: Rotations given as a vector in axis angle form, + as a tensor of shape (..., 3), where the magnitude is + the angle turned anticlockwise in radians around the + vector's direction. + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + return quaternion_to_matrix(axis_angle_to_quaternion(axis_angle)) + + +def matrix_to_axis_angle(matrix: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as rotation matrices to axis/angle. + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + Returns: + Rotations given as a vector in axis angle form, as a tensor + of shape (..., 3), where the magnitude is the angle + turned anticlockwise in radians around the vector's + direction. + """ + return quaternion_to_axis_angle(matrix_to_quaternion(matrix)) + + +def axis_angle_to_quaternion(axis_angle: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as axis/angle to quaternions. + Args: + axis_angle: Rotations given as a vector in axis angle form, + as a tensor of shape (..., 3), where the magnitude is + the angle turned anticlockwise in radians around the + vector's direction. + Returns: + quaternions with real part first, as tensor of shape (..., 4). + """ + angles = torch.norm(axis_angle, p=2, dim=-1, keepdim=True) + half_angles = angles * 0.5 + eps = 1e-6 + small_angles = angles.abs() < eps + sin_half_angles_over_angles = torch.empty_like(angles) + sin_half_angles_over_angles[~small_angles] = ( + torch.sin(half_angles[~small_angles]) / angles[~small_angles] + ) + # for x small, sin(x/2) is about x/2 - (x/2)^3/6 + # so sin(x/2)/x is about 1/2 - (x*x)/48 + sin_half_angles_over_angles[small_angles] = ( + 0.5 - (angles[small_angles] * angles[small_angles]) / 48 + ) + quaternions = torch.cat( + [torch.cos(half_angles), axis_angle * sin_half_angles_over_angles], dim=-1 + ) + return quaternions + + +def quaternion_to_axis_angle(quaternions: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as quaternions to axis/angle. + Args: + quaternions: quaternions with real part first, + as tensor of shape (..., 4). + Returns: + Rotations given as a vector in axis angle form, as a tensor + of shape (..., 3), where the magnitude is the angle + turned anticlockwise in radians around the vector's + direction. + """ + norms = torch.norm(quaternions[..., 1:], p=2, dim=-1, keepdim=True) + half_angles = torch.atan2(norms, quaternions[..., :1]) + angles = 2 * half_angles + eps = 1e-6 + small_angles = angles.abs() < eps + sin_half_angles_over_angles = torch.empty_like(angles) + sin_half_angles_over_angles[~small_angles] = ( + torch.sin(half_angles[~small_angles]) / angles[~small_angles] + ) + # for x small, sin(x/2) is about x/2 - (x/2)^3/6 + # so sin(x/2)/x is about 1/2 - (x*x)/48 + sin_half_angles_over_angles[small_angles] = ( + 0.5 - (angles[small_angles] * angles[small_angles]) / 48 + ) + return quaternions[..., 1:] / sin_half_angles_over_angles + + +def rotation_6d_to_matrix(d6: torch.Tensor) -> torch.Tensor: + """ + Converts 6D rotation representation by Zhou et al. [1] to rotation matrix + using Gram--Schmidt orthogonalization per Section B of [1]. + Args: + d6: 6D rotation representation, of size (*, 6) + Returns: + batch of rotation matrices of size (*, 3, 3) + [1] Zhou, Y., Barnes, C., Lu, J., Yang, J., & Li, H. + On the Continuity of Rotation Representations in Neural Networks. + IEEE Conference on Computer Vision and Pattern Recognition, 2019. + Retrieved from http://arxiv.org/abs/1812.07035 + """ + + a1, a2 = d6[..., :3], d6[..., 3:] + b1 = F.normalize(a1, dim=-1) + b2 = a2 - (b1 * a2).sum(-1, keepdim=True) * b1 + b2 = F.normalize(b2, dim=-1) + b3 = torch.cross(b1, b2, dim=-1) + return torch.stack((b1, b2, b3), dim=-2) + + +def matrix_to_rotation_6d(matrix: torch.Tensor) -> torch.Tensor: + """ + Converts rotation matrices to 6D rotation representation by Zhou et al. [1] + by dropping the last row. Note that 6D representation is not unique. + Args: + matrix: batch of rotation matrices of size (*, 3, 3) + Returns: + 6D rotation representation, of size (*, 6) + [1] Zhou, Y., Barnes, C., Lu, J., Yang, J., & Li, H. + On the Continuity of Rotation Representations in Neural Networks. + IEEE Conference on Computer Vision and Pattern Recognition, 2019. + Retrieved from http://arxiv.org/abs/1812.07035 + """ + batch_dim = matrix.size()[:-2] + return matrix[..., :2, :].clone().reshape(batch_dim + (6,)) + + +def matrix_to_euler_angles(matrix: torch.Tensor, convention: str) -> torch.Tensor: + """ + Convert rotations given as rotation matrices to Euler angles in radians. + + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + convention: Convention string of three uppercase letters. + + Returns: + Euler angles in radians as tensor of shape (..., 3). + """ + if len(convention) != 3: + raise ValueError("Convention must have 3 letters.") + if convention[1] in (convention[0], convention[2]): + raise ValueError(f"Invalid convention {convention}.") + for letter in convention: + if letter not in ("X", "Y", "Z"): + raise ValueError(f"Invalid letter {letter} in convention string.") + if matrix.size(-1) != 3 or matrix.size(-2) != 3: + raise ValueError(f"Invalid rotation matrix shape {matrix.shape}.") + i0 = _index_from_letter(convention[0]) + i2 = _index_from_letter(convention[2]) + tait_bryan = i0 != i2 + if tait_bryan: + central_angle = torch.asin( + matrix[..., i0, i2] * (-1.0 if i0 - i2 in [-1, 2] else 1.0) + ) + else: + central_angle = torch.acos(matrix[..., i0, i0]) + + o = ( + _angle_from_tan( + convention[0], convention[1], matrix[..., i2], False, tait_bryan + ), + central_angle, + _angle_from_tan( + convention[2], convention[1], matrix[..., i0, :], True, tait_bryan + ), + ) + return torch.stack(o, -1) + + +def euler_angles_to_matrix(euler_angles: torch.Tensor, convention: str) -> torch.Tensor: + """ + Convert rotations given as Euler angles in radians to rotation matrices. + + Args: + euler_angles: Euler angles in radians as tensor of shape (..., 3). + convention: Convention string of three uppercase letters from + {"X", "Y", and "Z"}. + + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + if euler_angles.dim() == 0 or euler_angles.shape[-1] != 3: + raise ValueError("Invalid input euler angles.") + if len(convention) != 3: + raise ValueError("Convention must have 3 letters.") + if convention[1] in (convention[0], convention[2]): + raise ValueError(f"Invalid convention {convention}.") + for letter in convention: + if letter not in ("X", "Y", "Z"): + raise ValueError(f"Invalid letter {letter} in convention string.") + matrices = [ + _axis_angle_rotation(c, e) + for c, e in zip(convention, torch.unbind(euler_angles, -1)) + ] + # return functools.reduce(torch.matmul, matrices) + return torch.matmul(torch.matmul(matrices[0], matrices[1]), matrices[2]) + + +def standardize_quaternion(quaternions: torch.Tensor) -> torch.Tensor: + """ + Convert a unit quaternion to a standard form: one in which the real + part is non negative. + + Args: + quaternions: Quaternions with real part first, + as tensor of shape (..., 4). + + Returns: + Standardized quaternions as tensor of shape (..., 4). + """ + return torch.where(quaternions[..., 0:1] < 0, -quaternions, quaternions) + + +def matrix_to_quaternion(matrix: torch.Tensor) -> torch.Tensor: + """ + Convert rotations given as rotation matrices to quaternions. + + Args: + matrix: Rotation matrices as tensor of shape (..., 3, 3). + + Returns: + quaternions with real part first, as tensor of shape (..., 4). + """ + if matrix.size(-1) != 3 or matrix.size(-2) != 3: + raise ValueError(f"Invalid rotation matrix shape {matrix.shape}.") + + batch_dim = matrix.shape[:-2] + m00, m01, m02, m10, m11, m12, m20, m21, m22 = torch.unbind( + matrix.reshape(batch_dim + (9,)), dim=-1 + ) + + q_abs = _sqrt_positive_part( + torch.stack( + [ + 1.0 + m00 + m11 + m22, + 1.0 + m00 - m11 - m22, + 1.0 - m00 + m11 - m22, + 1.0 - m00 - m11 + m22, + ], + dim=-1, + ) + ) + + # we produce the desired quaternion multiplied by each of r, i, j, k + quat_by_rijk = torch.stack( + [ + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([q_abs[..., 0] ** 2, m21 - m12, m02 - m20, m10 - m01], dim=-1), + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([m21 - m12, q_abs[..., 1] ** 2, m10 + m01, m02 + m20], dim=-1), + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([m02 - m20, m10 + m01, q_abs[..., 2] ** 2, m12 + m21], dim=-1), + # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and + # `int`. + torch.stack([m10 - m01, m20 + m02, m21 + m12, q_abs[..., 3] ** 2], dim=-1), + ], + dim=-2, + ) + + # We floor here at 0.1 but the exact level is not important; if q_abs is small, + # the candidate won't be picked. + flr = torch.tensor(0.1).to(dtype=q_abs.dtype, device=q_abs.device) + quat_candidates = quat_by_rijk / (2.0 * q_abs[..., None].max(flr)) + + # if not for numerical problems, quat_candidates[i] should be same (up to a sign), + # forall i; we pick the best-conditioned one (with the largest denominator) + out = quat_candidates[ + F.one_hot(q_abs.argmax(dim=-1), num_classes=4) > 0.5, : + ].reshape(batch_dim + (4,)) + return standardize_quaternion(out) + + +def _index_from_letter(letter: str) -> int: + if letter == "X": + return 0 + if letter == "Y": + return 1 + if letter == "Z": + return 2 + raise ValueError("letter must be either X, Y or Z.") + + +def _angle_from_tan( + axis: str, other_axis: str, data, horizontal: bool, tait_bryan: bool +) -> torch.Tensor: + """ + Extract the first or third Euler angle from the two members of + the matrix which are positive constant times its sine and cosine. + + Args: + axis: Axis label "X" or "Y or "Z" for the angle we are finding. + other_axis: Axis label "X" or "Y or "Z" for the middle axis in the + convention. + data: Rotation matrices as tensor of shape (..., 3, 3). + horizontal: Whether we are looking for the angle for the third axis, + which means the relevant entries are in the same row of the + rotation matrix. If not, they are in the same column. + tait_bryan: Whether the first and third axes in the convention differ. + + Returns: + Euler Angles in radians for each matrix in data as a tensor + of shape (...). + """ + + i1, i2 = {"X": (2, 1), "Y": (0, 2), "Z": (1, 0)}[axis] + if horizontal: + i2, i1 = i1, i2 + even = (axis + other_axis) in ["XY", "YZ", "ZX"] + if horizontal == even: + return torch.atan2(data[..., i1], data[..., i2]) + if tait_bryan: + return torch.atan2(-data[..., i2], data[..., i1]) + return torch.atan2(data[..., i2], -data[..., i1]) + + +def _axis_angle_rotation(axis: str, angle: torch.Tensor) -> torch.Tensor: + """ + Return the rotation matrices for one of the rotations about an axis + of which Euler angles describe, for each value of the angle given. + + Args: + axis: Axis label "X" or "Y or "Z". + angle: any shape tensor of Euler angles in radians + + Returns: + Rotation matrices as tensor of shape (..., 3, 3). + """ + + cos = torch.cos(angle) + sin = torch.sin(angle) + one = torch.ones_like(angle) + zero = torch.zeros_like(angle) + + if axis == "X": + R_flat = (one, zero, zero, zero, cos, -sin, zero, sin, cos) + elif axis == "Y": + R_flat = (cos, zero, sin, zero, one, zero, -sin, zero, cos) + elif axis == "Z": + R_flat = (cos, -sin, zero, sin, cos, zero, zero, zero, one) + else: + raise ValueError("letter must be either X, Y or Z.") + + return torch.stack(R_flat, -1).reshape(angle.shape + (3, 3)) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/texture_swap.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/texture_swap.py new file mode 100644 index 0000000000000000000000000000000000000000..420e6f1264340d6c819465050c0a933c4db05304 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/texture_swap.py @@ -0,0 +1,676 @@ +import inspect +import os +import random +from copy import deepcopy +from pathlib import Path + +import numpy as np +from lxml import etree as ET +from robosuite.utils.mjcf_utils import find_elements + +import robocasa + +TEXTURES_DIR = ( + Path(inspect.getfile(robocasa)).parent / "models" / "assets" / "generative_textures" +) + +CABINET_TEX_NAMES = [ + "flat copy 26.png", + "196415a6-3c0f-4a1f-a644-fc54a6801223.png", + "2a310e7f-8005-4dba-8dea-edb1484e1e28.png", + "flat copy 37.png", + "1fb8c016-b655-48ab-ad53-d6238a745065.png", + "f80067c5-9967-4607-880f-1c4002d400cb.png", + "00846c84-f900-4bdd-897f-3928e7d87dce.png", + "flat copy 38.png", + "54c4d59e-c0b1-4608-a953-568e9ae13409.png", + "flat copy 2.png", + "flat copy 23.png", + "flat copy 16.png", + "251695ed-d413-48fe-817e-c3e02b3ee117.png", + "18338c06-57fc-4882-ad44-b5f3b3846806.png", + "flat copy 40.png", + "36a1e6cb-98a1-4ada-a14e-8c04f135c5ee.png", + "f06bca10-a7ce-4a4a-92f6-973d7400fe8a.png", + "flat copy 41.png", + "397c17e0-e91b-4fa6-98d9-97e6d2f009ed.png", + "532a9660-8c7a-488b-8930-9134a9479afa.png", + "flat copy 33.png", + "d0299fe2-026b-4727-85e1-cb5de303e315.png", + "68a933bc-df0c-4891-bd41-2c05e4fde504.png", + "6698bb80-52f7-4e5b-ad6a-4a8122504f9a.png", + "99f0113d-8cb4-40b6-9670-b4be4c1fc475.png", + "flat copy 32.png", + "flat copy 34.png", + "c1ad279c-9093-469e-aa20-b73af0fc8db4.png", + "518ddc39-55c2-4b18-8bf6-e9c4f0806760.png", + "flat copy 8.png", + "860cab10-089c-4d99-ae89-3e4f87df5d9c.png", + "f29d41e9-d285-47e4-ad29-f04423533802.png", + "flat copy 13.png", + "flat copy 12.png", + "e6420ee4-14f0-404f-9cd7-abc9a69da621.png", + "flat copy 4.png", + "de7f86d5-56c9-4331-a9aa-655687dc354b.png", + "flat copy 35.png", + "flat.png", + "b6abcb20-8b90-42d3-9175-ba6b4d53a7a9.png", + "d29a6530-28d6-4dbe-bce5-9014d613ae5e.png", + "992f49b2-3f7c-4c54-a4d6-75af4693353b.png", + "flat copy 27.png", + "fd195b15-b98c-47c9-b608-de4157f6ceba.png", + "flat copy 10.png", + "flat copy 15.png", + "af993127-4ec6-4fa3-9a27-018af985a4a0.png", + "8de5fd51-b7b5-4014-a892-f0498c35fec2.png", + "flat copy 3.png", + "flat copy 11.png", + "flat copy 30.png", + "edc5b189-60a3-4aa0-a68d-cc35009f3648.png", + "flat copy 20.png", + "flat copy 19.png", + "9fe8882d-3aa9-4d2b-8de3-d9d220ea526c.png", + "flat copy 7.png", + "flat copy 46.png", + "flat copy 9.png", + "230e3f37-02d7-4be9-b6a8-1e4fb3acd368.png", + "flat copy 45.png", + "7f426b18-12ee-492b-9c69-dfa8ccbc42cc.png", + "flat copy 49.png", + "flat copy 22.png", + "7fe6e2dc-615f-432e-92d4-0a4f17a9ac49.png", + "flat copy 47.png", + "flat copy 42.png", + "34c9cf7b-5b5d-4c81-bb95-6d5743d25a18.png", + "aae9ec57-7df1-4af7-8e40-62962b90cce4.png", + "flat copy 36.png", + "flat copy 25.png", + "5a34b72d-3b7e-4a9a-9a0f-f73f2230fe28.png", + "e2e0160d-9809-48d2-b018-416ee0254fc0.png", + "a6bb714e-0f35-46d6-b7e8-3c18232a4801.png", + "a86a130e-04a3-44b0-99b7-44ce0a63cc2b.png", + "01f783e0-38de-497d-8ebe-c8d8a47e520a.png", + "flat copy 44.png", + "e0e2d63e-900b-4ecb-8df9-28115a58c3a2.png", + "flat copy 50.png", + "flat copy 5.png", + "flat copy 18.png", + "1aac54cf-8bf3-428c-93cd-1d3c258ff6b4.png", + "flat copy 14.png", + "11717454-440d-4b32-85c3-bf0013c66c61.png", + "67d50012-cba6-4525-8e00-b71124861f7e.png", + "25436e21-3140-4875-89a9-d14c5ce20f31.png", + "e4a28073-2252-4603-8c4b-75527a8c5ae9.png", + "flat copy 17.png", + "flat copy 48.png", + "flat copy 6.png", + "28d31de4-53f8-434a-ac57-4d5d27f5ab2f.png", + "flat copy.png", + "flat copy 39.png", + "flat copy 43.png", + "flat copy 24.png", + "6a13b80d-83c7-4fe1-8412-4fc07eefaa35.png", + "43a60b06-97b9-4119-b416-c7fc6783aa81.png", + "flat copy 21.png", + "flat copy 28.png", + "flat copy 31.png", + "flat copy 29.png", +] + +COUNTER_TOP_TEX_NAMES = [ + "5065776e-1fbc-4a70-a786-9a2ec6ee5aa0.png", + "e7f151aa-2354-48d0-94e8-071462f16ca7.png", + "b6618923-8455-44c3-8ae6-b766f34267cc.png", + "71d72043-3d97-4ea6-82f0-3ccbb53e0534.png", + "deb1e565-5c29-4285-aef8-f904c2b41dfb.png", + "ecf23b20-3db2-476a-bc06-442754ba5e76.png", + "39be4639-f28b-4bfa-8c1e-4b37e40395be.png", + "8bafdd4c-a44c-4bc0-8978-e7bc0abcedb4.png", + "3b958a28-0807-484a-92e7-f17b4c6dcbeb.png", + "ecd3c3fb-c4f2-4021-86d8-665e92b2735e.png", + "014ac251-0435-41c2-9dee-c664ee268327.png", + "0171bbba-6293-4117-b0ad-bc4b98d1c20e.png", + "0bd64a61-e098-4d06-ba3f-0a12269d3584.png", + "d5db5c5c-779b-4de0-ac66-31856239d488.png", + "9c47a3ac-2e56-47c1-86d4-006f98e21987.png", + "133b4eaf-bb93-4655-844c-a02278dfc032.png", + "58bcfa8c-6e11-494f-8fc5-d5a32ac7b3de.png", + "276de88a-374b-4dde-ac45-c52d651044b3.png", + "f52f1aaa-c061-42c0-8bdd-d2edb4af8736.png", + "1ccd1303-2e23-44c4-bb21-0dd474b0d899.png", + "761d55a2-5858-4d02-ab13-0bb272a67eed.png", + "c9d714cd-b00b-4d96-b6a6-cdc9e01c1b71.png", + "06da7e0e-c12c-4da7-a56b-9a3c82d87809.png", + "e5d1c208-34ad-49a7-8151-c0d55ecff952.png", + "9ccbd07a-887c-48c8-a806-0fac93606bb0.png", + "3d48ef42-02d9-41ed-bef6-f5c0dd47cdfa.png", + "9e1fd142-1d1c-4a82-a961-681db31b343f.png", + "5259cbe7-d956-4a0a-99d1-d7c7d391488f.png", + "94bdb3c5-faa2-4274-9337-ca5b9fabce88.png", + "e572f3d8-9ef2-4cd2-83c1-8acb766dbc4b.png", + "956782b3-ca4b-49e8-8939-6c50e87b9609.png", + "258270ae-3af4-4644-a031-176efac2c3f9.png", + "1fa52c2f-7474-4aa9-9ff9-0e411a78daac.png", + "f1299a54-59e5-42ea-9f53-e9f11fd6ca3c.png", + "6a6a86a2-bbba-422a-9620-5b90adaaf7a3.png", + "771c03d6-f0c8-4e3e-b734-0a07fff03c22.png", + "8c6ed656-6d1c-4707-82a2-cbff87a589f7.png", + "6a4f994f-293f-4a8a-8f8d-ac99f8e58adf.png", + "da90fb4d-3dfb-4a17-8ecc-95e82ab69b32.png", + "1563c9ee-30ab-44cc-b21f-fab5ad8df99d.png", + "932f5612-9058-4923-820d-894d630190cb.png", + "5e2958ab-c27d-41c8-8167-de9053f79038.png", + "2408cfed-ad91-43e2-9295-fdafafb76c8d.png", + "8549466d-50fe-4cb9-9001-e93532e7938c.png", + "00e4b598-2dd0-4ff9-b0a4-46e223a9296e.png", + "0666bf9a-4625-4132-bd7f-0079dace8c8c.png", + "ceb18b7d-1dcf-4aa2-adae-0e0aae1c5eeb.png", + "a4903060-7bfd-4bd5-b8d6-b916d172a82b.png", + "f5f4cf81-db71-42c7-b889-c25c145132c6.png", + "bf277536-38a6-41cd-a278-bd68e25816fd.png", + "a1cfe2ab-12cd-4d43-9ffc-77d48d0493f3.png", + "1c72f7db-374f-47db-8424-9526d4e7fa7a.png", + "3dc423ca-b351-429f-9842-1bd17e3ce360.png", + "2a8aea9d-218c-4601-8e8d-b98eb93fa461.png", + "451b6b8b-5d86-44ad-853b-e99153ba48e1.png", + "25d4c91a-c831-4249-b78e-a4b25d0b1ea1.png", + "b4f0036f-f2e7-4167-bbc4-708ee783052f.png", + "db04923e-96ac-41db-a16c-901f10a41bf0.png", + "65e832aa-974a-4ca8-9dd8-e90a96d75b6c.png", + "f66bf802-8273-4df7-a58a-faa8ba6ed46f.png", + "827976d2-dbab-47a3-905f-602e945a6b30.png", + "124bd263-2b8a-4057-9211-b36869047fd2.png", + "f69e2027-7163-4a53-8361-6050e5679242.png", + "d366b33d-335e-4a76-91f5-a5ce14266c89.png", + "adcb6ab3-7ecf-47f9-a11e-6a505ad23d98.png", + "2cea6a36-7053-4808-be22-fc5cc76b5531.png", + "ac3491a2-e817-4f5e-8453-ce34cb78a8a9.png", + "a875270b-fd82-409d-9bed-1d567657ff8e.png", + "f29cfb8b-d640-48a4-ae5e-02395ed7c6db.png", + "8c165058-abec-4ea9-9990-19b7eff4df4f.png", + "1c6ea15c-1cad-4a0c-838a-5eee8f99cfc9.png", + "897d7c04-f1bd-4bb1-bffb-bfada23a5b58.png", + "1b23c19f-7e79-4b96-a744-42615a72d722.png", + "f921b606-5363-41c2-aa93-dc8ec1475fda.png", + "efca4079-dd9f-4d54-8943-216d6c02e70a.png", + "040ff758-026f-4313-b390-ec86d3690f9d.png", + "0104c474-6473-4e05-b789-6bdb59f55da7.png", + "f73ed4a7-c1b1-4660-9eba-00f2ba25977b.png", + "0b184f66-ba4f-4fcd-9556-bea9f58dc9c6.png", + "7f638e9b-10e8-448c-a2f9-a75ae414dcfa.png", + "e563fd4b-656f-45f1-b803-df0d6dcb8bd3.png", + "0ed8ccf8-33e5-45a2-9200-4dc1a5565494.png", + "1ab263d2-ea24-4fe7-9383-f227aadc8c47.png", + "561d2d94-ec96-4246-974a-d9abc6f2297a.png", + "9af6ae6e-a842-4baa-a01e-cec57045c367.png", + "1c6fc0f3-d4ef-423b-9bba-d4a5d59c05df.png", + "76a72b39-24ec-4044-aad8-49f381939063.png", + "08ca0b3f-17e9-476e-9c17-ff81616c6bd7.png", + "9b637968-8173-44da-8f41-3943c4d182f9.png", + "725eb22a-2c4b-44b0-8aaf-bef282232601.png", + "3e81b87f-10ee-4f74-8ba8-1b724df383fb.png", + "fc9c7e5a-7abb-4ff6-84f2-9fce43bc200f.png", + "a8f33495-cd01-4b66-9c7e-3ba5edec6565.png", + "8585099d-cf7f-4c1c-8f36-937939dba42e.png", + "fe8afe85-5153-48cb-80e0-88de2a577f0c.png", + "46c59505-7dec-48f2-a0d1-c36ac213890e.png", + "95b636b0-8afb-4430-8f6a-1f4e0f4eb808.png", + "5ab4d96a-5401-45d8-977c-b3fef4e55ca9.png", + "8c8dd1cd-6c84-4fa8-b51b-ac736fda7a6c.png", + "76c7b19f-b375-48db-a1df-d79485a86d94.png", +] + +FLOOR_TEX_NAMES = [ + "8e4ea598-7170-4d24-ad12-42d45ef17a3b.png", + "9d7e7eac-9d81-4b04-8a07-ec35f9e7b58d.png", + "83c7c8bf-9277-4f59-88bd-1a4f428262ef.png", + "28359684-bb12-4b99-86b2-8c0998ee8fec.png", + "8ebc0bbe-1656-465e-b31e-766d1aceaec2.png", + "ada4e736-880d-4372-b148-218dc114c7fe.png", + "8a12dcf7-fc25-4341-9ea0-e583f1cc3d71.png", + "28f34ad5-b4f1-4b81-99cc-b04ed28d653b.png", + "b5350f4e-9521-4af1-a03f-a39e5d8b1796.png", + "14b4a5c3-69e0-425c-b8c5-ce495ab87409.png", + "022ec5c1-324e-4217-9f03-92b0e2f9c74f.png", + "9f345d0f-a768-4def-bebf-b818cf0c68dc.png", + "49de13f1-9488-4893-8398-48b0a5f27453.png", + "a938167f-6cb2-4e87-94f5-185eac06ff21.png", + "2aa2a926-fe72-4221-bd30-16e0a0cc9324.png", + "1671701f-60d2-4c71-95cc-8bdbb9f57ff9.png", + "8b24233c-7658-4d52-809d-a6fc71f37554.png", + "9582e8cc-89f5-464f-b183-2f21b8f0f267.png", + "8184ce85-7db2-4b23-908b-1170cc6830cf.png", + "32a18f41-8e7c-4a9d-b5ac-a7ba19a9ed35.png", + "56c9fb44-a8ee-469d-85d4-6d419f9dcba3.png", + "7ff039e9-7563-4ef0-b2ec-ce3d0d259a99.png", + "dbdd0778-8700-4967-bb52-75bbfa7eb29c.png", + "50578da0-60d8-4e12-800e-3df2fbf1bd5a.png", + "cedd99bd-8f8f-4d60-98e8-75e0af9b7e4f.png", + "b6c12637-3bd8-41d4-a787-3c2c271f4221.png", + "22c6be8e-a027-47dc-b2a1-3284cf5baad0.png", + "ed301cb6-fc33-4a6a-a2fd-4ce27a1f5bac.png", + "fc6bffaf-b9fd-4d51-a795-cb95d280dcab.png", + "310661bb-e74a-4b55-b999-ae1e2855990f.png", + "c327867a-02ea-4629-8059-181d3f341dc2.png", + "67a6f678-5f4b-4999-88fd-d0587299eb90.png", + "c65c9338-2903-4c6a-8015-dc606d24e659.png", + "e584ce4a-ff4d-461f-989e-5e4d21da42de.png", + "8776902b-74c1-4a54-94f2-320b4e89b5df.png", + "b588fa60-819c-4ae7-84bb-8f3de009ee1b.png", + "bdddfbd0-acc5-4e73-becb-c91f69986201.png", + "1f13ee23-d3f8-4fe4-b24d-97c4dece35c5.png", + "447fc81b-73c3-4502-8de7-9db654e62902.png", + "f78f9be1-385c-43ed-a89b-a4f11d45695f.png", + "c82d1a06-f78d-4e79-9b3e-23c4756d555d.png", + "573d34d2-a045-455c-b525-34a8571808eb.png", + "07f74135-07ab-4e29-bb00-4782f15ab59f.png", + "bec253e6-b2f0-48f2-afba-9207388a7937.png", + "0139f959-a4a8-4504-b6d2-f9351afd5941.png", + "8373a547-a792-438e-b941-f01ca1f0fb5d.png", + "b37ff2ac-f755-42f1-bdd4-a3a0f30fbfc6.png", + "f068688f-4b20-4d2f-b33a-9732b5050f72.png", + "c707d14d-3089-4a3e-a5b2-1088eda621bc.png", + "81ea9eea-29ea-4516-9e0d-e7ed0df98f5d.png", + "9aa36664-4ac6-4a50-b0e0-05c96f52c58e.png", + "c85db92d-b5a4-4fc8-aabd-9d4c82f3f444.png", + "df431f5c-699e-47ff-9161-b6e264a82163.png", + "4d8ea3e7-4a0b-4015-802c-cbbd0b12ba2e.png", + "3a34566d-b31f-4d3d-a86a-8038fde33b8c.png", + "83c6fd2f-caa2-4d53-b4d2-e19a7f12e6b4.png", + "ef044eea-9ebe-475e-bc05-d4e9d9255e39.png", + "02b897ed-2381-403a-aef1-095096993039.png", + "bb9ea1a0-7bfb-4aa2-85ee-0dbdb5001fa3.png", + "2afa8673-57cc-4953-b178-b57eedd9ad0a.png", + "2066e385-7798-47b3-89cc-1eaad15c75c4.png", + "45639cb9-7ac7-4d8c-a8a1-719d3a53d531.png", + "8f7fabcb-6875-4437-9d9c-27a2552c10dd.png", + "ce8ccc5f-20b9-4d06-aee6-fe85a6c02eaa.png", + "11fa953e-c11d-4dad-8e51-47cc6dc67aeb.png", + "8f51e06a-7bd0-4d2f-9a20-7821a975559a.png", + "1ef4cfa4-cf52-4efd-9fb3-6698650ee239.png", + "4d974231-cd17-4da5-ad9a-7faf83c2d683.png", + "cadaada3-e8f1-4bc7-af71-342215edbbb1.png", + "fb9b36a4-d87a-4c7f-a06c-a1e94869b96b.png", + "5daabcbd-0ce4-4dba-9342-c74d3da4fadf.png", + "612b00d2-819f-46ac-a599-38672184c842.png", + "0b5b5a9a-1435-4dfe-b6f4-19f4dbae1e8e.png", + "11f6a3bb-c36c-45c2-a429-501ac0cabc02.png", + "cf96c697-41f0-4d3c-a1d4-17d0d82719d0.png", + "81d9e9f2-8ff4-4d45-b1dd-d3afd3c62fb0.png", + "82036c07-5321-47c8-974c-27d58e526ba1.png", + "e793023f-7e5f-4211-9724-9022d3c8f920.png", + "0c01c256-4779-4093-a0b9-3347c31ef53f.png", + "9db099e2-56cb-4bec-becc-eb69c298866e.png", + "05f75518-7b70-4098-8983-aca459f33ddb.png", + "7c935010-badd-4fa4-8089-4fc9728dfe96.png", + "f9d057b1-5843-4b68-a58b-9fe87291a72f.png", + "9354be03-5a87-4ce8-85bc-8b0157abeb1c.png", + "9bfe963b-6d17-4704-8a9f-c2de48491b70.png", + "3b70d093-e264-4550-b5e5-f750ba577b78.png", + "67837bbb-05ae-4665-90e5-572130b7fc86.png", + "d339c422-36d0-40f3-8393-24076abb279c.png", + "5ccc395f-efd5-44af-b5f9-885789e26661.png", + "6d58d55a-34cc-455f-8b4c-004fabef6e11.png", + "5729f1d0-0796-4d82-99f7-76a171266fae.png", + "1e6da165-23cb-4426-91cf-450b3ac74e49.png", + "86ae5f3b-1a9c-4895-87eb-b526b403f332.png", + "4e53b13b-317a-484c-9b8b-7417453e45ff.png", + "8ddb08c1-facb-4fb1-841b-bde4e47fe584.png", + "41c3dbec-db54-4417-bb76-f51a4349943e.png", + "a2881fcf-1af3-46e9-87b0-c198fad703d1.png", + "808ec0fb-fcf8-4629-9296-38530521a95e.png", + "7c411449-a3c6-48e4-ab30-d08bca5938d6.png", + "0df28fee-6cef-48ae-9e8e-c0f0f3482412.png", +] + +WALL_TEX_NAMES = [ + "plain copy 49.png", + "18a6abbd-8ca1-43d9-9a0a-8424a7d1e016.png", + "plain copy 2.png", + "0882d081-d8be-49c0-aad6-3f5eff92265b.png", + "plain copy 39.png", + "7a19bf00-4f43-4e39-8fe6-977df7c6d147.png", + "plain copy 8.png", + "9b6f9830-a89d-4a42-965f-581dd0a12617.png", + "bcf9bf9b-ac75-408e-ab2e-516391c39d8e.png", + "plain copy 51.png", + "845424a1-4603-47d7-892c-426c2d427f0d.png", + "6e961263-5c90-41f9-87d3-b9e132c9583a.png", + "c72ea705-e088-4665-9683-6a8685758aef.png", + "plain copy 22.png", + "plain copy 44.png", + "plain copy 10.png", + "df17f0f3-68bb-46e2-ae9f-86cf84f48b04.png", + "plain copy 53.png", + "0906d773-7c22-4173-9edc-efc6e2da88e0.png", + "8995f82f-2435-4395-8ecd-a00824edd923.png", + "0adf5feb-6a2f-4417-811a-b7d70d42fb34.png", + "plain copy 5.png", + "536410ee-0460-43b0-9e8e-799e96439a0d.png", + "plain copy 11.png", + "plain copy 19.png", + "plain copy 17.png", + "plain copy.png", + "plain copy 31.png", + "Lance_Z._white_square_tiles_texture_image_ikea_high_quality_rea_f41b5937-af3e-4df8-b19d-ae4fa942f741.png", + "f6353155-1a10-41a1-be1d-149368938757.png", + "b1a7c75f-6b03-4b10-99cd-3299d7b6beb5.png", + "plain copy 52.png", + "7844f4b6-7d34-46b4-8ea4-19ab954ca58f.png", + "0dd40625-0cf8-4523-92cd-063c96108a23.png", + "plain copy 40.png", + "plain copy 21.png", + "plain copy 36.png", + "plain copy 37.png", + "plain copy 41.png", + "plain copy 23.png", + "1b8b8a44-ce4e-4156-978b-ad66bf4a6f45.png", + "plain copy 46.png", + "d208d65f-4d99-4963-8140-d54180844c8c.png", + "0aa2c331-8025-4417-a157-91467143c85b.png", + "d4775c13-15ea-496d-b5fc-19d2a9cab128.png", + "11760e4b-5f86-46cb-82ae-c87cc6f434d1.png", + "plain copy 3.png", + "plain copy 30.png", + "plain copy 9.png", + "0af727bd-14b4-4f7d-9fee-19f7f001ad34.png", + "67d1229f-7689-4dd6-ab2b-d003e0cd3cb7.png", + "plain copy 33.png", + "plain copy 4.png", + "2149f068-ca27-40ed-b53d-07e53210e678.png", + "plain copy 38.png", + "6b215002-fd31-4f1a-859a-d5d98a2a0c52.png", + "4fe97e2e-ae88-4dc9-8321-3529a2108508.png", + "Lance_Z._white_square_tiles_ikea_high_quality_realistic_ec4bd31e-d76d-4512-8b0d-a86dd8dd6aad.png", + "plain copy 6.png", + "plain copy 13.png", + "0d7afefe-58c8-4161-bf56-0974c7e806a2.png", + "plain copy 28.png", + "314f4070-0b2f-4433-98e7-dbdf18a8bff2.png", + "plain copy 18.png", + "dae6863d-b653-4998-8239-c6a6bb24362c.png", + "497cbc0b-a80a-42b3-8f5e-3bc97c145255.png", + "plain copy 20.png", + "4874a0d3-f5f2-46ea-a1d3-824b2f56f8ce.png", + "plain copy 50.png", + "plain copy 12.png", + "7c7c9950-576a-45fd-b3d1-74cca30f6fe7.png", + "8474c563-65b7-408b-976f-b19b38a44f90.png", + "Lance_Z._white_square_tiles_texture_image_ikea_high_quality_rea_ce2dcd92-29d7-4176-b7fa-79d91dab133b.png", + "738a1240-97f3-4fa6-97df-0ecc4b7aac26.png", + "plain copy 32.png", + "plain copy 29.png", + "a4046f8f-a2d6-4ef4-aa39-2ec541cbd246.png", + "plain copy 25.png", + "cbf05cdc-5d1c-472b-9891-0e4802553359.png", + "plain copy 16.png", + "plain copy 47.png", + "4bb0ad30-b60a-44a6-a259-058fab19b422.png", + "77abb443-a1b8-4b02-96de-1a7bc68d4f3f.png", + "plain copy 27.png", + "plain copy 24.png", + "plain copy 43.png", + "35ded0fe-73a7-4e82-8c01-32f79f5214a3.png", + "4b9d5219-38a0-4303-8837-29c4c51eed54.png", + "8949ad7c-2b89-444c-a758-b513f25937e1.png", + "plain copy 48.png", + "plain copy 45.png", + "plain copy 35.png", + "plain copy 26.png", + "plain copy 42.png", + "f7c0d850-4b56-484f-85ce-e9c4bd01ec22.png", + "9ec0b130-598a-4471-99ee-f68ee49a4a9f.png", + "b1dcb5d2-434e-4bd1-9329-eb1c2a6c039d.png", + "cf0d9763-3596-48de-af34-5f3647d812df.png", + "plain copy 14.png", + "fda88519-7a09-466d-84a2-19b216562dcb.png", +] + + +def get_random_textures(rng, frac=1.0): + """ + This function returns a dictionary of random textures for cabinet, counter top, floor, and wall. + + Args: + rng (np.random.Generator): Random number generator used for texture selection + + frac (float): Fraction of textures to select from the list of available textures + Default: 1.0 (select from all textures) + + Returns: + textures (dict): Dictionary of texture paths + """ + + end_ind = int(frac * 100) + ind = rng.integers(0, end_ind) + + textures = dict( + cab_tex=os.path.join(TEXTURES_DIR, "cabinet", CABINET_TEX_NAMES[ind]), + counter_tex=os.path.join(TEXTURES_DIR, "counter", COUNTER_TOP_TEX_NAMES[ind]), + floor_tex=os.path.join(TEXTURES_DIR, "floor", FLOOR_TEX_NAMES[ind]), + wall_tex=os.path.join(TEXTURES_DIR, "wall", WALL_TEX_NAMES[ind]), + ) + + return textures + + +def replace_counter_top_texture( + rng, initial_state: str, new_counter_top_texture_file: str = None +): + """ + This function replaces the counter top textures during playback. + + Args: + rng (np.random.Generator): Random number generator used for texture selection + + initial_state (str): Initial env XML string + + new_counter_top_texture_file (str): New texture file for counter top: i.e "marble/dark_marble.png" + If None (default), will replace with a random texture from marble directory + """ + + root = ET.fromstring(initial_state) + asset = root.find("asset") + + if new_counter_top_texture_file is None: + new_counter_top_texture_file = get_random_textures(rng)["counter_tex"] + else: + new_counter_top_texture_file = os.path.join( + TEXTURES_DIR, new_counter_top_texture_file + ) + + # step 1: find the name of texture that will be replaced + counter_tex_name = None + for mat in asset.findall("material"): + name = mat.get("name") + if "counter_top" in name: + counter_tex_name = mat.get("texture") + break + assert counter_tex_name is not None + + # step 2: find and replace texture element + CTOP_TEX_NAME = "counter_top_replacement_texture" + for tex in asset.findall("texture"): + name = tex.get("name") + if name == counter_tex_name: + tex.set("name", CTOP_TEX_NAME) + tex.set("file", str(new_counter_top_texture_file)) + + # step 3: reference new textures in materials + for mat in asset.findall("material"): + name = mat.get("name") + if "counter_top" in name: + mat.set("texture", CTOP_TEX_NAME) + + return ET.tostring(root).decode("utf-8") + + +def replace_cab_textures(rng, initial_state: str, new_cab_texture_file: str = None): + """ + This function replaces the cabinet and counter base textures during playback. + + Args: + rng (np.random.Generator): Random number generator used for texture selection + + initial_state (str): Initial env XML string + + new_cab_texture_file (str): New texture file for counter base and cabinets: i.e "cabinet/..." + If None (default), will replace with a random texture from flat or wood directories + """ + + root = ET.fromstring(initial_state) + asset = root.find("asset") + + if new_cab_texture_file is None: + new_cab_texture_file = get_random_textures(rng)["cab_tex"] + else: + new_cab_texture_file = os.path.join(TEXTURES_DIR, new_cab_texture_file) + + CAB_TEX_NAME_2D = "cab_replacement_texture_2d" + tex_2d = find_elements( + asset, tags="texture", attribs={"name": CAB_TEX_NAME_2D}, return_first=True + ) + if tex_2d is not None: + tex_2d.set("file", str(new_cab_texture_file)) + else: + tex_2d = ET.Element( + "texture", type="2d", name=CAB_TEX_NAME_2D, file=str(new_cab_texture_file) + ) + asset.append(tex_2d) + + CAB_TEX_NAME_CUBE = "cab_replacement_texture_cube" + tex_cube = find_elements( + asset, tags="texture", attribs={"name": CAB_TEX_NAME_CUBE}, return_first=True + ) + if tex_cube is not None: + tex_cube.set("file", str(new_cab_texture_file)) + else: + tex_cube = ET.Element( + "texture", + type="cube", + name=CAB_TEX_NAME_CUBE, + file=str(new_cab_texture_file), + ) + asset.append(tex_cube) + + for mat in asset.findall("material"): + name = mat.get("name") + if "counter_base" in name: + mat.set("texture", CAB_TEX_NAME_CUBE) + elif "housing" in name: + mat.set("texture", CAB_TEX_NAME_CUBE) + elif ( + "stack" in name + or "cab" in name + or "shelves" in name + or "bottom" in name + or ("top" in name and "counter" not in name and "stove" not in name) + ): + if "handle" in name or "transparent" in name: + continue + elif "door" in name: + mat.set("texture", CAB_TEX_NAME_2D) + elif "shelves" in name: + mat.set("texture", CAB_TEX_NAME_2D) + else: + mat.set("texture", CAB_TEX_NAME_CUBE) + + return ET.tostring(root).decode("utf-8") + + +def replace_floor_texture(rng, initial_state: str, new_floor_texture_file: str = None): + """ + This function replaces the counter top textures during playback. + + Args: + rng (np.random.Generator): Random number generator used for texture selection + + initial_state (str): Initial env XML string + + new_floor_texture_file (str): New texture file for counter top: i.e "wood/dark_wood_planks_2.png" + If None (default), will replace with a random texture from wood directory + """ + + root = ET.fromstring(initial_state) + asset = root.find("asset") + + if new_floor_texture_file is None: + new_floor_texture_file = get_random_textures(rng)["floor_tex"] + else: + new_floor_texture_file = os.path.join(TEXTURES_DIR, new_floor_texture_file) + + # step 1: find the name of texture that will be replaced + floor_tex_name = None + for mat in asset.findall("material"): + name = mat.get("name") + if "floor" in name and "backing" not in name: + floor_tex_name = mat.get("texture") + break + assert floor_tex_name is not None + + # step 2: find and replace texture element + FLOOR_TEX_NAME = "floor_replacement_texture" + for tex in asset.findall("texture"): + name = tex.get("name") + if name == floor_tex_name: + tex.set("name", FLOOR_TEX_NAME) + tex.set("file", str(new_floor_texture_file)) + tex.set("type", "2d") + + # step 3: reference new textures in materials + for mat in asset.findall("material"): + name = mat.get("name") + if "floor" in name and "backing" not in name: + mat.set("texture", FLOOR_TEX_NAME) + mat.set("texrepeat", "2 2") + + return ET.tostring(root).decode("utf-8") + + +def replace_wall_texture(rng, initial_state: str, new_wall_texture_file: str = None): + """ + This function replaces the counter top textures during playback. + + Args: + rng (np.random.Generator): Random number generator used for texture selection + + initial_state (str): Initial env XML string + + new_wall_texture_file (str): New texture file for counter top: i.e "wood/dark_wood_planks_2.png" + If None (default), will replace with a random texture from wood directory + """ + + root = ET.fromstring(initial_state) + asset = root.find("asset") + + if new_wall_texture_file is None: + new_wall_texture_file = get_random_textures(rng)["wall_tex"] + else: + new_wall_texture_file = os.path.join(TEXTURES_DIR, new_wall_texture_file) + + # step 1: find the name of texture that will be replaced + wall_tex_name = None + for mat in asset.findall("material"): + name = mat.get("name") + if "wall" in name and "floor" not in name and "backing" not in name: + wall_tex_name = mat.get("texture") + break + assert wall_tex_name is not None + + # step 2: add new texture element + WALL_TEX_NAME = "wall_replacement_texture" + for tex in asset.findall("texture"): + name = tex.get("name") + if name == wall_tex_name: + tex.set("name", WALL_TEX_NAME) + tex.set("file", str(new_wall_texture_file)) + tex.set("type", "2d") + + # step 3: reference new textures in materials + for mat in asset.findall("material"): + name = mat.get("name") + if "wall" in name and "floor" not in name and "backing" not in name: + mat.set("texture", WALL_TEX_NAME) + mat.set("texrepeat", "3 3") + + return ET.tostring(root).decode("utf-8") diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/README.md b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/README.md new file mode 100644 index 0000000000000000000000000000000000000000..770a519c87571a33b1186d770cc17c619ce524fc --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/README.md @@ -0,0 +1,30 @@ +# MuJoCo USD Integration + +USD is file format originally introduced by Pixar to compose 3D scenes in virtual worlds. We implement the ability to export MuJoCo models and trajectories as USD files for visualization with external renderers such as NVIDIA Omniverse and Blender. + +## Installation + +We assume that users have already installed MuJoCo either directly with pip or from source. For information on how to build MuJoCo from source, please visit this [reference](https://mujoco.readthedocs.io/en/stable/python.html#building-from-source). We also assume Python>=3.8. + +Using the USD bridge functionality requires the installation of additional libraries. Specifically, we utilize the `open3d` and `usd-core` packages. These can be installed directly using pip. + +```bash +pip install open3d +pip install usd-core +``` + +## Getting Started + +We provide a demo script to get started with generating USD files. This demo script is located at `python/mujoco/usd/demo.py`. In this script, we load a the `cards.xml` model and step through it for a given number of steps. At each step, we make a call to the USD exporter to store information for any state changes including the positions and orientations of geoms in the scene. + +## TODOs and Known Bugs + +TODOs: + +- Include tendons and contact forces in USD file +- Include references to third party materials for NVIDIA Omniverse in USD file +- Including custom defined matrials for NVIDIA Omniverse +- Bridge for modeling environments and assets from third party modeling engines to MuJoCo + +Known issues 🐛: +- Texture mapping for non-UV objects not consistent with MuJoCo renderer when ported to new renderers \ No newline at end of file diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/__init__.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..981ddeef54d2acf88184035bad291e59e256a100 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/__init__.py @@ -0,0 +1,4 @@ +from .component import * +from .exporter import * +from .shapes import * +from .utils import * diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/component.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/component.py new file mode 100644 index 0000000000000000000000000000000000000000..24c899daba351d4607e4870e5dca24ae2c9a5412 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/component.py @@ -0,0 +1,481 @@ +# Copyright 2024 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +from typing import List, Optional, Tuple + +import mujoco +import numpy as np + +# TODO: b/288149332 - Remove once USD Python Binding works well with pytype. +# pytype: disable=module-attr +# from open3d import open3d as o3d +# import open3d as o3d +from pxr import Gf, Sdf, Usd, UsdGeom, UsdLux, UsdShade, Vt + +import robocasa.utils.usd.shapes as shapes_component +import robocasa.utils.usd.utils as utils_component + + +class USDMesh: + def __init__( + self, + stage: Usd.Stage, + model: mujoco.MjModel, + geom: mujoco.MjvGeom, + obj_name: str, + dataid: int, + rgba: np.ndarray = np.array([1, 1, 1, 1]), + texture_file: Optional[str] = None, + ): + self.stage = stage + self.model = model + self.geom = geom + self.obj_name = obj_name + self.rgba = rgba + self.dataid = dataid + self.texture_file = texture_file + + xform_path = f"/World/Mesh_Xform_{obj_name}" + mesh_path = f"{xform_path}/Mesh_{obj_name}" + self.usd_xform = UsdGeom.Xform.Define(stage, xform_path) + self.usd_mesh = UsdGeom.Mesh.Define(stage, mesh_path) + self.usd_prim = stage.GetPrimAtPath(mesh_path) + + # setting mesh structure properties + mesh_vert, mesh_face, mesh_facenum = self._get_mesh_geometry() + self.usd_mesh.GetPointsAttr().Set(mesh_vert) + self.usd_mesh.GetFaceVertexCountsAttr().Set([3 for _ in range(mesh_facenum)]) + self.usd_mesh.GetFaceVertexIndicesAttr().Set(mesh_face) + + # setting mesh uv properties + mesh_texcoord, mesh_facetexcoord = self._get_uv_geometry() + self.texcoords = UsdGeom.PrimvarsAPI(self.usd_mesh).CreatePrimvar( + "UVMap", Sdf.ValueTypeNames.TexCoord2fArray, UsdGeom.Tokens.faceVarying + ) + self.texcoords.Set(mesh_texcoord) + self.texcoords.SetIndices(Vt.IntArray(mesh_facetexcoord.tolist())) + + self._attach_material() + + # defining ops required by update function + self.transform_op = self.usd_xform.AddTransformOp() + + def get_facetexcoord_ranges(self, nmesh, arr): + facetexcoords_ranges = [0] + running_sum = 0 + for i in range(nmesh): + running_sum += arr[i] * 3 + facetexcoords_ranges.append(running_sum) + return facetexcoords_ranges + + def _get_uv_geometry(self): + mesh_texcoord_adr_from = self.model.mesh_texcoordadr[self.dataid] + mesh_texcoord_adr_to = ( + self.model.mesh_texcoordadr[self.dataid + 1] + if self.dataid < self.model.nmesh - 1 + else len(self.model.mesh_texcoord) + ) + mesh_texcoord = self.model.mesh_texcoord[ + mesh_texcoord_adr_from:mesh_texcoord_adr_to + ] + + mesh_facetexcoord_ranges = self.get_facetexcoord_ranges( + self.model.nmesh, self.model.mesh_facenum + ) + + mesh_facetexcoord = self.model.mesh_facetexcoord.flatten() + mesh_facetexcoord = mesh_facetexcoord[ + mesh_facetexcoord_ranges[self.dataid] : mesh_facetexcoord_ranges[ + self.dataid + 1 + ] + ] + + mesh_facetexcoord[mesh_facetexcoord == len(mesh_texcoord)] = 0 + + return mesh_texcoord, mesh_facetexcoord + + def _get_mesh_geometry(self): + mesh_vert_adr_from = self.model.mesh_vertadr[self.dataid] + mesh_vert_adr_to = ( + self.model.mesh_vertadr[self.dataid + 1] + if self.dataid < self.model.nmesh - 1 + else len(self.model.mesh_vert) + ) + mesh_vert = self.model.mesh_vert[mesh_vert_adr_from:mesh_vert_adr_to] + + mesh_face_adr_from = self.model.mesh_faceadr[self.dataid] + mesh_face_adr_to = ( + self.model.mesh_faceadr[self.dataid + 1] + if self.dataid < self.model.nmesh - 1 + else len(self.model.mesh_face) + ) + mesh_face = self.model.mesh_face[mesh_face_adr_from:mesh_face_adr_to] + + mesh_facenum = self.model.mesh_facenum[self.dataid] + + return mesh_vert, mesh_face, mesh_facenum + + def _attach_material(self): + mtl_path = Sdf.Path(f"/World/_materials/Material_{self.obj_name}") + mtl = UsdShade.Material.Define(self.stage, mtl_path) + + if self.texture_file: + bsdf_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("Principled_BSDF") + ) + image_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("Image_Texture") + ) + uvmap_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("uvmap") + ) + + # setting the bsdf shader attributes + bsdf_shader.CreateIdAttr("UsdPreviewSurface") + bsdf_shader.CreateInput( + "diffuseColor", Sdf.ValueTypeNames.Color3f + ).ConnectToSource(image_shader.ConnectableAPI(), "rgb") + bsdf_shader.CreateInput("opacity", Sdf.ValueTypeNames.Float).Set( + float(self.rgba[-1]) + ) + bsdf_shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set( + self.geom.shininess + ) + bsdf_shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set( + 1.0 - self.geom.shininess + ) + + mtl.CreateSurfaceOutput().ConnectToSource( + bsdf_shader.ConnectableAPI(), "surface" + ) + + self.usd_mesh.GetPrim().ApplyAPI(UsdShade.MaterialBindingAPI) + UsdShade.MaterialBindingAPI(self.usd_mesh).Bind(mtl) + + # setting the image texture attributes + image_shader.CreateIdAttr("UsdUVTexture") + image_shader.CreateInput("file", Sdf.ValueTypeNames.Asset).Set( + self.texture_file + ) + image_shader.CreateInput("sourceColorSpace", Sdf.ValueTypeNames.Token).Set( + "sRGB" + ) + image_shader.CreateInput("wrapS", Sdf.ValueTypeNames.Token).Set("repeat") + image_shader.CreateInput("wrapT", Sdf.ValueTypeNames.Token).Set("repeat") + image_shader.CreateInput("st", Sdf.ValueTypeNames.Float2).ConnectToSource( + uvmap_shader.ConnectableAPI(), "result" + ) + image_shader.CreateOutput("rgb", Sdf.ValueTypeNames.Float3) + + # setting uvmap shader attributes + uvmap_shader.CreateIdAttr("UsdPrimvarReader_float2") + uvmap_shader.CreateInput("varname", Sdf.ValueTypeNames.Token).Set("UVMap") + uvmap_shader.CreateOutput("results", Sdf.ValueTypeNames.Float2) + else: + bsdf_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("Principled_BSDF") + ) + + # settings the bsdf shader attributes + bsdf_shader.CreateIdAttr("UsdPreviewSurface") + + bsdf_shader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).Set( + tuple(self.rgba[0:3]) + ) + bsdf_shader.CreateInput("opacity", Sdf.ValueTypeNames.Float).Set( + float(self.rgba[-1]) + ) + bsdf_shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set( + self.geom.shininess + ) + bsdf_shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set( + 1.0 - self.geom.shininess + ) + + mtl.CreateSurfaceOutput().ConnectToSource( + bsdf_shader.ConnectableAPI(), "surface" + ) + + self.usd_mesh.GetPrim().ApplyAPI(UsdShade.MaterialBindingAPI) + UsdShade.MaterialBindingAPI(self.usd_mesh).Bind(mtl) + + def update(self, pos: np.ndarray, mat: np.ndarray, visible: bool, frame: int): + transformation_mat = utils_component.create_transform_matrix( + rotation_matrix=mat, translation_vector=pos + ).T + self.transform_op.Set(Gf.Matrix4d(transformation_mat.tolist()), frame) + self.update_visibility(visible, frame) + + def update_visibility(self, visible: bool, frame: int): + if visible: + self.usd_prim.GetAttribute("visibility").Set("inherited", frame) + else: + self.usd_prim.GetAttribute("visibility").Set("invisible", frame) + + +class USDPrimitiveMesh: + def __init__( + self, + mesh_config: List[dict], + stage: Usd.Stage, + geom: mujoco.MjvGeom, + obj_name: str, + rgba: np.ndarray = np.array([1, 1, 1, 1]), + texture_file: Optional[str] = None, + ): + self.mesh_config = mesh_config + self.stage = stage + self.geom = geom + self.obj_name = obj_name + self.rgba = rgba + self.texture_file = texture_file + + self.usd_prim = Usd.Prim() + self.usd_mesh = UsdGeom.Mesh() + self.prim_mesh = None + self.transform_op = Gf.Matrix4d(1.0) + + _, self.prim_mesh = shapes_component.mesh_generator(mesh_config) + + xform_path = f"/World/{self.obj_name}_Xform" + mesh_path = f"{xform_path}/{obj_name}" + self.usd_xform = UsdGeom.Xform.Define(stage, xform_path) + self.usd_mesh = UsdGeom.Mesh.Define(stage, mesh_path) + self.usd_prim = stage.GetPrimAtPath(mesh_path) + + self.prim_mesh.translate(-self.prim_mesh.get_center()) + + mesh_vert, mesh_face, mesh_facenum = self._get_mesh_geometry() + self.usd_mesh.GetPointsAttr().Set(mesh_vert) + self.usd_mesh.GetFaceVertexCountsAttr().Set([3 for _ in range(mesh_facenum)]) + self.usd_mesh.GetFaceVertexIndicesAttr().Set(mesh_face) + + # setting mesh uv properties + mesh_texcoord, mesh_facetexcoord = self._get_uv_geometry() + self.texcoords = UsdGeom.PrimvarsAPI(self.usd_mesh).CreatePrimvar( + "UVMap", Sdf.ValueTypeNames.TexCoord2fArray, UsdGeom.Tokens.faceVarying + ) + + self.texcoords.Set(mesh_texcoord) + self.texcoords.SetIndices(Vt.IntArray([i for i in range(mesh_facenum * 3)])) + + self._set_refinement_properties() + + # setting attributes for the shape + self._attach_material() + + # defining ops required by update function + self.transform_op = self.usd_xform.AddTransformOp() + + def _set_refinement_properties(self): + self.usd_prim.GetAttribute("subdivisionScheme").Set("none") + + def _get_uv_geometry(self): + + assert self.prim_mesh + + x_scale, y_scale = self.geom.texrepeat + + mesh_texcoord = np.array(self.prim_mesh.triangle_uvs) + mesh_facetexcoord = np.asarray(self.prim_mesh.triangles) + + x_multiplier, y_multiplier = 1, 1 + if self.geom.texuniform: + x_multiplier, y_multiplier = self.geom.size[:2] + + mesh_texcoord[:, 0] *= x_scale * x_multiplier + mesh_texcoord[:, 1] *= y_scale * y_multiplier + + return mesh_texcoord, mesh_facetexcoord.flatten() + + def _get_mesh_geometry(self): + + assert self.prim_mesh + + # get mesh geometry from the open3d mesh model + mesh_vert = np.asarray(self.prim_mesh.vertices) + mesh_face = np.asarray(self.prim_mesh.triangles) + + return mesh_vert, mesh_face, len(mesh_face) + + def _attach_material(self): + mtl_path = Sdf.Path(f"/World/_materials/Material_{self.obj_name}") + mtl = UsdShade.Material.Define(self.stage, mtl_path) + if self.texture_file: + bsdf_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("Principled_BSDF") + ) + image_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("Image_Texture") + ) + uvmap_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("uvmap") + ) + + # setting the bsdf shader attributes + bsdf_shader.CreateIdAttr("UsdPreviewSurface") + bsdf_shader.CreateInput( + "diffuseColor", Sdf.ValueTypeNames.Color3f + ).ConnectToSource(image_shader.ConnectableAPI(), "rgb") + bsdf_shader.CreateInput("opacity", Sdf.ValueTypeNames.Float).Set( + float(self.rgba[-1]) + ) + bsdf_shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set( + self.geom.shininess + ) + bsdf_shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set( + 1.0 - self.geom.shininess + ) + + mtl.CreateSurfaceOutput().ConnectToSource( + bsdf_shader.ConnectableAPI(), "surface" + ) + + self.usd_mesh.GetPrim().ApplyAPI(UsdShade.MaterialBindingAPI) + UsdShade.MaterialBindingAPI(self.usd_mesh).Bind(mtl) + + # setting the image texture attributes + image_shader.CreateIdAttr("UsdUVTexture") + image_shader.CreateInput("file", Sdf.ValueTypeNames.Asset).Set( + self.texture_file + ) + image_shader.CreateInput("sourceColorSpace", Sdf.ValueTypeNames.Token).Set( + "sRGB" + ) + image_shader.CreateInput("wrapS", Sdf.ValueTypeNames.Token).Set("repeat") + image_shader.CreateInput("wrapT", Sdf.ValueTypeNames.Token).Set("repeat") + image_shader.CreateInput("st", Sdf.ValueTypeNames.Float2).ConnectToSource( + uvmap_shader.ConnectableAPI(), "result" + ) + image_shader.CreateOutput("rgb", Sdf.ValueTypeNames.Float3) + + # setting uvmap shader attributes + uvmap_shader.CreateIdAttr("UsdPrimvarReader_float2") + uvmap_shader.CreateInput("varname", Sdf.ValueTypeNames.Token).Set("UVMap") + uvmap_shader.CreateOutput("results", Sdf.ValueTypeNames.Float2) + else: + bsdf_shader = UsdShade.Shader.Define( + self.stage, mtl_path.AppendPath("Principled_BSDF") + ) + + # settings the bsdf shader attributes + bsdf_shader.CreateIdAttr("UsdPreviewSurface") + bsdf_shader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).Set( + tuple(self.rgba[:3]) + ) + bsdf_shader.CreateInput("opacity", Sdf.ValueTypeNames.Float).Set( + float(self.rgba[-1]) + ) + bsdf_shader.CreateInput("metallic", Sdf.ValueTypeNames.Float).Set( + self.geom.shininess + ) + bsdf_shader.CreateInput("roughness", Sdf.ValueTypeNames.Float).Set( + 1.0 - self.geom.shininess + ) + + mtl.CreateSurfaceOutput().ConnectToSource( + bsdf_shader.ConnectableAPI(), "surface" + ) + + self.usd_mesh.GetPrim().ApplyAPI(UsdShade.MaterialBindingAPI) + UsdShade.MaterialBindingAPI(self.usd_mesh).Bind(mtl) + + def update(self, pos: np.ndarray, mat: np.ndarray, visible: bool, frame: int): + transformation_mat = utils_component.create_transform_matrix( + rotation_matrix=mat, translation_vector=pos + ).T + self.transform_op.Set(Gf.Matrix4d(transformation_mat.tolist()), frame) + self.update_visibility(visible, frame) + + def update_visibility(self, visible: bool, frame: int): + if visible: + self.usd_prim.GetAttribute("visibility").Set("inherited", frame) + else: + self.usd_prim.GetAttribute("visibility").Set("invisible", frame) + + +class USDSphereLight: + def __init__(self, stage: Usd.Stage, obj_name: str, radius: Optional[float] = 0.3): + self.stage = stage + + xform_path = f"/World/Light_Xform_{obj_name}" + light_path = f"{xform_path}/Light_{obj_name}" + self.usd_xform = UsdGeom.Xform.Define(stage, xform_path) + self.usd_light = UsdLux.SphereLight.Define(stage, light_path) + self.usd_prim = stage.GetPrimAtPath(light_path) + + # we assume in mujoco that all lights are point lights + self.usd_light.GetRadiusAttr().Set(radius) + self.usd_light.GetTreatAsPointAttr().Set(False) + self.usd_light.GetNormalizeAttr().Set(True) + + # defining ops required by update function + self.translate_op = self.usd_xform.AddTranslateOp() + + def update(self, pos: np.ndarray, intensity: int, color: np.ndarray, frame: int): + self.translate_op.Set(Gf.Vec3d(pos.tolist()), frame) + + if not np.any(pos): + intensity = 0 + + self.usd_light.GetIntensityAttr().Set(intensity) + self.usd_light.GetColorAttr().Set(Gf.Vec3d(color.tolist())) + + +class USDDomeLight: + def __init__(self, stage: Usd.Stage, obj_name: str): + self.stage = stage + + xform_path = f"/World/Light_Xform_{obj_name}" + light_path = f"{xform_path}/Light_{obj_name}" + self.usd_xform = UsdGeom.Xform.Define(stage, xform_path) + self.usd_light = UsdLux.DomeLight.Define(stage, light_path) + self.usd_prim = stage.GetPrimAtPath(light_path) + + # we assume in mujoco that all lights are point lights + self.usd_light.GetNormalizeAttr().Set(True) + + def update(self, intensity: int, color: np.ndarray, frame: int): + self.usd_light.GetIntensityAttr().Set(intensity) + self.usd_light.GetExposureAttr().Set(0.0) + self.usd_light.GetColorAttr().Set(Gf.Vec3d(color.tolist())) + + +class USDCamera: + def __init__(self, stage: Usd.Stage, obj_name: str): + self.stage = stage + + xform_path = f"/World/Camera_Xform_{obj_name}" + camera_path = f"{xform_path}/Camera_{obj_name}" + self.usd_xform = UsdGeom.Xform.Define(stage, xform_path) + self.usd_camera = UsdGeom.Camera.Define(stage, camera_path) + self.usd_prim = stage.GetPrimAtPath(camera_path) + + # defining ops required by update function + self.transform_op = self.usd_xform.AddTransformOp() + + # self.usd_camera.CreateFocalLengthAttr().Set(18.14756) # default in omniverse + self.usd_camera.CreateFocalLengthAttr().Set(12) + self.usd_camera.CreateFocusDistanceAttr().Set(400) + + self.usd_camera.GetHorizontalApertureAttr().Set(12) + + self.usd_camera.GetClippingRangeAttr().Set(Gf.Vec2f(1e-4, 1e6)) + + def update(self, cam_pos: np.ndarray, cam_mat: np.ndarray, frame: int): + + transformation_mat = utils_component.create_transform_matrix( + rotation_matrix=cam_mat, translation_vector=cam_pos + ).T + self.transform_op.Set(Gf.Matrix4d(transformation_mat.tolist()), frame) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/demo.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/demo.py new file mode 100644 index 0000000000000000000000000000000000000000..6a3893d2c537e5e948473aecfab3eb29336c2857 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/demo.py @@ -0,0 +1,64 @@ +import argparse +from pathlib import Path + +import mujoco +from tqdm import tqdm + +from robocasa.utils.usd import exporter + + +def generate_usd_trajectory(args): + + # load a model to mujoco + model_path = args.model_path + m = mujoco.MjModel.from_xml_path(model_path) + d = mujoco.MjData(m) + + # create an instance of the USDExporter + exp = exporter.USDExporter( + model=m, + output_directory_name=Path(args.model_path).stem, + output_directory_root=args.output_directory_root, + camera_names=args.camera_names, + ) + + # step through the model for length steps + for i in tqdm(range(args.length)): + mujoco.mj_step(m, d) + exp.update_scene(d) + + exp.save_scene(filetype=args.export_extension) + + +if __name__ == "__main__": + + parser = argparse.ArgumentParser() + + parser.add_argument( + "--model_path", type=str, required=True, help="path to mjcf xml model" + ) + + parser.add_argument( + "--length", type=int, default=100, help="length of trajectory to render" + ) + + parser.add_argument( + "--output_directory_root", + type=str, + default="../usd_trajectories/", + help="location where to create usd files", + ) + + parser.add_argument( + "--camera_names", type=str, nargs="+", help="cameras to include in usd" + ) + + parser.add_argument( + "--export_extension", + type=str, + default="usd", + help="extension of exported file (can be usd, usda, or usdc)", + ) + + args = parser.parse_args() + generate_usd_trajectory(args) diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/exporter.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/exporter.py new file mode 100644 index 0000000000000000000000000000000000000000..e676f1c5020cc6f3fd2f6eb471cf30bf67d917a9 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/exporter.py @@ -0,0 +1,421 @@ +# Copyright 2024 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +import os +from typing import List, Optional, Tuple, Union + +import mujoco +import numpy as np +import scipy +import termcolor +import tqdm +from PIL import Image as im +from PIL import ImageOps + +# TODO: b/288149332 - Remove once USD Python Binding works well with pytype. +# pytype: disable=module-attr +from pxr import Sdf, Usd, UsdGeom + +import robocasa.utils.usd.component as component_module +import robocasa.utils.usd.shapes as shapes_module + + +class USDExporter: + def __init__( + self, + model: mujoco.MjModel, + height: int = 480, + width: int = 480, + max_geom: int = 10000, + output_directory_name: str = "mujoco_usdpkg", + output_directory_root: str = "./", + light_intensity: int = 10000, + camera_names: Optional[List[str]] = None, + specialized_materials_file: Optional[str] = None, + verbose: bool = True, + ): + """Initializes a new USD Exporter + + Args: + model: an MjModel instance. + height: image height in pixels. + width: image width in pixels. + max_geom: Optional integer specifying the maximum number of geoms that + can be rendered in the same scene. If None this will be chosen + automatically based on the estimated maximum number of renderable + geoms in the model. + output_directory_name: name of root directory to store outputted frames + and assets generated by the USD renderer. + output_directory_root: path to root directory storing generated frames + and assets by the USD renderer. + verbose: decides whether to print updates. + """ + + buffer_width = model.vis.global_.offwidth + buffer_height = model.vis.global_.offheight + + if width > buffer_width: + raise ValueError( + f""" + Image width {width} > framebuffer width {buffer_width}. Either reduce the image + width or specify a larger offscreen framebuffer in the model XML using the + clause: + + + """.lstrip() + ) + + if height > buffer_height: + raise ValueError( + f""" + Image height {height} > framebuffer height {buffer_height}. Either reduce the + image height or specify a larger offscreen framebuffer in the model XML using + the clause: + + + """.lstrip() + ) + + self.model = model + self.height = height + self.width = width + self.max_geom = max_geom + self.output_directory_name = output_directory_name + self.output_directory_root = output_directory_root + self.light_intensity = light_intensity + self.camera_names = camera_names + self.specialized_materials_file = specialized_materials_file + self.verbose = verbose + + self.frame_count = 0 # maintains how many times we have saved the scene + self.updates = 0 + + self.geom_name2usd = {} + + # initializing rendering requirements + self.renderer = mujoco.Renderer(model, height, width, max_geom) + self._initialize_usd_stage() + self._scene_option = mujoco.MjvOption() # using default scene option + + # initializing output_directories + self._initialize_output_directories() + + # loading required textures for the scene + self._load_textures() + + @property + def usd(self): + return self.stage.GetRootLayer().ExportToString() + + @property + def scene(self): + return self.renderer.scene + + def _initialize_usd_stage(self): + self.stage = Usd.Stage.CreateInMemory() + UsdGeom.SetStageUpAxis(self.stage, UsdGeom.Tokens.z) + self.stage.SetStartTimeCode(0) + # add as user input + self.stage.SetTimeCodesPerSecond(60.0) + + default_prim = UsdGeom.Xform.Define(self.stage, Sdf.Path("/World")).GetPrim() + self.stage.SetDefaultPrim(default_prim) + + def _initialize_output_directories(self): + self.output_directory_path = os.path.join( + self.output_directory_root, self.output_directory_name + ) + if not os.path.exists(self.output_directory_path): + os.makedirs(self.output_directory_path) + + self.frames_directory = os.path.join(self.output_directory_path, "frames") + if not os.path.exists(self.frames_directory): + os.makedirs(self.frames_directory) + + self.assets_directory = os.path.join(self.output_directory_path, "assets") + if not os.path.exists(self.assets_directory): + os.makedirs(self.assets_directory) + + if self.verbose: + print( + termcolor.colored( + "Writing output frames and assets to" + f" {self.output_directory_path}", + "green", + ) + ) + + def update_scene( + self, + data: mujoco.MjData, + scene_option: Optional[mujoco.MjvOption] = None, + ): + """Updates the scene with latest sim data + + Args: + data: structure storing current simulation state + scene_option: we use this to determine which geom groups to activate + """ + + self.frame_count += 1 + + scene_option = scene_option or self._scene_option + + # update the mujoco renderer + self.renderer.update_scene(data, scene_option=scene_option) + + # TODO: update scene options + if self.updates == 0: + self._initialize_usd_stage() + + self._load_lights() + self._load_cameras() + + self._update_geoms() + self._update_lights() + self._update_cameras(data, scene_option=scene_option) + + self.updates += 1 + + def _load_textures(self): + # TODO: remove code once added internally to mujoco + data_adr = 0 + self.texture_files = [] + for texture_id in tqdm.tqdm(range(self.model.ntex)): + texture_height = self.model.tex_height[texture_id] + texture_width = self.model.tex_width[texture_id] + pixels = 3 * texture_height * texture_width + img = im.fromarray( + self.model.tex_rgb[data_adr : data_adr + pixels].reshape( + texture_height, texture_width, 3 + ) + ) + img = ImageOps.flip(img) + + texture_file_name = f"texture_{texture_id}.png" + + img.save(os.path.join(self.assets_directory, texture_file_name)) + + relative_path = os.path.relpath( + self.assets_directory, self.frames_directory + ) + img_path = os.path.join( + relative_path, texture_file_name + ) # relative path, TODO: switch back to this + + self.texture_files.append(img_path) + + data_adr += pixels + + if self.verbose: + print( + termcolor.colored( + f"Completed writing {self.model.ntex} textures to" + f" {self.assets_directory}", + "green", + ) + ) + + def _load_geom(self, geom: mujoco.MjvGeom): + + geom_name = self._get_geom_name(geom.objtype, geom.objid) + + assert geom_name not in self.geom_name2usd + + texture_file = self.texture_files[geom.texid] if geom.texid != -1 else None + + if geom.type == mujoco.mjtGeom.mjGEOM_MESH: + usd_geom = component_module.USDMesh( + stage=self.stage, + model=self.model, + geom=geom, + obj_name=geom_name, + dataid=self.model.geom_dataid[geom.objid], + rgba=geom.rgba, + texture_file=texture_file, + ) + else: + mesh_config = shapes_module.mesh_config_generator( + name=geom_name, geom_type=geom.type, size=geom.size + ) + usd_geom = component_module.USDPrimitiveMesh( + mesh_config=mesh_config, + stage=self.stage, + geom=geom, + obj_name=geom_name, + rgba=geom.rgba, + texture_file=texture_file, + ) + + self.geom_name2usd[geom_name] = usd_geom + + def _update_geoms(self): + + geom_names = set(self.geom_name2usd.keys()) + + for i in range(self.scene.ngeom): + geom = self.scene.geoms[i] + geom_name = mujoco.mj_id2name(self.model, geom.objtype, geom.objid) + if not geom_name: + geom_name = "None" + geom_name += f"_{geom.objid}" + + # iterate through all geoms in the scene and makes update + for i in range(self.scene.ngeom): + geom = self.scene.geoms[i] + geom_name = self._get_geom_name(geom.objtype, geom.objid) + + if geom_name not in self.geom_name2usd: + self._load_geom(geom) + if self.geom_name2usd[geom_name]: + self.geom_name2usd[geom_name].update_visibility(False, 0) + + if self.geom_name2usd[geom_name]: + self.geom_name2usd[geom_name].update( + pos=geom.pos, + mat=geom.mat, + visible=geom.rgba[3] > 0, + frame=self.updates, + ) + if geom_name in geom_names: + geom_names.remove(geom_name) + + for geom_name in geom_names: + if self.geom_name2usd[geom_name]: + self.geom_name2usd[geom_name].update_visibility(False, self.updates) + + def _load_lights(self): + # initializes an usd light object for every light in the scene + self.usd_lights = [] + for i in range(self.scene.nlight): + light = self.scene.lights[i] + if not np.allclose(light.pos, [0, 0, 0]): + self.usd_lights.append + (component_module.USDSphereLight(stage=self.stage, obj_name=str(i))) + else: + self.usd_lights.append(None) + + def _update_lights(self): + for i in range(self.scene.nlight): + light = self.scene.lights[i] + + if np.allclose(light.pos, [0, 0, 0]): + continue + + if i >= len(self.usd_lights) or self.usd_lights[i] is None: + continue + + self.usd_lights[i].update( + pos=light.pos, + intensity=self.light_intensity, + color=light.diffuse, + frame=self.updates, + ) + + def _load_cameras(self): + self.usd_cameras = [] + if self.camera_names is not None: + for name in self.camera_names: + self.usd_cameras.append( + component_module.USDCamera(stage=self.stage, obj_name=name) + ) + + def _update_cameras( + self, + data: mujoco.MjData, + scene_option: Optional[mujoco.MjvOption] = None, + ): + for i in range(len(self.usd_cameras)): + + camera = self.usd_cameras[i] + camera_name = self.camera_names[i] + + self.renderer.update_scene( + data, scene_option=scene_option, camera=camera_name + ) + + avg_camera = mujoco.mjv_averageCamera( + self.scene.camera[0], self.scene.camera[1] + ) + + forward = avg_camera.forward + up = avg_camera.up + right = np.cross(forward, up) + + R = np.eye(3) + R[:, 0] = right + R[:, 1] = up + R[:, 2] = -forward + + camera.update(cam_pos=avg_camera.pos, cam_mat=R, frame=self.updates) + + def add_light( + self, + pos: List[float], + intensity: int, + objid: int, + radius: Optional[float] = 1.0, + color: Optional[np.ndarray] = np.array([0.3, 0.3, 0.3]), + obj_name: Optional[str] = "light_1", + light_type: Optional[str] = "sphere", + ): + + if light_type == "sphere": + new_light = component_module.USDSphereLight( + stage=self.stage, obj_name=str(objid), radius=radius + ) + + new_light.update( + pos=np.array(pos), intensity=intensity, color=color, frame=0 + ) + elif light_type == "dome": + new_light = component_module.USDDomeLight( + stage=self.stage, obj_name=str(objid) + ) + + new_light.update(intensity=intensity, color=color, frame=0) + + def add_camera( + self, + pos: List[float], + rotation_xyz: List[float], + objid: int, + obj_name: Optional[str] = "camera_1", + ): + new_camera = component_module.USDCamera(stage=self.stage, obj_name=str(objid)) + + r = scipy.spatial.transform.Rotation.from_euler( + "xyz", rotation_xyz, degrees=True + ) + new_camera.update(cam_pos=np.array(pos), cam_mat=r.as_matrix(), frame=0) + + def save_scene(self, filetype: str = "usd"): + assert filetype in ["usd", "usda", "usdc"] + self.stage.SetEndTimeCode(self.frame_count) + self.stage.Export( + f"{self.output_directory_root}/{self.output_directory_name}/frames/frame_{self.frame_count}_.{filetype}" + ) + if self.verbose: + print( + termcolor.colored( + f"Completed writing frame_{self.frame_count}.{filetype}", "green" + ) + ) + + def _get_geom_name(self, objtype, objid): + geom_name = mujoco.mj_id2name(self.model, objtype, objid) + if not geom_name: + geom_name = "None" + geom_name += f"_{objid}" + return geom_name diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/exporter_test.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/exporter_test.py new file mode 100644 index 0000000000000000000000000000000000000000..a81db35c406e0518666c041f2caca78fea22e698 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/exporter_test.py @@ -0,0 +1,73 @@ +# Copyright 2024 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for the MuJoCo USD Exporter.""" + +import logging +import os + +import mujoco +from absl.testing import absltest +from etils import epath + +# Open3D and USD are not fully supported on all MuJoCo architectures. +# pylint: disable=python.style(g-import-not-at-top) +execute_test = True +try: + from pxr import Usd + + from robocasa.utils.usd import exporter as exporter_module +except ImportError: + logging.warning("Skipping test due to missing import") + execute_test = False +# pylint: enable=python.style(g-import-not-at-top) + + +class ExporterTest(absltest.TestCase): + def test_usd_export(self): + if not execute_test: + return + + output_dir = os.getenv("TEST_UNDECLARED_OUTPUTS_DIR") + xml = """ + + + + + + +""" + model = mujoco.MjModel.from_xml_string(xml) + data = mujoco.MjData(model) + exporter = exporter_module.USDExporter( + model, + output_directory_name="mujoco_usdpkg", + output_directory_root=output_dir, + ) + exporter.update_scene(data) + exporter.save_scene("export.usda") + + with open( + os.path.join(output_dir, "mujoco_usdpkg/frames", "frame_1_.export.usda"), + "r", + ) as f: + golden_path = os.path.join( + epath.resource_path("mujoco"), "testdata", "usd_golden.usda" + ) + with open(golden_path, "r") as golden_file: + self.assertEqual(f.read(), golden_file.read()) + + +if __name__ == "__main__": + absltest.main() diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/shapes.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/shapes.py new file mode 100644 index 0000000000000000000000000000000000000000..377e90a9fecaa986c3d0224e3cbf48f2c3f42c65 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/shapes.py @@ -0,0 +1,139 @@ +import copy +import pprint + +import mujoco +import numpy as np +import open3d as o3d + + +def create_hemisphere( + radius: float, resolution: int = 20, theta_steps: int = 50, phi_steps: int = 50 +): + + points = [] + for i in range(phi_steps + 1): + phi = np.pi / 2 * i / phi_steps + for j in range(theta_steps + 1): + theta = 2 * np.pi * j / theta_steps + x = radius * np.sin(phi) * np.cos(theta) + y = radius * np.sin(phi) * np.sin(theta) + z = radius * np.cos(phi) + points.append([x, y, z]) + + pcd = o3d.geometry.PointCloud() + pcd.points = o3d.utility.Vector3dVector(points) + + mesh = pcd.compute_convex_hull()[0] + + return mesh + + +def mesh_config_generator(name: str, geom_type: mujoco.mjtGeom, size: np.ndarray): + + if geom_type == mujoco.mjtGeom.mjGEOM_PLANE: + return { + "name": name, + "box": { + "width": size[0] * 2 if size[0] > 0 else 100, + "height": size[1] * 2 if size[1] > 0 else 100, + "depth": 0.001, + "map_texture_to_each_face": True, + }, + } + elif geom_type == mujoco.mjtGeom.mjGEOM_SPHERE: + return {"name": name, "sphere": {"radius": float(size[0])}} + elif geom_type == mujoco.mjtGeom.mjGEOM_CAPSULE: + cylinder = mesh_config_generator(name, mujoco.mjtGeom.mjGEOM_CYLINDER, size) + return { + "name": name, + "cylinder": cylinder["cylinder"], + "left_hemisphere": { + "radius": size[0], + "transform": {"translate": (0, 0, -size[2]), "rotate": (np.pi, 0, 0)}, + }, + "right_hemisphere": { + "radius": size[0], + "transform": {"translate": (0, 0, size[2])}, + }, + } + elif geom_type == mujoco.mjtGeom.mjGEOM_ELLIPSOID: + sphere = mesh_config_generator(name, mujoco.mjtGeom.mjGEOM_SPHERE, [1.0]) + sphere["sphere"]["transform"] = {"scale": tuple(size)} + return { + "name": name, + "sphere": sphere["sphere"], + } + elif geom_type == mujoco.mjtGeom.mjGEOM_CYLINDER: + return { + "name": name, + "cylinder": { + "radius": size[0], + "height": size[2] * 2, + }, + } + elif geom_type == mujoco.mjtGeom.mjGEOM_BOX: + return { + "name": name, + "box": { + "width": size[0] * 2, + "height": size[1] * 2, + "depth": size[2] * 2, + }, + } + else: + raise NotImplemented( + f"{geom_type} primitive geom type not implemented with USD integration" + ) + + +def mesh_generator(mesh_config: dict): + + assert "name" in mesh_config + + mesh = None + + for shape, config in mesh_config.items(): + + if shape == "name": + continue + + if "box" in shape: + prim_mesh = o3d.geometry.TriangleMesh.create_box( + width=mesh_config[shape]["width"], + height=mesh_config[shape]["height"], + depth=mesh_config[shape]["depth"], + create_uv_map=True, + map_texture_to_each_face=True, + ) + elif "hemisphere" in shape: + prim_mesh = create_hemisphere(radius=mesh_config[shape]["radius"]) + elif "sphere" in shape: + prim_mesh = o3d.geometry.TriangleMesh.create_sphere( + radius=mesh_config[shape]["radius"], create_uv_map=True + ) + elif "cylinder" in shape: + prim_mesh = o3d.geometry.TriangleMesh.create_cylinder( + radius=mesh_config[shape]["radius"], + height=mesh_config[shape]["height"], + create_uv_map=True, + ) + + if "transform" in config: + + if "rotate" in config["transform"]: + R = mesh.get_rotation_matrix_from_xyz(config["transform"]["rotate"]) + prim_mesh.rotate(R, center=(0, 0, 0)) + if "scale" in config["transform"]: + prim_mesh.vertices = o3d.utility.Vector3dVector( + np.asarray(prim_mesh.vertices) + * np.array(config["transform"]["scale"]) + ) + if "translate" in config["transform"]: + prim_mesh.translate(config["transform"]["translate"]) + + if not mesh: + mesh = prim_mesh + else: + mesh += prim_mesh + + return mesh_config["name"], mesh diff --git a/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/utils.py b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..8c4408c2ac5d23a107ffd4578be03ffd65ceaf46 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/robocasa/utils/usd/utils.py @@ -0,0 +1,27 @@ +# Copyright 2024 DeepMind Technologies Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +import numpy as np + + +def create_transform_matrix(rotation_matrix, translation_vector): + # Ensure rotation_matrix and translation_vector are NumPy arrays + rotation_matrix = np.array(rotation_matrix) + translation_vector = np.array(translation_vector) + + transform_matrix = np.eye(4) + transform_matrix[:3, :3] = rotation_matrix + transform_matrix[:3, 3] = translation_vector + + return transform_matrix diff --git a/Isaac-GR00T/external_dependencies/robocasa/tests/test_asset_load_speed.py b/Isaac-GR00T/external_dependencies/robocasa/tests/test_asset_load_speed.py new file mode 100644 index 0000000000000000000000000000000000000000..e78f75ef15c83744fc1ac48f6f48e75c93a47be1 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/tests/test_asset_load_speed.py @@ -0,0 +1,70 @@ +import os +import numpy as np +import tqdm +import traceback +import argparse + +from robocasa.scripts.browse_mjcf_model import read_model +import robocasa + + +def find_all_xml_files(directory): + file_list = [] + for root, dirs, files in os.walk(directory): + for file in files: + if file.endswith(".xml"): + file_list.append(os.path.join(root, file)) + return file_list + + +def get_load_time_stats(directory, verbose=False): + xml_files = find_all_xml_files(directory) + load_times = [] + + for mjcf_path in xml_files: + try: + sim, info = read_model(filepath=mjcf_path) + load_times.append(info["sim_load_time"]) + del sim + except Exception as e: + if verbose: + print("Caught exception for {}".format(mjcf_path)) + traceback.print_exc() + + if len(load_times) == 0: + return None + + stats = dict( + mean=np.mean(load_times), + min=np.min(load_times), + percentile25=np.percentile(load_times, 25), + percentile50=np.percentile(load_times, 50), + percentile75=np.percentile(load_times, 75), + max=np.max(load_times), + ) + + print("Directory:", directory) + print("Mean loading time: {:.4f} s".format(stats["mean"])) + print("Median loading time: {:.4f} s".format(stats["percentile50"])) + print() + + return stats + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--directory", type=str) + args = parser.parse_args() + + if args.directory is not None: + get_load_time_stats(args.directory) + else: + objects_path = os.path.join(robocasa.__path__[0], "models/assets/objects") + fixtures_path = os.path.join(robocasa.__path__[0], "models/assets/fixtures") + objaverse_path = os.path.join(objects_path, "objaverse") + + for fixture_type in os.listdir(fixtures_path): + dir = os.path.join(fixtures_path, fixture_type) + get_load_time_stats(dir) + + get_load_time_stats(objaverse_path) diff --git a/Isaac-GR00T/external_dependencies/robocasa/tests/test_dataset_playback.py b/Isaac-GR00T/external_dependencies/robocasa/tests/test_dataset_playback.py new file mode 100644 index 0000000000000000000000000000000000000000..624d3f222d715b5a344e5b994fbbe93d408afbf8 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/tests/test_dataset_playback.py @@ -0,0 +1,64 @@ +import unittest +from termcolor import colored +import argparse +import os + +from robocasa.scripts.playback_dataset import playback_dataset +from robocasa.utils.dataset_registry import ( + SINGLE_STAGE_TASK_DATASETS, + MULTI_STAGE_TASK_DATASETS, +) +from robocasa.utils.dataset_registry import get_ds_path + + +class TestTasksValidity(unittest.TestCase): + def test_tasks_validity(self, *args): + """ + Tests that all kitchen environment tasks run error free. Iterates through + all tasks, creates the environment, then runs NUM_ROLLOUTS test episodes per scene. + At the end, prints out all tests that were successful, and then any that were not + completed successfully along with their errors. + """ + + # iterate through all atomic and composite tasks + all_tasks = list(SINGLE_STAGE_TASK_DATASETS) + list(MULTI_STAGE_TASK_DATASETS) + all_tasks = all_tasks[-2:] + for task_i, task in enumerate(all_tasks): + human_path = get_ds_path( + task=task, ds_type="human_raw" + ) # human dataset path + print(f"Dataset path: {human_path}") + print( + colored( + f"Playing back {task} environment [{task_i+1}/{len(all_tasks)}]...", + "green", + ) + ) + + args = argparse.ArgumentParser() + args.dataset = human_path + args.filter_key = None + args.n = 5 + args.use_obs = False + args.use_actions = True + args.use_abs_actions = False + args.render = False + video_folder = os.path.expanduser("~/tmp/playback_videos") + if os.path.exists(video_folder) is False: + os.makedirs(video_folder) + args.video_path = os.path.join(video_folder, f"{task}.mp4") + args.video_skip = 5 + args.render_image_names = [ + "robot0_agentview_left", + "robot0_agentview_right", + "robot0_eye_in_hand", + ] + args.first = False + args.extend_states = False + args.verbose = False + + playback_dataset(args) + + +if __name__ == "__main__": + unittest.main() diff --git a/Isaac-GR00T/external_dependencies/robocasa/tests/test_env_determinism.py b/Isaac-GR00T/external_dependencies/robocasa/tests/test_env_determinism.py new file mode 100644 index 0000000000000000000000000000000000000000..d653eadb70e1bfec47778c41c81cae9aa005494a --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/tests/test_env_determinism.py @@ -0,0 +1,195 @@ +import unittest +from unittest import mock + +import numpy as np +from lxml import etree as ET + +import mujoco +import robocasa +import robosuite +from robosuite import load_controller_config +from termcolor import colored + +DEFAULT_SEED = 3 + + +class TestEnvDeterminism(unittest.TestCase): + + skip_envs = set( + [ + "AfterwashSorting", + "BowlAndCup", + "ClearingCleaningReceptacles", + "DrinkwareConsolidation", + "PnP", + "SetBowlsForSoup", + "WineServingPrep", + ] + ) + + def create_env(self, config): + env = robosuite.make(**config) + env.reset() + return env + + @mock.patch("random.choice") + @mock.patch("random.choices") + @mock.patch("random.randint") + @mock.patch("random.shuffle") + @mock.patch("numpy.random.randint") + @mock.patch("numpy.random.normal") + @mock.patch("numpy.random.uniform") + def test_env_determinism(self, *args): + """ + Tests environment determinism for all Kichen environments excluding those in + skip_envs (defined above). We test for similarity in scene layout, style, all + objects and fixtures in the scene including their position and orientation, + and randomized cameras. + """ + + def compare_scene_appearance(env_1, env_2): + """ + Compares the appearance of two environments based on their layout + and their style. + """ + self.assertEqual(env_1.layout_id, env_2.layout_id) + self.assertEqual(env_1.style_id, env_2.style_id) + + def compare_objects_in_scene(env_1, env_2): + """ + Compares all added objects in the scene and their positions and + quaternions. + """ + env_1_objects = env_1.object_placements + env_2_objects = env_2.object_placements + + self.assertEqual(env_1_objects.keys(), env_2_objects.keys()) + + # Checks the position and rotation of all the geoms in the scene + for name in env_1_objects.keys(): + pos_1, quat_1 = env_1_objects[name][:2] + pos_2, quat_2 = env_2_objects[name][:2] + np.testing.assert_allclose(pos_1, pos_2, atol=1e-7) + np.testing.assert_allclose(quat_1, quat_2, atol=1e-7) + + def compare_fixtures_in_scene(env_1, env_2): + """ + Compares all added fixtures in the scene and their positions and + quaternions. + """ + env_1_fixtures = env_1.fxtr_placements + env_2_fixtures = env_2.fxtr_placements + + self.assertEqual(env_1_fixtures.keys(), env_2_fixtures.keys()) + + for name in env_1_fixtures.keys(): + pos_1, quat_1 = env_1_fixtures[name][:2] + pos_2, quat_2 = env_2_fixtures[name][:2] + np.testing.assert_allclose(pos_1, pos_2, atol=1e-7) + np.testing.assert_allclose(quat_1, quat_2, atol=1e-7) + + envs = sorted(robocasa.ALL_KITCHEN_ENVIRONMENTS) + + for i, env in enumerate(envs): + if env in self.skip_envs or env.startswith("MG_"): + continue + + print(colored(f"Testing {env} environment...", "green")) + + config = { + "env_name": env, + "robots": "PandaOmron", + "controller_configs": load_controller_config( + default_controller="OSC_POSE" + ), + "has_renderer": False, + "has_offscreen_renderer": False, + "ignore_done": True, + "use_camera_obs": False, + "control_freq": 20, + "seed": DEFAULT_SEED, + "randomize_cameras": False, + } + + env_1 = self.create_env(config) + env_2 = self.create_env(config) + + compare_scene_appearance(env_1, env_2) + compare_objects_in_scene(env_1, env_2) + compare_fixtures_in_scene(env_1, env_2) + + env_1.close() + env_2.close() + + for mock in args: + mock.assert_not_called() + + def test_random_generative_textures(self): + """ + Tests env determinism when using generative textures to ensure random generation + of textures results in the same generated texture replacement file. + """ + + config = { + "env_name": "PnPCounterToCab", + "robots": "PandaOmron", + "controller_configs": load_controller_config(default_controller="OSC_POSE"), + "has_renderer": False, + "has_offscreen_renderer": False, + "ignore_done": True, + "use_camera_obs": False, + "control_freq": 20, + "seed": DEFAULT_SEED, + "randomize_cameras": False, + "generative_textures": "100p", + } + + env_1 = self.create_env(config) + env_2 = self.create_env(config) + + texture_names = ["cab_tex", "counter_tex", "wall_tex", "floor_tex"] + + for texture_name in texture_names: + self.assertEqual( + env_1._curr_gen_fixtures[texture_name], + env_2._curr_gen_fixtures[texture_name], + ) + + def test_randomized_cameras(self): + """ + Tests env determinism when using randomized cameras. Ensures that the position + and orientation of all respective cameras are the same when using the same seed. + """ + + config = { + "env_name": "PnPCounterToCab", + "robots": "PandaOmron", + "controller_configs": load_controller_config(default_controller="OSC_POSE"), + "has_renderer": False, + "has_offscreen_renderer": False, + "ignore_done": True, + "use_camera_obs": False, + "control_freq": 20, + "seed": DEFAULT_SEED, + "randomize_cameras": False, + } + + env_1 = self.create_env(config) + env_2 = self.create_env(config) + + self.assertListEqual( + list(env_1._cam_configs.keys()), list(env_2._cam_configs.keys()) + ) + for camera_name in env_1._cam_configs.keys(): + self.assertEqual( + env_1._cam_configs[camera_name]["pos"], + env_2._cam_configs[camera_name]["pos"], + ) + self.assertEqual( + env_1._cam_configs[camera_name]["quat"], + env_2._cam_configs[camera_name]["quat"], + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/Isaac-GR00T/external_dependencies/robocasa/tests/test_tasks_validity.py b/Isaac-GR00T/external_dependencies/robocasa/tests/test_tasks_validity.py new file mode 100644 index 0000000000000000000000000000000000000000..d3e5e66e68987b08834850dbef16a2a66c8d00b4 --- /dev/null +++ b/Isaac-GR00T/external_dependencies/robocasa/tests/test_tasks_validity.py @@ -0,0 +1,72 @@ +import unittest +from termcolor import colored +import traceback + +from robocasa.environments import ALL_KITCHEN_ENVIRONMENTS +from robocasa.utils.env_utils import create_env, run_random_rollouts + +DEFAULT_SEED = 0 +NUM_ROLLOUTS = 10 +NUM_STEPS = 20 + + +class TestTasksValidity(unittest.TestCase): + def test_tasks_validity(self, *args): + """ + Tests that all kitchen environment tasks run error free. Iterates through + all tasks, creates the environment, then runs NUM_ROLLOUTS test episodes per scene. + At the end, prints out all tests that were successful, and then any that were not + completed successfully along with their errors. + """ + + successful = [] + unsucessful = [] + error_dict = {} + + for i, env_name in enumerate(list(ALL_KITCHEN_ENVIRONMENTS)): + print( + colored( + f"Testing {env_name} environment [{i}/{len(list(ALL_KITCHEN_ENVIRONMENTS))}]...", + "green", + ) + ) + + completed = True + try: + env = create_env(env_name) + run_random_rollouts( + env, + num_rollouts=NUM_ROLLOUTS, + num_steps=NUM_STEPS, + video_path="/tmp/test.mp4", + ) + except KeyboardInterrupt: + print(colored(f"Exiting Test Early.", "yellow")) + break + except Exception: + print(colored(f"Test {env_name} Failed.", "red")) + if env_name not in error_dict.keys(): + error_dict[env_name] = [] + error_dict[env_name].append(traceback.format_exc()) + completed = False + + if completed: + successful.append(env_name) + else: + unsucessful.append(env_name) + + print( + colored(f"The following tests ran successfully:\n{successful}\n", "green") + ) + print(colored(f"The following tests ran unsuccessfully:\n{unsucessful}", "red")) + if error_dict: + print(colored(f"With the following errors:", "red")) + for key in error_dict.keys(): + print(colored(f"{key}:", "red")) + for i, error in enumerate(error_dict[key]): + print(colored(f"Error #{i+1}:", "red")) + print(colored(f"{error}\n", "red")) + + +if __name__ == "__main__": + unittest.main() diff --git a/Isaac-GR00T/scripts/deployment/dgpu/wheels/torchcodec-0.8.0-cp312-cp312-linux_aarch64.whl b/Isaac-GR00T/scripts/deployment/dgpu/wheels/torchcodec-0.8.0-cp312-cp312-linux_aarch64.whl new file mode 100644 index 0000000000000000000000000000000000000000..2033155f7041878cd92cf57144866368e935595f --- /dev/null +++ b/Isaac-GR00T/scripts/deployment/dgpu/wheels/torchcodec-0.8.0-cp312-cp312-linux_aarch64.whl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c5bf377f922d2126041b3c49846504083a015d44979ca594e368ccc8c4c0814 +size 512641 diff --git a/Isaac-GR00T/scripts/deployment/orin/wheels/torchcodec-0.10.0a0-cp310-cp310-linux_aarch64.whl b/Isaac-GR00T/scripts/deployment/orin/wheels/torchcodec-0.10.0a0-cp310-cp310-linux_aarch64.whl new file mode 100644 index 0000000000000000000000000000000000000000..382cf8090d7546257f5427e5e3ba9c16fad9dcca --- /dev/null +++ b/Isaac-GR00T/scripts/deployment/orin/wheels/torchcodec-0.10.0a0-cp310-cp310-linux_aarch64.whl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74f85bfa1e30610a3c314fe39bca71bb2f0285e8e7308c60176219a6a3e3bf1a +size 621818 diff --git a/Isaac-GR00T/scripts/deployment/spark/wheels/flash_attn-2.8.3-cp312-cp312-linux_aarch64.whl b/Isaac-GR00T/scripts/deployment/spark/wheels/flash_attn-2.8.3-cp312-cp312-linux_aarch64.whl new file mode 100644 index 0000000000000000000000000000000000000000..95f65f046f50d5b3d7d9679c680892e48c0c67bb --- /dev/null +++ b/Isaac-GR00T/scripts/deployment/spark/wheels/flash_attn-2.8.3-cp312-cp312-linux_aarch64.whl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2777f80d348e213ae6cd65f288485189cb49e1a2ff7bfbceeb47cdef43301e2b +size 65372908 diff --git a/Isaac-GR00T/scripts/deployment/spark/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl b/Isaac-GR00T/scripts/deployment/spark/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl new file mode 100644 index 0000000000000000000000000000000000000000..24c5bcc2399817ecc92e02a085ba280f8ca3f3b8 --- /dev/null +++ b/Isaac-GR00T/scripts/deployment/spark/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4dcd2ce933cfdbbeeda0bb4d35cece373035bdf341f0c58c1176c36f71e53954 +size 570558 diff --git a/Isaac-GR00T/scripts/deployment/thor/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl b/Isaac-GR00T/scripts/deployment/thor/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl new file mode 100644 index 0000000000000000000000000000000000000000..5cf6cf984ff9212d77ce8ca45fc3ea6a0e0d3ed4 --- /dev/null +++ b/Isaac-GR00T/scripts/deployment/thor/wheels/torchcodec-0.10.0a0-cp312-cp312-linux_aarch64.whl @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1421de7e6248cc33398c16b2d7ba5ada4bf5c2a38af7cc44a003f3b0c36eb314 +size 571602