iMihayo commited on
Commit
ca61096
·
verified ·
1 Parent(s): d3db03d

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +53 -0
  2. Piper_ros_private-ros-noetic/src/piper_description/meshes/base_link.STL +3 -0
  3. Piper_ros_private-ros-noetic/src/piper_description/meshes/link1.STL +3 -0
  4. Piper_ros_private-ros-noetic/src/piper_description/meshes/link2.STL +3 -0
  5. Piper_ros_private-ros-noetic/src/piper_description/meshes/link3.STL +3 -0
  6. Piper_ros_private-ros-noetic/src/piper_description/meshes/link4.STL +3 -0
  7. Piper_ros_private-ros-noetic/src/piper_description/meshes/link5.STL +3 -0
  8. Piper_ros_private-ros-noetic/src/piper_description/meshes/link6.STL +3 -0
  9. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/base_link.STL +3 -0
  10. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link1.STL +3 -0
  11. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link2.STL +3 -0
  12. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link3.STL +3 -0
  13. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link4.STL +3 -0
  14. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link5.STL +3 -0
  15. Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link6.STL +3 -0
  16. aloha-devel/act/train.sh +20 -0
  17. aloha-devel/robomimic/algo/__pycache__/algo.cpython-38.pyc +0 -0
  18. aloha-devel/robomimic/algo/__pycache__/bcq.cpython-38.pyc +0 -0
  19. aloha-devel/robomimic/algo/__pycache__/cql.cpython-38.pyc +0 -0
  20. aloha-devel/robomimic/algo/__pycache__/diffusion_policy.cpython-38.pyc +0 -0
  21. aloha-devel/robomimic/algo/__pycache__/hbc.cpython-38.pyc +0 -0
  22. aloha-devel/robomimic/algo/__pycache__/td3_bc.cpython-38.pyc +0 -0
  23. aloha-devel/robomimic/scripts/config_gen/bc_xfmr_gen.py +169 -0
  24. aloha-devel/robomimic/scripts/config_gen/diffusion_gen.py +263 -0
  25. aloha-devel/robomimic/scripts/conversion/convert_roboturk_pilot.py +192 -0
  26. aloha-devel/robomimic/scripts/conversion/convert_to_robosuite_v141.py +156 -0
  27. aloha-devel/robomimic/scripts/conversion/extract_action_dict.py +81 -0
  28. aloha-devel/robomimic/scripts/conversion/robosuite_add_absolute_actions.py +306 -0
  29. aloha-devel/robomimic/scripts/dataset_states_to_obs.py +375 -0
  30. aloha-devel/robomimic/scripts/download_momart_datasets.py +161 -0
  31. aloha-devel/robomimic/scripts/filter_dataset_size.py +81 -0
  32. aloha-devel/robomimic/scripts/plot_model_predictions.py +213 -0
  33. aloha-devel/robomimic/scripts/setup_macros.py +32 -0
  34. aloha-devel/robomimic/scripts/split_train_val.py +105 -0
  35. aloha-devel/robomimic/scripts/train.py +512 -0
  36. camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/base_realsense_node.cpp.o +3 -0
  37. camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/realsense_node_factory.cpp.o +3 -0
  38. camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/t265_realsense_node.cpp.o +3 -0
  39. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/d2c_viewer.cpp.o +3 -0
  40. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_info.cpp.o +3 -0
  41. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_node.cpp.o +3 -0
  42. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_node_factory.cpp.o +3 -0
  43. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/point_cloud_proc/point_cloud_xyz.cpp.o +3 -0
  44. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/point_cloud_proc/point_cloud_xyzrgb.cpp.o +3 -0
  45. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ros_service.cpp.o +3 -0
  46. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/utils.cpp.o +3 -0
  47. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/uvc_camera_driver.cpp.o +3 -0
  48. camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera_node.dir/src/main.cpp.o +3 -0
  49. camera_ws/devel/lib/astra_camera/astra_camera_node +3 -0
  50. camera_ws/devel/lib/libastra_camera.so +3 -0
.gitattributes CHANGED
@@ -34,3 +34,56 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  Piper_ros_private-ros-noetic/asserts/pictures/piper_rviz.jpg filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
  Piper_ros_private-ros-noetic/asserts/pictures/piper_rviz.jpg filter=lfs diff=lfs merge=lfs -text
37
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/utils.cpp.o filter=lfs diff=lfs merge=lfs -text
38
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera_node.dir/src/main.cpp.o filter=lfs diff=lfs merge=lfs -text
39
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/base_link.STL filter=lfs diff=lfs merge=lfs -text
40
+ camera_ws/src/ros_astra_camera/include/openni2_redist/x64/PS1080Console filter=lfs diff=lfs merge=lfs -text
41
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm/OpenNI2/Drivers/libOniFile.so filter=lfs diff=lfs merge=lfs -text
42
+ camera_ws/devel/lib/astra_camera/astra_camera_node filter=lfs diff=lfs merge=lfs -text
43
+ camera_ws/src/ros_astra_camera/include/openni2_redist/x64/NiViewer filter=lfs diff=lfs merge=lfs -text
44
+ camera_ws/src/ros_astra_camera/include/openni2_redist/x64/OpenNI2/Drivers/libOniFile.so filter=lfs diff=lfs merge=lfs -text
45
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm/PS1080Console filter=lfs diff=lfs merge=lfs -text
46
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/uvc_camera_driver.cpp.o filter=lfs diff=lfs merge=lfs -text
47
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/d2c_viewer.cpp.o filter=lfs diff=lfs merge=lfs -text
48
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ros_service.cpp.o filter=lfs diff=lfs merge=lfs -text
49
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_info.cpp.o filter=lfs diff=lfs merge=lfs -text
50
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/base_link.STL filter=lfs diff=lfs merge=lfs -text
51
+ camera_ws/src/ros_astra_camera/cfg/1.png filter=lfs diff=lfs merge=lfs -text
52
+ camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/base_realsense_node.cpp.o filter=lfs diff=lfs merge=lfs -text
53
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm64/PS1080Console filter=lfs diff=lfs merge=lfs -text
54
+ camera_ws/src/ros_astra_camera/include/openni2_redist/x64/OpenNI2/Drivers/liborbbec.so filter=lfs diff=lfs merge=lfs -text
55
+ collect_data/docs/episode_0_qpos.png filter=lfs diff=lfs merge=lfs -text
56
+ camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/realsense_node_factory.cpp.o filter=lfs diff=lfs merge=lfs -text
57
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/point_cloud_proc/point_cloud_xyz.cpp.o filter=lfs diff=lfs merge=lfs -text
58
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link4.STL filter=lfs diff=lfs merge=lfs -text
59
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/link4.STL filter=lfs diff=lfs merge=lfs -text
60
+ camera_ws/src/realsense-ros/realsense2_description/meshes/plug.stl filter=lfs diff=lfs merge=lfs -text
61
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link2.STL filter=lfs diff=lfs merge=lfs -text
62
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_node_factory.cpp.o filter=lfs diff=lfs merge=lfs -text
63
+ camera_ws/src/realsense-ros/realsense2_description/meshes/d455.stl filter=lfs diff=lfs merge=lfs -text
64
+ camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/t265_realsense_node.cpp.o filter=lfs diff=lfs merge=lfs -text
65
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_node.cpp.o filter=lfs diff=lfs merge=lfs -text
66
+ camera_ws/src/ros_astra_camera/include/openni2_redist/x64/libOpenNI2.so filter=lfs diff=lfs merge=lfs -text
67
+ camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/point_cloud_proc/point_cloud_xyzrgb.cpp.o filter=lfs diff=lfs merge=lfs -text
68
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/link1.STL filter=lfs diff=lfs merge=lfs -text
69
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/link5.STL filter=lfs diff=lfs merge=lfs -text
70
+ camera_ws/devel/lib/libastra_camera.so filter=lfs diff=lfs merge=lfs -text
71
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm/libOpenNI2.so filter=lfs diff=lfs merge=lfs -text
72
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm64/NiViewer filter=lfs diff=lfs merge=lfs -text
73
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm64/libOpenNI2.so filter=lfs diff=lfs merge=lfs -text
74
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link1.STL filter=lfs diff=lfs merge=lfs -text
75
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/link2.STL filter=lfs diff=lfs merge=lfs -text
76
+ collect_data/docs/1.png filter=lfs diff=lfs merge=lfs -text
77
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link5.STL filter=lfs diff=lfs merge=lfs -text
78
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm/OpenNI2/Drivers/liborbbec.so filter=lfs diff=lfs merge=lfs -text
79
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm64/OpenNI2/Drivers/liborbbec.so filter=lfs diff=lfs merge=lfs -text
80
+ camera_ws/devel/lib/librealsense2_camera.so filter=lfs diff=lfs merge=lfs -text
81
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/link3.STL filter=lfs diff=lfs merge=lfs -text
82
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link3.STL filter=lfs diff=lfs merge=lfs -text
83
+ Piper_ros_private-ros-noetic/src/piper_description/meshes/link6.STL filter=lfs diff=lfs merge=lfs -text
84
+ camera_ws/src/ros_astra_camera/include/openni2_redist/arm64/OpenNI2/Drivers/libOniFile.so filter=lfs diff=lfs merge=lfs -text
85
+ camera_ws/src/realsense-ros/realsense2_description/meshes/d435.dae filter=lfs diff=lfs merge=lfs -text
86
+ Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link6.STL filter=lfs diff=lfs merge=lfs -text
87
+ camera_ws/src/realsense-ros/realsense2_description/meshes/d415.stl filter=lfs diff=lfs merge=lfs -text
88
+ camera_ws/src/realsense-ros/realsense2_description/meshes/l515.dae filter=lfs diff=lfs merge=lfs -text
89
+ collect_data/docs/1.gif filter=lfs diff=lfs merge=lfs -text
Piper_ros_private-ros-noetic/src/piper_description/meshes/base_link.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:931bbb6f5c5290b3b62a85158b8df5385cf062586382072806819dc393c62bc2
3
+ size 509684
Piper_ros_private-ros-noetic/src/piper_description/meshes/link1.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2c33c970be7eb178e8cca7c18e0f2f29a678bc1057e3387c5931104de11c3785
3
+ size 938084
Piper_ros_private-ros-noetic/src/piper_description/meshes/link2.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f9d1ee8f4861c7f04ee0ae100363c92cd10b6e9961fa81527345d6b88c397da7
3
+ size 2658484
Piper_ros_private-ros-noetic/src/piper_description/meshes/link3.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6b8befd0d8020ae1ebeb4bc6af3524c1d7fce12cff5524fe94f886fe7c110b8f
3
+ size 2511784
Piper_ros_private-ros-noetic/src/piper_description/meshes/link4.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:322f3f19233d4c312d3074dfecda3b13a285f08fd83ef5adac77020d8db541f3
3
+ size 730484
Piper_ros_private-ros-noetic/src/piper_description/meshes/link5.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:82700536a6c9a5cbd08d974f6785a0ecb38e66752a893df5ad68b87c13762890
3
+ size 1147884
Piper_ros_private-ros-noetic/src/piper_description/meshes/link6.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e0b2050ba81a45c79c045b9f13e3d1dd11f84bca1beb12eebc3102651c8476cf
3
+ size 671184
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/base_link.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:931bbb6f5c5290b3b62a85158b8df5385cf062586382072806819dc393c62bc2
3
+ size 509684
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link1.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2c33c970be7eb178e8cca7c18e0f2f29a678bc1057e3387c5931104de11c3785
3
+ size 938084
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link2.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f9d1ee8f4861c7f04ee0ae100363c92cd10b6e9961fa81527345d6b88c397da7
3
+ size 2658484
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link3.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:6b8befd0d8020ae1ebeb4bc6af3524c1d7fce12cff5524fe94f886fe7c110b8f
3
+ size 2511784
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link4.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:322f3f19233d4c312d3074dfecda3b13a285f08fd83ef5adac77020d8db541f3
3
+ size 730484
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link5.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:82700536a6c9a5cbd08d974f6785a0ecb38e66752a893df5ad68b87c13762890
3
+ size 1147884
Piper_ros_private-ros-noetic/src/piper_mujoco/mujoco_description/meshes_mujoco/link6.STL ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e0b2050ba81a45c79c045b9f13e3d1dd11f84bca1beb12eebc3102651c8476cf
3
+ size 671184
aloha-devel/act/train.sh ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ num_epochs=600
2
+ batch_size=48
3
+ num_episodes=80
4
+ ROOT=/inspire/hdd/ws-f4d69b29-e0a5-44e6-bd92-acf4de9990f0/public-project/chengdongzhou-240108390137/vla_projects/cobot_magic
5
+ train_dir=$ROOT/tranin_dir
6
+ pretrain_ckpt=$ROOT/policy_best.ckpt
7
+ ws_path=$(pwd)
8
+ dataset_dir=/inspire/ssd/ws-f4d69b29-e0a5-44e6-bd92-acf4de9990f0/public-project/public/aloha_group/blue_new
9
+ # echo "$pretrain_ckpt"
10
+ # echo "$train_dir"
11
+ # echo $(pwd)
12
+
13
+ cd $ws_path
14
+
15
+ python act/train.py --dataset $dataset_dir --ckpt_dir $train_dir/pretrain --batch_size $batch_size --num_epochs $num_epochs --num_episodes $num_episodes --pretrain_ckpt $pretrain_ckpt
16
+ python act/train.py --dataset /media/lin/T7/data0314/ --ckpt_dir $train_dir/no_pretrain --batch_size $batch_size --num_epochs $num_epochs --num_episodes $num_episodes
17
+
18
+
19
+
20
+ python act/train.py --dataset $dataset_dir --ckpt_dir $train_dir/no_pretrain --batch_size $batch_size --num_epochs $num_epochs --num_episodes $num_episodes
aloha-devel/robomimic/algo/__pycache__/algo.cpython-38.pyc ADDED
Binary file (23 kB). View file
 
aloha-devel/robomimic/algo/__pycache__/bcq.cpython-38.pyc ADDED
Binary file (31.9 kB). View file
 
aloha-devel/robomimic/algo/__pycache__/cql.cpython-38.pyc ADDED
Binary file (21.5 kB). View file
 
aloha-devel/robomimic/algo/__pycache__/diffusion_policy.cpython-38.pyc ADDED
Binary file (18.2 kB). View file
 
aloha-devel/robomimic/algo/__pycache__/hbc.cpython-38.pyc ADDED
Binary file (10.5 kB). View file
 
aloha-devel/robomimic/algo/__pycache__/td3_bc.cpython-38.pyc ADDED
Binary file (17 kB). View file
 
aloha-devel/robomimic/scripts/config_gen/bc_xfmr_gen.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from robomimic.scripts.config_gen.helper import *
2
+
3
+ def make_generator_helper(args):
4
+ algo_name_short = "bc_xfmr"
5
+
6
+ generator = get_generator(
7
+ algo_name="bc",
8
+ config_file=os.path.join(base_path, 'robomimic/exps/templates/bc_transformer.json'),
9
+ args=args,
10
+ algo_name_short=algo_name_short,
11
+ pt=True,
12
+ )
13
+ if args.ckpt_mode is None:
14
+ args.ckpt_mode = "off"
15
+
16
+ if args.env == "r2d2":
17
+ generator.add_param(
18
+ key="train.data",
19
+ name="ds",
20
+ group=2,
21
+ values=[
22
+ [{"path": p} for p in scan_datasets("~/Downloads/example_pen_in_cup", postfix="trajectory_im128.h5")],
23
+ ],
24
+ value_names=[
25
+ "pen-in-cup",
26
+ ],
27
+ )
28
+ generator.add_param(
29
+ key="observation.modalities.obs.rgb",
30
+ name="cams",
31
+ group=130,
32
+ values=[
33
+ # ["camera/image/hand_camera_left_image"],
34
+ ["camera/image/hand_camera_left_image", "camera/image/varied_camera_1_left_image", "camera/image/varied_camera_2_left_image"],
35
+ ],
36
+ value_names=[
37
+ # "wrist",
38
+ "3cams",
39
+ ]
40
+ )
41
+ elif args.env == "kitchen":
42
+ generator.add_param(
43
+ key="train.data",
44
+ name="ds",
45
+ group=2,
46
+ values=[
47
+ [
48
+ {
49
+ "path": "/home/aaronl/tmp/v2_demos/KitchenPnPCounterToCab_im84.hdf5",
50
+ "filter_key": "100_demos",
51
+ "lang": "pick and place the object from the counter to the cabinet",
52
+ },
53
+ {
54
+ "path": "/home/aaronl/tmp/v2_demos/KitchenPnPCabToCounter_im84.hdf5",
55
+ "filter_key": "100_demos",
56
+ "lang": "pick and place the object from the cabinet to the counter",
57
+ },
58
+ ],
59
+ ],
60
+ value_names=[
61
+ "pnp-multi-task"
62
+ ],
63
+ )
64
+ generator.add_param(
65
+ key="algo.language_conditioned",
66
+ name="langcond",
67
+ group=145892,
68
+ values=[
69
+ True,
70
+ False,
71
+ ],
72
+ )
73
+ elif args.env == "square":
74
+ generator.add_param(
75
+ key="train.data",
76
+ name="ds",
77
+ group=2,
78
+ values=[
79
+ [
80
+ {"path": "~/datasets/square/ph/square_ph_abs_tmp.hdf5"}, # replace with your own path
81
+ ],
82
+ ],
83
+ value_names=[
84
+ "square",
85
+ ],
86
+ )
87
+ else:
88
+ raise ValueError
89
+
90
+ # change default settings: predict 10 steps into future
91
+ generator.add_param(
92
+ key="algo.transformer.pred_future_acs",
93
+ name="predfuture",
94
+ group=1,
95
+ values=[
96
+ True,
97
+ # False,
98
+ ],
99
+ hidename=True,
100
+ )
101
+ generator.add_param(
102
+ key="algo.transformer.supervise_all_steps",
103
+ name="supallsteps",
104
+ group=1,
105
+ values=[
106
+ True,
107
+ # False,
108
+ ],
109
+ hidename=True,
110
+ )
111
+ generator.add_param(
112
+ key="algo.transformer.causal",
113
+ name="causal",
114
+ group=1,
115
+ values=[
116
+ False,
117
+ # True,
118
+ ],
119
+ hidename=True,
120
+ )
121
+ generator.add_param(
122
+ key="train.seq_length",
123
+ name="",
124
+ group=-1,
125
+ values=[10],
126
+ hidename=True,
127
+ )
128
+
129
+ generator.add_param(
130
+ key="algo.gmm.min_std",
131
+ name="mindstd",
132
+ group=271314,
133
+ values=[
134
+ 0.03,
135
+ #0.0001,
136
+ ],
137
+ hidename=True,
138
+ )
139
+ generator.add_param(
140
+ key="train.max_grad_norm",
141
+ name="maxgradnorm",
142
+ group=18371,
143
+ values=[
144
+ # None,
145
+ 100.0,
146
+ ],
147
+ hidename=True,
148
+ )
149
+
150
+ generator.add_param(
151
+ key="train.output_dir",
152
+ name="",
153
+ group=-1,
154
+ values=[
155
+ "~/expdata/{env}/{mod}/{algo_name_short}".format(
156
+ env=args.env,
157
+ mod=args.mod,
158
+ algo_name_short=algo_name_short,
159
+ )
160
+ ],
161
+ )
162
+
163
+ return generator
164
+
165
+ if __name__ == "__main__":
166
+ parser = get_argparser()
167
+
168
+ args = parser.parse_args()
169
+ make_generator(args, make_generator_helper)
aloha-devel/robomimic/scripts/config_gen/diffusion_gen.py ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from robomimic.scripts.config_gen.helper import *
2
+
3
+ def make_generator_helper(args):
4
+ algo_name_short = "diffusion_policy"
5
+
6
+ generator = get_generator(
7
+ algo_name="diffusion_policy",
8
+ config_file=os.path.join(base_path, 'robomimic/exps/templates/diffusion_policy.json'),
9
+ args=args,
10
+ algo_name_short=algo_name_short,
11
+ pt=True,
12
+ )
13
+ if args.ckpt_mode is None:
14
+ args.ckpt_mode = "off"
15
+
16
+ generator.add_param(
17
+ key="train.num_data_workers",
18
+ name="",
19
+ group=-1,
20
+ values=[8],
21
+ )
22
+
23
+ generator.add_param(
24
+ key="train.num_epochs",
25
+ name="",
26
+ group=-1,
27
+ values=[1000],
28
+ )
29
+
30
+ # use ddim by default
31
+ generator.add_param(
32
+ key="algo.ddim.enabled",
33
+ name="ddim",
34
+ group=1001,
35
+ values=[
36
+ True,
37
+ # False,
38
+ ],
39
+ hidename=True,
40
+ )
41
+ generator.add_param(
42
+ key="algo.ddpm.enabled",
43
+ name="ddpm",
44
+ group=1001,
45
+ values=[
46
+ False,
47
+ # True,
48
+ ],
49
+ hidename=True,
50
+ )
51
+
52
+ if args.env == "r2d2":
53
+ generator.add_param(
54
+ key="train.data",
55
+ name="ds",
56
+ group=2,
57
+ values=[
58
+ [{"path": p, "lang": "put the pen in the cup"} for p in scan_datasets("~/Downloads/example_pen_in_cup", postfix="trajectory_im128.h5")],
59
+ ],
60
+ value_names=[
61
+ "pen-in-cup",
62
+ ],
63
+ )
64
+ generator.add_param(
65
+ key="train.action_keys",
66
+ name="ac_keys",
67
+ group=-1,
68
+ values=[
69
+ [
70
+ "action/abs_pos",
71
+ "action/abs_rot_6d",
72
+ "action/gripper_position",
73
+ ],
74
+ ],
75
+ value_names=[
76
+ "abs",
77
+ ],
78
+ hidename=True,
79
+ )
80
+ generator.add_param(
81
+ key="observation.modalities.obs.rgb",
82
+ name="cams",
83
+ group=130,
84
+ values=[
85
+ # ["camera/image/hand_camera_left_image"],
86
+ # ["camera/image/hand_camera_left_image", "camera/image/hand_camera_right_image"],
87
+ ["camera/image/hand_camera_left_image", "camera/image/varied_camera_1_left_image", "camera/image/varied_camera_2_left_image"],
88
+ # [
89
+ # "camera/image/hand_camera_left_image", "camera/image/hand_camera_right_image",
90
+ # "camera/image/varied_camera_1_left_image", "camera/image/varied_camera_1_right_image",
91
+ # "camera/image/varied_camera_2_left_image", "camera/image/varied_camera_2_right_image",
92
+ # ],
93
+ ],
94
+ value_names=[
95
+ # "wrist",
96
+ # "wrist-stereo",
97
+ "3cams",
98
+ # "3cams-stereo",
99
+ ]
100
+ )
101
+
102
+ generator.add_param(
103
+ key="observation.modalities.obs.low_dim",
104
+ name="ldkeys",
105
+ group=2498,
106
+ values=[
107
+ ["robot_state/cartesian_position", "robot_state/gripper_position"],
108
+ # [
109
+ # "robot_state/cartesian_position", "robot_state/gripper_position",
110
+ # "camera/extrinsics/hand_camera_left", "camera/extrinsics/hand_camera_left_gripper_offset",
111
+ # "camera/extrinsics/hand_camera_right", "camera/extrinsics/hand_camera_right_gripper_offset",
112
+ # "camera/extrinsics/varied_camera_1_left", "camera/extrinsics/varied_camera_1_right",
113
+ # "camera/extrinsics/varied_camera_2_left", "camera/extrinsics/varied_camera_2_right",
114
+ # ]
115
+ ],
116
+ value_names=[
117
+ "proprio",
118
+ # "proprio-extrinsics",
119
+ ]
120
+ )
121
+
122
+ generator.add_param(
123
+ key="observation.encoder.rgb.core_kwargs.backbone_class",
124
+ name="backbone",
125
+ group=1234,
126
+ values=[
127
+ "ResNet18Conv",
128
+ # "ResNet50Conv",
129
+ ],
130
+ )
131
+ generator.add_param(
132
+ key="observation.encoder.rgb.core_kwargs.feature_dimension",
133
+ name="visdim",
134
+ group=1234,
135
+ values=[
136
+ 64,
137
+ # 512,
138
+ ],
139
+ )
140
+
141
+ generator.add_param(
142
+ key="algo.language_conditioned",
143
+ name="langcond",
144
+ group=145892,
145
+ values=[
146
+ True,
147
+ False,
148
+ ],
149
+ )
150
+
151
+ elif args.env == "kitchen":
152
+ generator.add_param(
153
+ key="train.data",
154
+ name="ds",
155
+ group=2,
156
+ values=[
157
+ # [{"path": "~/datasets/kitchen/prior/human_demos/pnp_table_to_cab/bowls/20230816_im84.hdf5", "filter_key": "100_demos"}],
158
+ [{"path": "~/datasets/kitchen/prior/human_demos/pnp_table_to_cab/all/20230806_im84.hdf5", "filter_key": "100_demos"}],
159
+ # [{"path": "~/datasets/kitchen/prior/mimicgen/pnp_table_to_cab/viraj_mg_2023-08-10-20-31-14/demo_im84.hdf5", "filter_key": "100_demos"}],
160
+ # [{"path": "~/datasets/kitchen/prior/mimicgen/pnp_table_to_cab/viraj_mg_2023-08-10-20-31-14/demo_im84.hdf5", "filter_key": "1000_demos"}],
161
+ ],
162
+ value_names=[
163
+ # "bowls-human-100",
164
+ "human-100",
165
+ # "mg-100",
166
+ # "mg-1000",
167
+ ],
168
+ )
169
+
170
+ # update env config to use absolute action control
171
+ generator.add_param(
172
+ key="experiment.env_meta_update_dict",
173
+ name="",
174
+ group=-1,
175
+ values=[
176
+ {"env_kwargs": {"controller_configs": {"control_delta": False}}}
177
+ ],
178
+ )
179
+
180
+ generator.add_param(
181
+ key="train.action_keys",
182
+ name="ac_keys",
183
+ group=-1,
184
+ values=[
185
+ [
186
+ "action_dict/abs_pos",
187
+ "action_dict/abs_rot_6d",
188
+ "action_dict/gripper",
189
+ "action_dict/base_mode",
190
+ # "actions",
191
+ ],
192
+ ],
193
+ value_names=[
194
+ "abs",
195
+ ],
196
+ hidename=True,
197
+ )
198
+ elif args.env == "square":
199
+ generator.add_param(
200
+ key="train.data",
201
+ name="ds",
202
+ group=2,
203
+ values=[
204
+ [
205
+ {"path": "~/datasets/square/ph/square_ph_abs_tmp.hdf5"}, # replace with your own path
206
+ ],
207
+ ],
208
+ value_names=[
209
+ "square",
210
+ ],
211
+ )
212
+
213
+ # update env config to use absolute action control
214
+ generator.add_param(
215
+ key="experiment.env_meta_update_dict",
216
+ name="",
217
+ group=-1,
218
+ values=[
219
+ {"env_kwargs": {"controller_configs": {"control_delta": False}}}
220
+ ],
221
+ )
222
+
223
+ generator.add_param(
224
+ key="train.action_keys",
225
+ name="ac_keys",
226
+ group=-1,
227
+ values=[
228
+ [
229
+ "action_dict/abs_pos",
230
+ "action_dict/abs_rot_6d",
231
+ "action_dict/gripper",
232
+ # "actions",
233
+ ],
234
+ ],
235
+ value_names=[
236
+ "abs",
237
+ ],
238
+ )
239
+
240
+
241
+ else:
242
+ raise ValueError
243
+
244
+ generator.add_param(
245
+ key="train.output_dir",
246
+ name="",
247
+ group=-1,
248
+ values=[
249
+ "~/expdata/{env}/{mod}/{algo_name_short}".format(
250
+ env=args.env,
251
+ mod=args.mod,
252
+ algo_name_short=algo_name_short,
253
+ )
254
+ ],
255
+ )
256
+
257
+ return generator
258
+
259
+ if __name__ == "__main__":
260
+ parser = get_argparser()
261
+
262
+ args = parser.parse_args()
263
+ make_generator(args, make_generator_helper)
aloha-devel/robomimic/scripts/conversion/convert_roboturk_pilot.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Helper script to convert the RoboTurk Pilot datasets (https://roboturk.stanford.edu/dataset_sim.html)
3
+ into a format compatible with this repository. It will also create some useful filter keys
4
+ in the file (e.g. training, validation, and fastest n trajectories). Prior work
5
+ (https://arxiv.org/abs/1911.05321) has found this useful (for example, training on the
6
+ fastest 225 demonstrations for bins-Can).
7
+
8
+ Direct download link for dataset: http://cvgl.stanford.edu/projects/roboturk/RoboTurkPilot.zip
9
+
10
+ Args:
11
+ folder (str): path to a folder containing a demo.hdf5 and a models directory containing
12
+ mujoco xml files. For example, RoboTurkPilot/bins-Can.
13
+
14
+ n (int): creates a filter key corresponding to the n fastest trajectories. Defaults to 225.
15
+
16
+ Example usage:
17
+
18
+ python convert_roboturk_pilot.py --folder /path/to/RoboTurkPilot/bins-Can --n 225
19
+ """
20
+
21
+ import os
22
+ import h5py
23
+ import json
24
+ import argparse
25
+ import numpy as np
26
+ from tqdm import tqdm
27
+
28
+ import robomimic
29
+ import robomimic.envs.env_base as EB
30
+ from robomimic.utils.file_utils import create_hdf5_filter_key
31
+ from robomimic.scripts.split_train_val import split_train_val_from_hdf5
32
+
33
+
34
+ def convert_rt_pilot_hdf5(ref_folder):
35
+ """
36
+ Uses the reference demo hdf5 to write a new converted hdf5 compatible with
37
+ the repository.
38
+
39
+ Args:
40
+ ref_folder (str): path to a folder containing a demo.hdf5 and a models directory containing
41
+ mujoco xml files.
42
+ """
43
+ hdf5_path = os.path.join(ref_folder, "demo.hdf5")
44
+ new_path = os.path.join(ref_folder, "demo_new.hdf5")
45
+
46
+ f = h5py.File(hdf5_path, "r")
47
+ f_new = h5py.File(new_path, "w")
48
+ f_new_grp = f_new.create_group("data")
49
+
50
+ # sorted list of demonstrations by demo number
51
+ demos = list(f["data"].keys())
52
+ inds = np.argsort([int(elem[5:]) for elem in demos])
53
+ demos = [demos[i] for i in inds]
54
+
55
+ # write each demo
56
+ num_samples_arr = []
57
+ for demo_id in tqdm(range(len(demos))):
58
+ ep = demos[demo_id]
59
+
60
+ # create group for this demonstration
61
+ ep_data_grp = f_new_grp.create_group(ep)
62
+
63
+ # copy states over
64
+ states = f["data/{}/states".format(ep)][()]
65
+ ep_data_grp.create_dataset("states", data=np.array(states))
66
+
67
+ # concat jvels and gripper actions to form full actions
68
+ jvels = f["data/{}/joint_velocities".format(ep)][()]
69
+ gripper_acts = f["data/{}/gripper_actuations".format(ep)][()]
70
+ actions = np.concatenate([jvels, gripper_acts], axis=1)
71
+
72
+ # IMPORTANT: clip actions to -1, 1, since this is expected by the codebase
73
+ actions = np.clip(actions, -1., 1.)
74
+ ep_data_grp.create_dataset("actions", data=actions)
75
+
76
+ # store model xml directly in the new hdf5 file
77
+ model_path = os.path.join(ref_folder, "models", f["data/{}".format(ep)].attrs["model_file"])
78
+ f_model = open(model_path, "r")
79
+ model_xml = f_model.read()
80
+ f_model.close()
81
+ ep_data_grp.attrs["model_file"] = model_xml
82
+
83
+ # store num samples for this ep
84
+ num_samples = actions.shape[0]
85
+ ep_data_grp.attrs["num_samples"] = num_samples # number of transitions in this episode
86
+ num_samples_arr.append(num_samples)
87
+
88
+ # write dataset attributes (metadata)
89
+ f_new_grp.attrs["total"] = np.sum(num_samples_arr)
90
+
91
+ # construct and save env metadata
92
+ env_meta = dict()
93
+ env_meta["type"] = EB.EnvType.ROBOSUITE_TYPE
94
+ env_meta["env_name"] = (f["data"].attrs["env"] + "Teleop")
95
+ # hardcode robosuite v0.3 args
96
+ robosuite_args = {
97
+ "has_renderer": False,
98
+ "has_offscreen_renderer": False,
99
+ "ignore_done": True,
100
+ "use_object_obs": True,
101
+ "use_camera_obs": False,
102
+ "camera_depth": False,
103
+ "camera_height": 84,
104
+ "camera_width": 84,
105
+ "camera_name": "agentview",
106
+ "gripper_visualization": False,
107
+ "reward_shaping": False,
108
+ "control_freq": 100,
109
+ }
110
+ env_meta["env_kwargs"] = robosuite_args
111
+ f_new_grp.attrs["env_args"] = json.dumps(env_meta, indent=4) # environment info
112
+
113
+ print("\n====== Added env meta ======")
114
+ print(f_new_grp.attrs["env_args"])
115
+
116
+ f.close()
117
+ f_new.close()
118
+
119
+ # back up the old dataset, and replace with new dataset
120
+ os.rename(hdf5_path, os.path.join(ref_folder, "demo_bak.hdf5"))
121
+ os.rename(new_path, hdf5_path)
122
+
123
+
124
+ def split_fastest_from_hdf5(hdf5_path, n):
125
+ """
126
+ Creates filter key for fastest N trajectories, named
127
+ "fastest_{}".format(n).
128
+
129
+ Args:
130
+ hdf5_path (str): path to the hdf5 file
131
+
132
+ n (int): fastest n demos to create filter key for
133
+ """
134
+
135
+ # retrieve fastest n demos
136
+ f = h5py.File(hdf5_path, "r")
137
+ demos = sorted(list(f["data"].keys()))
138
+ traj_lengths = []
139
+ for ep in demos:
140
+ traj_lengths.append(f["data/{}/actions".format(ep)].shape[0])
141
+ inds = np.argsort(traj_lengths)[:n]
142
+ filtered_demos = [demos[i] for i in inds]
143
+ f.close()
144
+
145
+ # create filter key
146
+ name = "fastest_{}".format(n)
147
+ lengths = create_hdf5_filter_key(hdf5_path=hdf5_path, demo_keys=filtered_demos, key_name=name)
148
+
149
+ print("Total number of samples in fastest {} demos: {}".format(n, np.sum(lengths)))
150
+ print("Average number of samples in fastest {} demos: {}".format(n, np.mean(lengths)))
151
+
152
+
153
+ if __name__ == "__main__":
154
+ parser = argparse.ArgumentParser()
155
+ parser.add_argument(
156
+ "--folder",
157
+ type=str,
158
+ help="path to a folder containing a demo.hdf5 and a models directory containing \
159
+ mujoco xml files. For example, RoboTurkPilot/bins-Can.",
160
+ )
161
+ parser.add_argument(
162
+ "--n",
163
+ type=int,
164
+ default=225,
165
+ help="creates a filter key corresponding to the n fastest trajectories. Defaults to 225.",
166
+ )
167
+ args = parser.parse_args()
168
+
169
+ # convert hdf5
170
+ convert_rt_pilot_hdf5(ref_folder=args.folder)
171
+
172
+ # create 90-10 train-validation split in the dataset
173
+ print("\nCreating 90-10 train-validation split...\n")
174
+ hdf5_path = os.path.join(args.folder, "demo.hdf5")
175
+ split_train_val_from_hdf5(hdf5_path=hdf5_path, val_ratio=0.1)
176
+
177
+ print("\nCreating filter key for fastest {} trajectories...".format(args.n))
178
+ split_fastest_from_hdf5(hdf5_path=hdf5_path, n=args.n)
179
+
180
+ print("\nCreating 90-10 train-validation split for fastest {} trajectories...".format(args.n))
181
+ split_train_val_from_hdf5(hdf5_path=hdf5_path, val_ratio=0.1, filter_key="fastest_{}".format(args.n))
182
+
183
+ print(
184
+ "\nWARNING: new dataset has replaced old one in demo.hdf5 file. "
185
+ "The old dataset file has been moved to demo_bak.hdf5"
186
+ )
187
+
188
+ print(
189
+ "\nNOTE: the new dataset also contains a fastest_{} filter key, for an easy way "
190
+ "to train on the fastest trajectories. Just set config.train.hdf5_filter to train on this "
191
+ "subset. A common choice is 225 when training on the bins-Can dataset.\n".format(args.n)
192
+ )
aloha-devel/robomimic/scripts/conversion/convert_to_robosuite_v141.py ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import h5py
2
+ import json
3
+ import argparse
4
+ import os
5
+ from shutil import copyfile
6
+ import robosuite
7
+ import xml.etree.ElementTree as ET
8
+
9
+ import robomimic.utils.obs_utils as ObsUtils
10
+ import robomimic.utils.env_utils as EnvUtils
11
+ import robomimic.utils.file_utils as FileUtils
12
+
13
+ from robosuite.utils.mjcf_utils import find_elements
14
+
15
+ def replace_elem(parent, old_elem, new_elem):
16
+ """
17
+ code adapted from https://stackoverflow.com/a/20931505
18
+ """
19
+ parent_index = list(parent).index(old_elem)
20
+ parent.remove(old_elem)
21
+ parent.insert(parent_index, new_elem)
22
+
23
+ def convert_xml(old_xml_str, env_name, env):
24
+ """
25
+ Postprocess xml string generated by robosuite to be compatible with robosuite v1.3
26
+ This script should not the xml string if it was already generated using robosuite v1.3
27
+ Args:
28
+ xml_str (str): xml string to process (from robosuite v1.2)
29
+ """
30
+
31
+ if env_name in ["PickPlaceCan", "NutAssemblySquare", "ToolHang"]:
32
+ xml_str = env.env.sim.model.get_xml()
33
+ elif env_name == "Lift":
34
+ xml_str = env.env.sim.model.get_xml()
35
+ # replace the cube_g0 and cube_g0_vis with elements in old_xml_str
36
+ old_et = ET.ElementTree(ET.fromstring(old_xml_str)).getroot()
37
+ new_et = ET.ElementTree(ET.fromstring(xml_str)).getroot()
38
+
39
+ cube_new = find_elements(
40
+ root=new_et,
41
+ tags="body",
42
+ attribs={"name": "cube_main"},
43
+ return_first=True
44
+ )
45
+
46
+ cube_old = find_elements(
47
+ root=old_et,
48
+ tags="body",
49
+ attribs={"name": "cube_main"},
50
+ return_first=True
51
+ )
52
+
53
+ worldbody_new = find_elements(
54
+ root=new_et,
55
+ tags="worldbody",
56
+ return_first=True
57
+ )
58
+
59
+ replace_elem(worldbody_new, cube_new, cube_old)
60
+
61
+ xml_str = ET.tostring(new_et, encoding="utf8").decode("utf8")
62
+ elif env_name == "TwoArmTransport":
63
+ xml_str = env.env.sim.model.get_xml()
64
+ # replace the cube_g0 and cube_g0_vis with elements in old_xml_str
65
+ old_et = ET.ElementTree(ET.fromstring(old_xml_str)).getroot()
66
+ new_et = ET.ElementTree(ET.fromstring(xml_str)).getroot()
67
+
68
+ worldbody_new = find_elements(
69
+ root=new_et,
70
+ tags="worldbody",
71
+ return_first=True
72
+ )
73
+ for bname in [
74
+ "payload_root",
75
+
76
+ ### ignore all these other following assets (makes playback worse for some reason...)
77
+ # "trash_main",
78
+ # "transport_start_bin_root", "transport_target_bin_root",
79
+ # "transport_trash_bin_root", "transport_start_bin_lid_root"
80
+ ]:
81
+ body_new = find_elements(
82
+ root=new_et,
83
+ tags="body",
84
+ attribs={"name": bname},
85
+ return_first=True
86
+ )
87
+
88
+ body_old = find_elements(
89
+ root=old_et,
90
+ tags="body",
91
+ attribs={"name": bname},
92
+ return_first=True
93
+ )
94
+
95
+ replace_elem(worldbody_new, body_new, body_old)
96
+
97
+ xml_str = ET.tostring(new_et, encoding="utf8").decode("utf8")
98
+
99
+ return xml_str
100
+
101
+ if __name__ == "__main__":
102
+ parser = argparse.ArgumentParser()
103
+ parser.add_argument(
104
+ "--dataset",
105
+ type=str,
106
+ help="path to input hdf5 dataset",
107
+ )
108
+ parser.add_argument(
109
+ "--output_dataset",
110
+ type=str,
111
+ help="path to output hdf5 dataset",
112
+ )
113
+ args = parser.parse_args()
114
+
115
+ args.dataset = os.path.expanduser(args.dataset)
116
+ args.output_dataset = os.path.expanduser(args.output_dataset)
117
+
118
+ assert args.output_dataset != args.dataset
119
+ assert robosuite.__version__ == '1.4.1'
120
+
121
+ copyfile(args.dataset, args.output_dataset)
122
+
123
+ f = h5py.File(args.output_dataset, "r+")
124
+
125
+ env_args = json.loads(f["data"].attrs["env_args"])
126
+ env_name = env_args["env_name"]
127
+
128
+ env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path=args.dataset)
129
+ env_type = EnvUtils.get_env_type(env_meta=env_meta)
130
+
131
+ # need to make sure ObsUtils knows which observations are images, but it doesn't matter
132
+ # for playback since observations are unused. Pass a dummy spec here.
133
+ dummy_spec = dict(
134
+ obs=dict(
135
+ low_dim=["robot0_eef_pos"],
136
+ rgb=[],
137
+ ),
138
+ )
139
+ ObsUtils.initialize_obs_utils_with_obs_specs(obs_modality_specs=dummy_spec)
140
+
141
+ env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path=args.dataset)
142
+ env = EnvUtils.create_env_from_metadata(env_meta=env_meta, render=False, render_offscreen=True)
143
+ env.reset()
144
+
145
+ for demo_key in list(f["data"].keys()):
146
+ ep_data_grp = f["data/{}".format(demo_key)]
147
+ model_file = ep_data_grp.attrs["model_file"]
148
+
149
+ coverted_model_file = convert_xml(model_file, env_name, env)
150
+ ep_data_grp.attrs["model_file"] = coverted_model_file
151
+
152
+ env_args = json.loads(f["data"].attrs["env_args"])
153
+ env_args["env_version"] = robosuite.__version__
154
+ f["data"].attrs["env_args"] = json.dumps(env_args, indent=4)
155
+
156
+ f.close()
aloha-devel/robomimic/scripts/conversion/extract_action_dict.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import pathlib
3
+ import sys
4
+ import tqdm
5
+ import h5py
6
+ import numpy as np
7
+ import torch
8
+ import os
9
+
10
+ import robomimic.utils.torch_utils as TorchUtils
11
+
12
+ def extract_action_dict(dataset):
13
+ # find files
14
+ f = h5py.File(os.path.expanduser(dataset), mode="r+")
15
+
16
+ SPECS = [
17
+ dict(
18
+ key="actions",
19
+ is_absolute=False,
20
+ ),
21
+ dict(
22
+ key="actions_abs",
23
+ is_absolute=True,
24
+ )
25
+ ]
26
+
27
+ # execute
28
+ for spec in SPECS:
29
+ input_action_key = spec["key"]
30
+ is_absolute = spec["is_absolute"]
31
+
32
+ if is_absolute:
33
+ prefix = "abs_"
34
+ else:
35
+ prefix = "rel_"
36
+
37
+ for demo in f["data"].values():
38
+ in_action = demo[str(input_action_key)][:]
39
+ in_pos = in_action[:,:3].astype(np.float32)
40
+ in_rot = in_action[:,3:6].astype(np.float32)
41
+ in_grip = in_action[:,6:7].astype(np.float32)
42
+
43
+ rot_6d = TorchUtils.axis_angle_to_rot_6d(
44
+ axis_angle=torch.from_numpy(in_rot)
45
+ )
46
+ rot_6d = rot_6d.numpy().astype(np.float32) # convert to numpy
47
+
48
+ this_action_dict = {
49
+ prefix + "pos": in_pos,
50
+ prefix + "rot_axis_angle": in_rot,
51
+ prefix + "rot_6d": rot_6d,
52
+ "gripper": in_grip
53
+ }
54
+
55
+ # special case: 8 dim actions mean there is a mobile base mode in the action space
56
+ if in_action.shape[1] == 8:
57
+ this_action_dict["base_mode"] = in_action[:,7:8].astype(np.float32)
58
+
59
+ action_dict_group = demo.require_group("action_dict")
60
+ for key, data in this_action_dict.items():
61
+ if key in action_dict_group:
62
+ del action_dict_group[key]
63
+ action_dict_group.create_dataset(key, data=data)
64
+
65
+ f.close()
66
+
67
+
68
+ def main():
69
+ parser = argparse.ArgumentParser()
70
+
71
+ parser.add_argument(
72
+ "--dataset",
73
+ type=str,
74
+ required=True
75
+ )
76
+
77
+ args = parser.parse_args()
78
+ extract_action_dict(args.dataset)
79
+
80
+ if __name__ == "__main__":
81
+ main()
aloha-devel/robomimic/scripts/conversion/robosuite_add_absolute_actions.py ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import multiprocessing
2
+ import os
3
+ import pathlib
4
+ import h5py
5
+ from tqdm import tqdm
6
+ import collections
7
+ import pickle
8
+ import argparse
9
+ import numpy as np
10
+ import copy
11
+
12
+ import h5py
13
+ import robomimic.utils.obs_utils as ObsUtils
14
+ import robomimic.utils.file_utils as FileUtils
15
+ import robomimic.utils.env_utils as EnvUtils
16
+ from scipy.spatial.transform import Rotation
17
+
18
+ from robomimic.config import config_factory
19
+
20
+ """
21
+ copied/adapted from https://github.com/columbia-ai-robotics/diffusion_policy/blob/main/diffusion_policy/common/robomimic_util.py
22
+ """
23
+ class RobomimicAbsoluteActionConverter:
24
+ def __init__(self, dataset_path, algo_name='bc'):
25
+ # default BC config
26
+ config = config_factory(algo_name=algo_name)
27
+
28
+ # read config to set up metadata for observation modalities (e.g. detecting rgb observations)
29
+ # must ran before create dataset
30
+ ObsUtils.initialize_obs_utils_with_config(config)
31
+
32
+ env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path)
33
+ abs_env_meta = copy.deepcopy(env_meta)
34
+ abs_env_meta['env_kwargs']['controller_configs']['control_delta'] = False
35
+
36
+ env = EnvUtils.create_env_from_metadata(
37
+ env_meta=env_meta,
38
+ render=False,
39
+ render_offscreen=False,
40
+ use_image_obs=False,
41
+ )
42
+ assert len(env.env.robots) in (1, 2)
43
+
44
+ abs_env = EnvUtils.create_env_from_metadata(
45
+ env_meta=abs_env_meta,
46
+ render=False,
47
+ render_offscreen=False,
48
+ use_image_obs=False,
49
+ )
50
+ assert not abs_env.env.robots[0].controller.use_delta
51
+
52
+ self.env = env
53
+ self.abs_env = abs_env
54
+ self.file = h5py.File(dataset_path, 'r')
55
+
56
+ def get_demo_keys(self):
57
+ return list(self.file['data'].keys())
58
+
59
+ def convert_actions(self,
60
+ states: np.ndarray,
61
+ actions: np.ndarray,
62
+ initial_state: dict) -> np.ndarray:
63
+ """
64
+ Given state and delta action sequence
65
+ generate equivalent goal position and orientation for each step
66
+ keep the original gripper action intact.
67
+ """
68
+ env = self.env
69
+ d_a = len(env.env.robots[0].action_limits[0])
70
+
71
+ # in case of multi robot
72
+ # reshape (N,14) to (N,2,7)
73
+ # or (N,7) to (N,1,7)
74
+ stacked_actions = actions.reshape(*actions.shape[:-1], -1, d_a)
75
+
76
+ # generate abs actions
77
+ action_goal_pos = np.zeros(
78
+ stacked_actions.shape[:-1]+(3,),
79
+ dtype=stacked_actions.dtype)
80
+ action_goal_ori = np.zeros(
81
+ stacked_actions.shape[:-1]+(3,),
82
+ dtype=stacked_actions.dtype)
83
+ action_remainder = stacked_actions[...,6:]
84
+ for i in range(len(states)):
85
+ if i == 0:
86
+ _ = env.reset_to(initial_state)
87
+ else:
88
+ _ = env.reset_to({'states': states[i]})
89
+
90
+ # taken from robot_env.py L#454
91
+ for idx, robot in enumerate(env.env.robots):
92
+ # run controller goal generator
93
+ robot.control(stacked_actions[i,idx], policy_step=True)
94
+
95
+ # read pos and ori from robots
96
+ controller = robot.controller
97
+ action_goal_pos[i,idx] = controller.goal_pos
98
+ action_goal_ori[i,idx] = Rotation.from_matrix(
99
+ controller.goal_ori).as_rotvec()
100
+
101
+ stacked_abs_actions = np.concatenate([
102
+ action_goal_pos,
103
+ action_goal_ori,
104
+ action_remainder
105
+ ], axis=-1)
106
+ abs_actions = stacked_abs_actions.reshape(actions.shape)
107
+ return abs_actions
108
+
109
+ def convert_demo(self, demo_key):
110
+ file = self.file
111
+ demo = file["data/{}".format(demo_key)]
112
+ # input
113
+ states = demo['states'][:]
114
+ actions = demo['actions'][:]
115
+ initial_state = dict(states=states[0])
116
+ initial_state["model"] = demo.attrs["model_file"]
117
+ initial_state["ep_meta"] = demo.attrs.get("ep_meta", None)
118
+
119
+ # generate abs actions
120
+ abs_actions = self.convert_actions(states, actions, initial_state=initial_state)
121
+ return abs_actions
122
+
123
+ def convert_and_eval_demo(self, demo_key):
124
+ raise NotImplementedError
125
+ env = self.env
126
+ abs_env = self.abs_env
127
+ file = self.file
128
+ # first step have high error for some reason, not representative
129
+ eval_skip_steps = 1
130
+
131
+ demo = file["data/{}".format(demo_key)]
132
+ # input
133
+ states = demo['states'][:]
134
+ actions = demo['actions'][:]
135
+
136
+ # generate abs actions
137
+ abs_actions = self.convert_actions(states, actions)
138
+
139
+ # verify
140
+ robot0_eef_pos = demo['obs']['robot0_eef_pos'][:]
141
+ robot0_eef_quat = demo['obs']['robot0_eef_quat'][:]
142
+
143
+ delta_error_info = self.evaluate_rollout_error(
144
+ env, states, actions, robot0_eef_pos, robot0_eef_quat,
145
+ metric_skip_steps=eval_skip_steps)
146
+ abs_error_info = self.evaluate_rollout_error(
147
+ abs_env, states, abs_actions, robot0_eef_pos, robot0_eef_quat,
148
+ metric_skip_steps=eval_skip_steps)
149
+
150
+ info = {
151
+ 'delta_max_error': delta_error_info,
152
+ 'abs_max_error': abs_error_info
153
+ }
154
+ return abs_actions, info
155
+
156
+ @staticmethod
157
+ def evaluate_rollout_error(env,
158
+ states, actions,
159
+ robot0_eef_pos,
160
+ robot0_eef_quat,
161
+ metric_skip_steps=1):
162
+ # first step have high error for some reason, not representative
163
+
164
+ # evaluate abs actions
165
+ rollout_next_states = list()
166
+ rollout_next_eef_pos = list()
167
+ rollout_next_eef_quat = list()
168
+ obs = env.reset_to({'states': states[0]})
169
+ for i in range(len(states)):
170
+ obs = env.reset_to({'states': states[i]})
171
+ obs, reward, done, info = env.step(actions[i])
172
+ obs = env.get_observation()
173
+ rollout_next_states.append(env.get_state()['states'])
174
+ rollout_next_eef_pos.append(obs['robot0_eef_pos'])
175
+ rollout_next_eef_quat.append(obs['robot0_eef_quat'])
176
+ rollout_next_states = np.array(rollout_next_states)
177
+ rollout_next_eef_pos = np.array(rollout_next_eef_pos)
178
+ rollout_next_eef_quat = np.array(rollout_next_eef_quat)
179
+
180
+ next_state_diff = states[1:] - rollout_next_states[:-1]
181
+ max_next_state_diff = np.max(np.abs(next_state_diff[metric_skip_steps:]))
182
+
183
+ next_eef_pos_diff = robot0_eef_pos[1:] - rollout_next_eef_pos[:-1]
184
+ next_eef_pos_dist = np.linalg.norm(next_eef_pos_diff, axis=-1)
185
+ max_next_eef_pos_dist = next_eef_pos_dist[metric_skip_steps:].max()
186
+
187
+ next_eef_rot_diff = Rotation.from_quat(robot0_eef_quat[1:]) \
188
+ * Rotation.from_quat(rollout_next_eef_quat[:-1]).inv()
189
+ next_eef_rot_dist = next_eef_rot_diff.magnitude()
190
+ max_next_eef_rot_dist = next_eef_rot_dist[metric_skip_steps:].max()
191
+
192
+ info = {
193
+ 'state': max_next_state_diff,
194
+ 'pos': max_next_eef_pos_dist,
195
+ 'rot': max_next_eef_rot_dist
196
+ }
197
+ return info
198
+
199
+ """
200
+ copied/adapted from https://github.com/columbia-ai-robotics/diffusion_policy/blob/main/diffusion_policy/scripts/robomimic_dataset_conversion.py
201
+ """
202
+ def worker(x):
203
+ path, demo_key, do_eval = x
204
+ converter = RobomimicAbsoluteActionConverter(path)
205
+ if do_eval:
206
+ abs_actions, info = converter.convert_and_eval_demo(demo_key)
207
+ else:
208
+ abs_actions = converter.convert_demo(demo_key)
209
+ info = dict()
210
+ return abs_actions, info
211
+
212
+
213
+ def add_absolute_actions_to_dataset(dataset, eval_dir, num_workers):
214
+ # process inputs
215
+ dataset = pathlib.Path(dataset).expanduser()
216
+ assert dataset.is_file()
217
+
218
+ do_eval = False
219
+ if eval_dir is not None:
220
+ eval_dir = pathlib.Path(eval_dir).expanduser()
221
+ assert eval_dir.parent.exists()
222
+ do_eval = True
223
+
224
+ converter = RobomimicAbsoluteActionConverter(dataset)
225
+ demo_keys = converter.get_demo_keys()
226
+ del converter
227
+
228
+ # run
229
+ with multiprocessing.Pool(num_workers) as pool:
230
+ results = pool.map(worker, [(dataset, demo_key, do_eval) for demo_key in demo_keys])
231
+
232
+ # modify action
233
+ with h5py.File(dataset, 'r+') as out_file:
234
+ for i in tqdm(range(len(results)), desc="Writing to output"):
235
+ abs_actions, info = results[i]
236
+ demo = out_file["data/{}".format(demo_keys[i])]
237
+ if "actions_abs" not in demo:
238
+ demo.create_dataset("actions_abs", data=np.array(abs_actions))
239
+ else:
240
+ demo['actions_abs'][:] = abs_actions
241
+
242
+ # save eval
243
+ if do_eval:
244
+ eval_dir.mkdir(parents=False, exist_ok=True)
245
+
246
+ print("Writing error_stats.pkl")
247
+ infos = [info for _, info in results]
248
+ pickle.dump(infos, eval_dir.joinpath('error_stats.pkl').open('wb'))
249
+
250
+ print("Generating visualization")
251
+ metrics = ['pos', 'rot']
252
+ metrics_dicts = dict()
253
+ for m in metrics:
254
+ metrics_dicts[m] = collections.defaultdict(list)
255
+
256
+ for i in range(len(infos)):
257
+ info = infos[i]
258
+ for k, v in info.items():
259
+ for m in metrics:
260
+ metrics_dicts[m][k].append(v[m])
261
+
262
+ from matplotlib import pyplot as plt
263
+ plt.switch_backend('PDF')
264
+
265
+ fig, ax = plt.subplots(1, len(metrics))
266
+ for i in range(len(metrics)):
267
+ axis = ax[i]
268
+ data = metrics_dicts[metrics[i]]
269
+ for key, value in data.items():
270
+ axis.plot(value, label=key)
271
+ axis.legend()
272
+ axis.set_title(metrics[i])
273
+ fig.set_size_inches(10,4)
274
+ fig.savefig(str(eval_dir.joinpath('error_stats.pdf')))
275
+ fig.savefig(str(eval_dir.joinpath('error_stats.png')))
276
+
277
+
278
+ if __name__ == "__main__":
279
+ parser = argparse.ArgumentParser()
280
+
281
+ parser.add_argument(
282
+ "--dataset",
283
+ type=str,
284
+ required=True
285
+ )
286
+
287
+ parser.add_argument(
288
+ "--eval_dir",
289
+ type=str,
290
+ help="directory to output evaluation metrics",
291
+ )
292
+
293
+ parser.add_argument(
294
+ "--num_workers",
295
+ type=int,
296
+ default=10,
297
+ )
298
+
299
+ args = parser.parse_args()
300
+
301
+
302
+ add_absolute_actions_to_dataset(
303
+ dataset=args.dataset,
304
+ eval_dir=args.eval_dir,
305
+ num_workers=args.num_workers,
306
+ )
aloha-devel/robomimic/scripts/dataset_states_to_obs.py ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Script to extract observations from low-dimensional simulation states in a robosuite dataset.
3
+
4
+ Args:
5
+ dataset (str): path to input hdf5 dataset
6
+
7
+ output_name (str): name of output hdf5 dataset
8
+
9
+ n (int): if provided, stop after n trajectories are processed
10
+
11
+ shaped (bool): if flag is set, use dense rewards
12
+
13
+ camera_names (str or [str]): camera name(s) to use for image observations.
14
+ Leave out to not use image observations.
15
+
16
+ camera_height (int): height of image observation.
17
+
18
+ camera_width (int): width of image observation
19
+
20
+ done_mode (int): how to write done signal. If 0, done is 1 whenever s' is a success state.
21
+ If 1, done is 1 at the end of each trajectory. If 2, both.
22
+
23
+ copy_rewards (bool): if provided, copy rewards from source file instead of inferring them
24
+
25
+ copy_dones (bool): if provided, copy dones from source file instead of inferring them
26
+
27
+ Example usage:
28
+
29
+ # extract low-dimensional observations
30
+ python dataset_states_to_obs.py --dataset /path/to/demo.hdf5 --output_name low_dim.hdf5 --done_mode 2
31
+
32
+ # extract 84x84 image observations
33
+ python dataset_states_to_obs.py --dataset /path/to/demo.hdf5 --output_name image.hdf5 \
34
+ --done_mode 2 --camera_names agentview robot0_eye_in_hand --camera_height 84 --camera_width 84
35
+
36
+ # (space saving option) extract 84x84 image observations with compression and without
37
+ # extracting next obs (not needed for pure imitation learning algos)
38
+ python dataset_states_to_obs.py --dataset /path/to/demo.hdf5 --output_name image.hdf5 \
39
+ --done_mode 2 --camera_names agentview robot0_eye_in_hand --camera_height 84 --camera_width 84 \
40
+ --compress --exclude-next-obs
41
+
42
+ # use dense rewards, and only annotate the end of trajectories with done signal
43
+ python dataset_states_to_obs.py --dataset /path/to/demo.hdf5 --output_name image_dense_done_1.hdf5 \
44
+ --done_mode 1 --dense --camera_names agentview robot0_eye_in_hand --camera_height 84 --camera_width 84
45
+ """
46
+ import os
47
+ import json
48
+ import h5py
49
+ import argparse
50
+ import numpy as np
51
+ from copy import deepcopy
52
+
53
+ import robomimic.utils.tensor_utils as TensorUtils
54
+ import robomimic.utils.file_utils as FileUtils
55
+ import robomimic.utils.env_utils as EnvUtils
56
+ from robomimic.envs.env_base import EnvBase
57
+
58
+
59
+ def extract_trajectory(
60
+ env,
61
+ initial_state,
62
+ states,
63
+ actions,
64
+ actions_abs,
65
+ done_mode,
66
+ ):
67
+ """
68
+ Helper function to extract observations, rewards, and dones along a trajectory using
69
+ the simulator environment.
70
+
71
+ Args:
72
+ env (instance of EnvBase): environment
73
+ initial_state (dict): initial simulation state to load
74
+ states (np.array): array of simulation states to load to extract information
75
+ actions (np.array): array of actions
76
+ done_mode (int): how to write done signal. If 0, done is 1 whenever s' is a
77
+ success state. If 1, done is 1 at the end of each trajectory.
78
+ If 2, do both.
79
+ """
80
+ assert isinstance(env, EnvBase)
81
+ assert states.shape[0] == actions.shape[0]
82
+
83
+ # load the initial state
84
+ ## this reset call doesn't seem necessary.
85
+ ## seems ok to remove but haven't fully tested it.
86
+ ## removing for now
87
+ # env.reset()
88
+ obs = env.reset_to(initial_state)
89
+
90
+ traj = dict(
91
+ obs=[],
92
+ next_obs=[],
93
+ rewards=[],
94
+ dones=[],
95
+ actions=np.array(actions),
96
+ states=np.array(states),
97
+ initial_state_dict=initial_state,
98
+ )
99
+ if actions_abs is not None:
100
+ traj["actions_abs"] = np.array(actions_abs)
101
+
102
+ traj_len = states.shape[0]
103
+ # iteration variable @t is over "next obs" indices
104
+ for t in range(1, traj_len + 1):
105
+
106
+ # get next observation
107
+ if t == traj_len:
108
+ # play final action to get next observation for last timestep
109
+ next_obs, _, _, _ = env.step(actions[t - 1])
110
+ else:
111
+ # reset to simulator state to get observation
112
+ next_obs = env.reset_to({"states" : states[t]})
113
+
114
+ # infer reward signal
115
+ # note: our tasks use reward r(s'), reward AFTER transition, so this is
116
+ # the reward for the current timestep
117
+ r = env.get_reward()
118
+
119
+ # infer done signal
120
+ done = False
121
+ if (done_mode == 1) or (done_mode == 2):
122
+ # done = 1 at end of trajectory
123
+ done = done or (t == traj_len)
124
+ if (done_mode == 0) or (done_mode == 2):
125
+ # done = 1 when s' is task success state
126
+ done = done or env.is_success()["task"]
127
+ done = int(done)
128
+
129
+ # collect transition
130
+ traj["obs"].append(obs)
131
+ traj["next_obs"].append(next_obs)
132
+ traj["rewards"].append(r)
133
+ traj["dones"].append(done)
134
+
135
+ # update for next iter
136
+ obs = deepcopy(next_obs)
137
+
138
+ # convert list of dict to dict of list for obs dictionaries (for convenient writes to hdf5 dataset)
139
+ traj["obs"] = TensorUtils.list_of_flat_dict_to_dict_of_list(traj["obs"])
140
+ traj["next_obs"] = TensorUtils.list_of_flat_dict_to_dict_of_list(traj["next_obs"])
141
+
142
+ # list to numpy array
143
+ for k in traj:
144
+ if k == "initial_state_dict":
145
+ continue
146
+ if isinstance(traj[k], dict):
147
+ for kp in traj[k]:
148
+ traj[k][kp] = np.array(traj[k][kp])
149
+ else:
150
+ traj[k] = np.array(traj[k])
151
+
152
+ return traj
153
+
154
+
155
+ def dataset_states_to_obs(args):
156
+ # create environment to use for data processing
157
+ env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path=args.dataset)
158
+ env = EnvUtils.create_env_for_data_processing(
159
+ env_meta=env_meta,
160
+ camera_names=args.camera_names,
161
+ camera_height=args.camera_height,
162
+ camera_width=args.camera_width,
163
+ reward_shaping=args.shaped,
164
+ )
165
+
166
+ print("==== Using environment with the following metadata ====")
167
+ print(json.dumps(env.serialize(), indent=4))
168
+ print("")
169
+
170
+ # some operations for playback are robosuite-specific, so determine if this environment is a robosuite env
171
+ is_robosuite_env = EnvUtils.is_robosuite_env(env_meta)
172
+
173
+ # list of all demonstration episodes (sorted in increasing number order)
174
+ f = h5py.File(args.dataset, "r")
175
+ demos = list(f["data"].keys())
176
+ inds = np.argsort([int(elem[5:]) for elem in demos])
177
+ demos = [demos[i] for i in inds]
178
+
179
+ # maybe reduce the number of demonstrations to playback
180
+ if args.n is not None:
181
+ demos = demos[:args.n]
182
+
183
+ # output file in same directory as input file
184
+ output_name = args.output_name
185
+ if output_name is None:
186
+ if len(args.camera_names) == 0:
187
+ output_name = os.path.basename(args.dataset)[:-5] + "_ld.hdf5"
188
+ else:
189
+ output_name = os.path.basename(args.dataset)[:-5] + "_im{}.hdf5".format(args.camera_width)
190
+
191
+ output_path = os.path.join(os.path.dirname(args.dataset), output_name)
192
+ f_out = h5py.File(output_path, "w")
193
+ data_grp = f_out.create_group("data")
194
+ print("input file: {}".format(args.dataset))
195
+ print("output file: {}".format(output_path))
196
+
197
+ total_samples = 0
198
+ for ind in range(len(demos)):
199
+ ep = demos[ind]
200
+
201
+ # prepare initial state to reload from
202
+ states = f["data/{}/states".format(ep)][()]
203
+ initial_state = dict(states=states[0])
204
+ if is_robosuite_env:
205
+ initial_state["model"] = f["data/{}".format(ep)].attrs["model_file"]
206
+ initial_state["ep_meta"] = f["data/{}".format(ep)].attrs.get("ep_meta", None)
207
+
208
+ # extract obs, rewards, dones
209
+ actions = f["data/{}/actions".format(ep)][()]
210
+ if "data/{}/actions_abs".format(ep) in f:
211
+ actions_abs = f["data/{}/actions_abs".format(ep)][()]
212
+ else:
213
+ actions_abs = None
214
+ traj = extract_trajectory(
215
+ env=env,
216
+ initial_state=initial_state,
217
+ states=states,
218
+ actions=actions,
219
+ actions_abs=actions_abs,
220
+ done_mode=args.done_mode,
221
+ )
222
+
223
+ # maybe copy reward or done signal from source file
224
+ if args.copy_rewards:
225
+ traj["rewards"] = f["data/{}/rewards".format(ep)][()]
226
+ if args.copy_dones:
227
+ traj["dones"] = f["data/{}/dones".format(ep)][()]
228
+
229
+ # store transitions
230
+
231
+ # IMPORTANT: keep name of group the same as source file, to make sure that filter keys are
232
+ # consistent as well
233
+ ep_data_grp = data_grp.create_group(ep)
234
+ ep_data_grp.create_dataset("actions", data=np.array(traj["actions"]))
235
+ ep_data_grp.create_dataset("states", data=np.array(traj["states"]))
236
+ ep_data_grp.create_dataset("rewards", data=np.array(traj["rewards"]))
237
+ ep_data_grp.create_dataset("dones", data=np.array(traj["dones"]))
238
+ if "actions_abs" in traj:
239
+ ep_data_grp.create_dataset("actions_abs", data=np.array(traj["actions_abs"]))
240
+ for k in traj["obs"]:
241
+ if args.compress:
242
+ ep_data_grp.create_dataset("obs/{}".format(k), data=np.array(traj["obs"][k]), compression="gzip")
243
+ else:
244
+ ep_data_grp.create_dataset("obs/{}".format(k), data=np.array(traj["obs"][k]))
245
+ if not args.exclude_next_obs:
246
+ if args.compress:
247
+ ep_data_grp.create_dataset("next_obs/{}".format(k), data=np.array(traj["next_obs"][k]), compression="gzip")
248
+ else:
249
+ ep_data_grp.create_dataset("next_obs/{}".format(k), data=np.array(traj["next_obs"][k]))
250
+
251
+ # copy action dict (if applicable)
252
+ if "data/{}/action_dict".format(ep) in f:
253
+ action_dict = f["data/{}/action_dict".format(ep)]
254
+ for k in action_dict:
255
+ ep_data_grp.create_dataset("action_dict/{}".format(k), data=np.array(action_dict[k][()]))
256
+
257
+ # episode metadata
258
+ if is_robosuite_env:
259
+ ep_data_grp.attrs["model_file"] = traj["initial_state_dict"]["model"] # model xml for this episode
260
+ if "ep_meta" in f["data/{}".format(ep)].attrs:
261
+ ep_data_grp.attrs["ep_meta"] = f["data/{}".format(ep)].attrs["ep_meta"]
262
+ ep_data_grp.attrs["num_samples"] = traj["actions"].shape[0] # number of transitions in this episode
263
+ total_samples += traj["actions"].shape[0]
264
+ print("ep {}: wrote {} transitions to group {}".format(ind, ep_data_grp.attrs["num_samples"], ep))
265
+
266
+
267
+ # copy over all filter keys that exist in the original hdf5
268
+ if "mask" in f:
269
+ f.copy("mask", f_out)
270
+
271
+ # global metadata
272
+ data_grp.attrs["total"] = total_samples
273
+ data_grp.attrs["env_args"] = json.dumps(env.serialize(), indent=4) # environment info
274
+ print("Wrote {} trajectories to {}".format(len(demos), output_path))
275
+
276
+ f.close()
277
+ f_out.close()
278
+
279
+
280
+ if __name__ == "__main__":
281
+ parser = argparse.ArgumentParser()
282
+ parser.add_argument(
283
+ "--dataset",
284
+ type=str,
285
+ required=True,
286
+ help="path to input hdf5 dataset",
287
+ )
288
+ # name of hdf5 to write - it will be in the same directory as @dataset
289
+ parser.add_argument(
290
+ "--output_name",
291
+ type=str,
292
+ help="name of output hdf5 dataset",
293
+ )
294
+
295
+ # specify number of demos to process - useful for debugging conversion with a handful
296
+ # of trajectories
297
+ parser.add_argument(
298
+ "--n",
299
+ type=int,
300
+ default=None,
301
+ help="(optional) stop after n trajectories are processed",
302
+ )
303
+
304
+ # flag for reward shaping
305
+ parser.add_argument(
306
+ "--shaped",
307
+ action='store_true',
308
+ help="(optional) use shaped rewards",
309
+ )
310
+
311
+ # camera names to use for observations
312
+ parser.add_argument(
313
+ "--camera_names",
314
+ type=str,
315
+ nargs='+',
316
+ default=[],
317
+ help="(optional) camera name(s) to use for image observations. Leave out to not use image observations.",
318
+ )
319
+
320
+ parser.add_argument(
321
+ "--camera_height",
322
+ type=int,
323
+ default=84,
324
+ help="(optional) height of image observations",
325
+ )
326
+
327
+ parser.add_argument(
328
+ "--camera_width",
329
+ type=int,
330
+ default=84,
331
+ help="(optional) width of image observations",
332
+ )
333
+
334
+ # specifies how the "done" signal is written. If "0", then the "done" signal is 1 wherever
335
+ # the transition (s, a, s') has s' in a task completion state. If "1", the "done" signal
336
+ # is one at the end of every trajectory. If "2", the "done" signal is 1 at task completion
337
+ # states for successful trajectories and 1 at the end of all trajectories.
338
+ parser.add_argument(
339
+ "--done_mode",
340
+ type=int,
341
+ default=0,
342
+ help="how to write done signal. If 0, done is 1 whenever s' is a success state.\
343
+ If 1, done is 1 at the end of each trajectory. If 2, both.",
344
+ )
345
+
346
+ # flag for copying rewards from source file instead of re-writing them
347
+ parser.add_argument(
348
+ "--copy_rewards",
349
+ action='store_true',
350
+ help="(optional) copy rewards from source file instead of inferring them",
351
+ )
352
+
353
+ # flag for copying dones from source file instead of re-writing them
354
+ parser.add_argument(
355
+ "--copy_dones",
356
+ action='store_true',
357
+ help="(optional) copy dones from source file instead of inferring them",
358
+ )
359
+
360
+ # flag to exclude next obs in dataset
361
+ parser.add_argument(
362
+ "--exclude-next-obs",
363
+ action='store_true',
364
+ help="(optional) exclude next obs in dataset",
365
+ )
366
+
367
+ # flag to compress observations with gzip option in hdf5
368
+ parser.add_argument(
369
+ "--compress",
370
+ action='store_true',
371
+ help="(optional) compress observations with gzip option in hdf5",
372
+ )
373
+
374
+ args = parser.parse_args()
375
+ dataset_states_to_obs(args)
aloha-devel/robomimic/scripts/download_momart_datasets.py ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Script to download datasets used in MoMaRT paper (https://arxiv.org/abs/2112.05251). By default, all
3
+ datasets will be stored at robomimic/datasets, unless the @download_dir
4
+ argument is supplied. We recommend using the default, as most examples that
5
+ use these datasets assume that they can be found there.
6
+
7
+ The @tasks and @dataset_types arguments can all be supplied
8
+ to choose which datasets to download.
9
+
10
+ Args:
11
+ download_dir (str): Base download directory. Created if it doesn't exist.
12
+ Defaults to datasets folder in repository - only pass in if you would
13
+ like to override the location.
14
+
15
+ tasks (list): Tasks to download datasets for. Defaults to table_setup_from_dishwasher task. Pass 'all' to
16
+ download all tasks - 5 total:
17
+ - table_setup_from_dishwasher
18
+ - table_setup_from_dresser
19
+ - table_cleanup_to_dishwasher
20
+ - table_cleanup_to_sink
21
+ - unload_dishwasher
22
+
23
+ dataset_types (list): Dataset types to download datasets for (expert, suboptimal, generalize, sample).
24
+ Defaults to expert. Pass 'all' to download datasets for all available dataset
25
+ types per task, or directly specify the list of dataset types.
26
+ NOTE: Because these datasets are huge, we will always print out a warning
27
+ that a user must respond yes to to acknowledge the data size (can be up to >100G for all tasks of a single type)
28
+
29
+ Example usage:
30
+
31
+ # default behavior - just download expert table_setup_from_dishwasher dataset
32
+ python download_momart_datasets.py
33
+
34
+ # download expert datasets for all tasks
35
+ # (do a dry run first to see which datasets would be downloaded)
36
+ python download_momart_datasets.py --tasks all --dataset_types expert --dry_run
37
+ python download_momart_datasets.py --tasks all --dataset_types expert low_dim
38
+
39
+ # download all expert and suboptimal datasets for the table_setup_from_dishwasher and table_cleanup_to_dishwasher tasks
40
+ python download_datasets.py --tasks table_setup_from_dishwasher table_cleanup_to_dishwasher --dataset_types expert suboptimal
41
+
42
+ # download the sample datasets
43
+ python download_datasets.py --tasks all --dataset_types sample
44
+
45
+ # download all datasets
46
+ python download_datasets.py --tasks all --dataset_types all
47
+ """
48
+ import os
49
+ import argparse
50
+
51
+ import robomimic
52
+ import robomimic.utils.file_utils as FileUtils
53
+ from robomimic import MOMART_DATASET_REGISTRY
54
+
55
+ ALL_TASKS = [
56
+ "table_setup_from_dishwasher",
57
+ "table_setup_from_dresser",
58
+ "table_cleanup_to_dishwasher",
59
+ "table_cleanup_to_sink",
60
+ "unload_dishwasher",
61
+ ]
62
+ ALL_DATASET_TYPES = [
63
+ "expert",
64
+ "suboptimal",
65
+ "generalize",
66
+ "sample",
67
+ ]
68
+
69
+
70
+ if __name__ == "__main__":
71
+ parser = argparse.ArgumentParser()
72
+
73
+ # directory to download datasets to
74
+ parser.add_argument(
75
+ "--download_dir",
76
+ type=str,
77
+ default=None,
78
+ help="Base download directory. Created if it doesn't exist. Defaults to datasets folder in repository.",
79
+ )
80
+
81
+ # tasks to download datasets for
82
+ parser.add_argument(
83
+ "--tasks",
84
+ type=str,
85
+ nargs='+',
86
+ default=["table_setup_from_dishwasher"],
87
+ help="Tasks to download datasets for. Defaults to table_setup_from_dishwasher task. Pass 'all' to download all"
88
+ f"5 tasks, or directly specify the list of tasks. Options are any of: {ALL_TASKS}",
89
+ )
90
+
91
+ # dataset types to download datasets for
92
+ parser.add_argument(
93
+ "--dataset_types",
94
+ type=str,
95
+ nargs='+',
96
+ default=["expert"],
97
+ help="Dataset types to download datasets for (e.g. expert, suboptimal). Defaults to expert. Pass 'all' to "
98
+ "download datasets for all available dataset types per task, or directly specify the list of dataset "
99
+ f"types. Options are any of: {ALL_DATASET_TYPES}",
100
+ )
101
+
102
+ # dry run - don't actually download datasets, but print which datasets would be downloaded
103
+ parser.add_argument(
104
+ "--dry_run",
105
+ action='store_true',
106
+ help="set this flag to do a dry run to only print which datasets would be downloaded"
107
+ )
108
+
109
+ args = parser.parse_args()
110
+
111
+ # set default base directory for downloads
112
+ default_base_dir = args.download_dir
113
+ if default_base_dir is None:
114
+ default_base_dir = os.path.join(robomimic.__path__[0], "../datasets")
115
+
116
+ # load args
117
+ download_tasks = args.tasks
118
+ if "all" in download_tasks:
119
+ assert len(download_tasks) == 1, "all should be only tasks argument but got: {}".format(args.tasks)
120
+ download_tasks = ALL_TASKS
121
+
122
+ download_dataset_types = args.dataset_types
123
+ if "all" in download_dataset_types:
124
+ assert len(download_dataset_types) == 1, "all should be only dataset_types argument but got: {}".format(args.dataset_types)
125
+ download_dataset_types = ALL_DATASET_TYPES
126
+
127
+ # Run sanity check first to warn user if they're about to download a huge amount of data
128
+ total_size = 0
129
+ for task in MOMART_DATASET_REGISTRY:
130
+ if task in download_tasks:
131
+ for dataset_type in MOMART_DATASET_REGISTRY[task]:
132
+ if dataset_type in download_dataset_types:
133
+ total_size += MOMART_DATASET_REGISTRY[task][dataset_type]["size"]
134
+
135
+ # Verify user acknowledgement if we're not doing a dry run
136
+ if not args.dry_run:
137
+ user_response = input(f"Warning: requested datasets will take a total of {total_size}GB. Proceed? y/n\n")
138
+ assert user_response.lower() in {"yes", "y"}, f"Did not receive confirmation. Aborting download."
139
+
140
+ # download requested datasets
141
+ for task in MOMART_DATASET_REGISTRY:
142
+ if task in download_tasks:
143
+ for dataset_type in MOMART_DATASET_REGISTRY[task]:
144
+ if dataset_type in download_dataset_types:
145
+ dataset_info = MOMART_DATASET_REGISTRY[task][dataset_type]
146
+ download_dir = os.path.abspath(os.path.join(default_base_dir, task, dataset_type))
147
+ print(f"\nDownloading dataset:\n"
148
+ f" task: {task}\n"
149
+ f" dataset type: {dataset_type}\n"
150
+ f" dataset size: {dataset_info['size']}GB\n"
151
+ f" download path: {download_dir}")
152
+ if args.dry_run:
153
+ print("\ndry run: skip download")
154
+ else:
155
+ # Make sure path exists and create if it doesn't
156
+ os.makedirs(download_dir, exist_ok=True)
157
+ FileUtils.download_url(
158
+ url=dataset_info["url"],
159
+ download_dir=download_dir,
160
+ )
161
+ print("")
aloha-devel/robomimic/scripts/filter_dataset_size.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import h5py
3
+ import numpy as np
4
+
5
+ from robomimic.utils.file_utils import create_hdf5_filter_key
6
+
7
+
8
+ def filter_dataset_size(hdf5_path, num_demos, input_filter_key=None, output_filter_key=None):
9
+ # retrieve number of demos
10
+ f = h5py.File(hdf5_path, "r")
11
+ if input_filter_key is not None:
12
+ print("using filter key: {}".format(input_filter_key))
13
+ demos = sorted([elem.decode("utf-8") for elem in np.array(f["mask/{}".format(input_filter_key)])])
14
+ else:
15
+ demos = sorted(list(f["data"].keys()))
16
+ f.close()
17
+
18
+ # get random split
19
+ total_num_demos = len(demos)
20
+ mask = np.zeros(total_num_demos)
21
+ mask[:num_demos] = 1.
22
+ np.random.shuffle(mask)
23
+ mask = mask.astype(int)
24
+ subset_inds = mask.nonzero()[0]
25
+ subset_keys = [demos[i] for i in subset_inds]
26
+
27
+ # pass mask to generate split
28
+ if output_filter_key is not None:
29
+ name = output_filter_key
30
+ else:
31
+ name = "{}_demos".format(num_demos)
32
+
33
+ if input_filter_key is not None:
34
+ name = "{}_{}".format(input_filter_key, name)
35
+
36
+ subset_lengths = create_hdf5_filter_key(hdf5_path=hdf5_path, demo_keys=subset_keys, key_name=name)
37
+
38
+ print("Total number of subset samples: {}".format(np.sum(subset_lengths)))
39
+ print("Average number of subset samples {}".format(np.mean(subset_lengths)))
40
+
41
+
42
+ if __name__ == "__main__":
43
+ parser = argparse.ArgumentParser()
44
+ parser.add_argument(
45
+ "--dataset",
46
+ type=str,
47
+ required=True,
48
+ help="path to hdf5 dataset",
49
+ )
50
+ parser.add_argument(
51
+ "--input_filter_key",
52
+ type=str,
53
+ default=None,
54
+ help="if provided, split the subset of trajectories in the file that correspond to\
55
+ this filter key into a training and validation set of trajectories, instead of\
56
+ splitting the full set of trajectories",
57
+ )
58
+ parser.add_argument(
59
+ "--num_demos",
60
+ type=int,
61
+ nargs='+',
62
+ required=True,
63
+ )
64
+ parser.add_argument(
65
+ "--output_filter_key",
66
+ type=str,
67
+ required=False,
68
+ help="(optional) use custom name for output filter key name"
69
+ )
70
+ args = parser.parse_args()
71
+
72
+ # seed to make sure results are consistent
73
+ np.random.seed(0)
74
+
75
+ for n in args.num_demos:
76
+ filter_dataset_size(
77
+ args.dataset,
78
+ input_filter_key=args.input_filter_key,
79
+ num_demos=n,
80
+ output_filter_key=args.output_filter_key,
81
+ )
aloha-devel/robomimic/scripts/plot_model_predictions.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ import matplotlib.gridspec as gridspec
6
+ from copy import deepcopy
7
+ import random
8
+ from sklearn.metrics import mean_squared_error
9
+ import re
10
+ import robomimic.utils.file_utils as FileUtils
11
+ import robomimic.utils.torch_utils as TorchUtils
12
+ import robomimic.utils.tensor_utils as TensorUtils
13
+ import robomimic.utils.train_utils as TrainUtils
14
+ from robomimic.config import config_factory
15
+ import robomimic.utils.obs_utils as ObsUtils
16
+ import torch
17
+ from torch.utils.data import DataLoader
18
+
19
+ """
20
+ TODO: track rotation magnitude seperately (https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.magnitude.html)
21
+ """
22
+
23
+ # the configs of the models to be plotted
24
+ model_config_mapping = {
25
+ # "bottle_less_obs": {
26
+ # "model":"/home/zehan/expdata/r2d2/im/bc_xfmr/google_bc_baseline/bottle_less_obs/20230815225106/models/model_epoch_60.pth",
27
+ # 'folder':"/home/zehan/expdata/r2d2/im/bc_xfmr/google_bc_baseline/bottle_less_obs/20230815225106/test_inference_figures/",
28
+ # # "action_names": ['x', 'y', 'z', 'roll', 'pitch', 'yaw', "gripper_action" , 'terminate'],
29
+ # "action_names": None,
30
+ # "trajectory_name_regex": r'(\d+_trajectory_im\d+)'
31
+ # },
32
+ "r2d2_wire": {
33
+ # "model": "/home/soroushn/expdata/r2d2/im/diffusion_policy/debug/ds_pen-in-cup_cams_3cams/20230830160945/models/model_epoch_2.pth",
34
+ "model": "/home/soroushn/expdata/r2d2/im/bc_xfmr/debug/ds_pen-in-cup_cams_3cams_predfuture_True_ac_keys_rel/20230830161631/models/model_epoch_2.pth",
35
+ "folder": "/home/soroushn/tmp/model_predictions",
36
+ # "action_names": ['x', 'y', 'z', 'r', 'p', 'y', "gripper_pos"], # use custom names
37
+ "action_names": None, # use default names, see line 71
38
+ "trajectory_name_regex": r'(\w+_\w+_\d{2}_\d{2}:\d{2}:\d{2}_\d{4})' # the name of the figure files need to be custom defined (the part of the names of the trajectories that uniquely identifies them)
39
+ }
40
+ }
41
+
42
+ NUM_SAMPLES = 2
43
+
44
+ # loop through each model
45
+ for model_name in model_config_mapping:
46
+ ckpt_path = model_config_mapping[model_name]['model']
47
+ saving_folder = model_config_mapping[model_name]['folder']
48
+ # can custom-define or using default action_names
49
+ action_names = model_config_mapping[model_name]['action_names']
50
+ trajectory_name_regex = model_config_mapping[model_name]['trajectory_name_regex']
51
+ accuracy_thresholds = np.logspace(-3,-5, num=3).tolist()
52
+
53
+
54
+
55
+ device = TorchUtils.get_torch_device(try_to_use_cuda=True)
56
+
57
+ ckpt_dict = FileUtils.maybe_dict_from_checkpoint(ckpt_path=ckpt_path)
58
+ config = json.loads(ckpt_dict["config"])
59
+ config["train"]["shuffled_obs_key_groups"] = None
60
+ ckpt_dict["config"] = json.dumps(config)
61
+ policy, _ = FileUtils.policy_from_checkpoint(ckpt_dict=ckpt_dict, device=device, verbose=True)
62
+ shape_meta = ckpt_dict['shape_metadata']
63
+ ext_cfg = json.loads(ckpt_dict["config"])
64
+ config = config_factory(ext_cfg["algo_name"])
65
+ with config.values_unlocked():
66
+ config.update(ext_cfg)
67
+
68
+
69
+ frame_stack = config.train.frame_stack
70
+ device = TorchUtils.get_torch_device(try_to_use_cuda=config.train.cuda)
71
+
72
+ trainset, validset = TrainUtils.load_data_for_training(config, obs_keys=shape_meta["all_obs_keys"])
73
+ # trainset.datasets is a list
74
+ # the trajectories to plot is randomly sampled from the training and validation sets
75
+ training_sampled_data = random.sample(trainset.datasets, NUM_SAMPLES)
76
+ # validation_sampled_data = random.sample(validset.datasets, NUM_SAMPLES)
77
+
78
+ inference_datasets_mapping = {"training": training_sampled_data} #, "validation": validation_sampled_data}
79
+
80
+
81
+ if action_names == None:
82
+ # TODO
83
+ action_keys = config.train.action_keys # Need to adjust. For Robomimic datasets, there is no `action_keys`, it is config.train.dataset_keys
84
+ modified_action_keys = [element.replace('action/', '') for element in action_keys]
85
+ action_names = []
86
+ for i, action_key in enumerate(action_keys):
87
+ if isinstance(training_sampled_data[0].__getitem__(0)[action_key][frame_stack-1], np.ndarray):
88
+ action_names.extend([f'{modified_action_keys[i]}_{j+1}' for j in range(len(training_sampled_data[0].__getitem__(0)[action_key][frame_stack-1]))])
89
+ else:
90
+ action_names.append(modified_action_keys[i])
91
+
92
+ # loop through training and validation sets
93
+ for inference_key in inference_datasets_mapping:
94
+ mse_training_per_traj = []
95
+ data_name = []
96
+ actual_actions_all_traj = [] # (NxT, D)
97
+ predicted_actions_all_traj = [] # (NxT, D)
98
+
99
+ # loop through each trajectory
100
+ for d in inference_datasets_mapping[inference_key]:
101
+ hdf5_path = d.hdf5_path
102
+ mse_for_one_traj = []
103
+ traj_length = len(d)
104
+ action_dim = len(action_names)
105
+ actual_actions = [[] for _ in range(action_dim)] # (T, D)
106
+ predicted_actions = [[] for _ in range(action_dim)] # (T, D)
107
+
108
+ image_keys = [item for item in d.__getitem__(0)['obs'].keys() if "image" in item]
109
+ images = {key: [] for key in image_keys}
110
+
111
+ dataloader = DataLoader(
112
+ dataset=d,
113
+ sampler=None,
114
+ batch_size=1,
115
+ shuffle=False,
116
+ num_workers=1,
117
+ drop_last=True,
118
+ )
119
+
120
+ model = policy.policy
121
+
122
+ model.reset()
123
+
124
+ # loop through each timestep
125
+ for batch in iter(dataloader):
126
+ batch = model.process_batch_for_training(batch)
127
+
128
+ for image_key in image_keys:
129
+ im = batch["obs"][image_key][0][-1]
130
+ im = TensorUtils.to_numpy(im).astype(np.uint32)
131
+ images[image_key].append(im)
132
+
133
+ batch = model.postprocess_batch_for_training(batch, obs_normalization_stats=None) # ignore obs_normalization for now
134
+ # model_output = model.nets["policy"](batch["obs"])
135
+
136
+ model_output = model.get_action(batch["obs"])
137
+
138
+ actual_action = TensorUtils.to_numpy(
139
+ batch["actions"][0][0]
140
+ )
141
+ predicted_action = TensorUtils.to_numpy(
142
+ model_output[0]
143
+ )
144
+
145
+ actual_actions_all_traj.append(actual_action)
146
+ predicted_actions_all_traj.append(predicted_action)
147
+
148
+ for dim in range(action_dim):
149
+ actual_actions[dim].append(actual_action[dim])
150
+ predicted_actions[dim].append(predicted_action[dim])
151
+
152
+ # Plot
153
+ fig, axs = plt.subplots(len(images) + action_dim, 1, figsize=(30, (len(images) + action_dim) * 3))
154
+ for i, image_key in enumerate(image_keys):
155
+ interval = int(traj_length/15) # plot `5` images
156
+ images[image_key] = images[image_key][::interval]
157
+ combined_images = np.concatenate(images[image_key], axis=1)
158
+ axs[i].imshow(combined_images)
159
+ if i == 0:
160
+ axs[i].set_title(hdf5_path + '\n' + image_key, fontsize=30)
161
+ else:
162
+ axs[i].set_title(image_key, fontsize=30)
163
+ axs[i].axis("off")
164
+ for dim in range(action_dim):
165
+ mse = mean_squared_error(actual_actions[dim], predicted_actions[dim])
166
+ mse_for_one_traj.append(mse)
167
+ axs[len(images)+dim].plot(range(traj_length), actual_actions[dim], label='Actual Action', color='blue')
168
+ axs[len(images)+dim].plot(range(traj_length), predicted_actions[dim], label='Predicted Action', color='red')
169
+ # axs[len(images)+dim].set_xlabel('Timestep')
170
+ # axs[len(images)+dim].set_ylabel('Action Dimension {}'.format(dim + 1))
171
+ axs[len(images)+dim].set_title(action_names[dim], fontsize=30)
172
+ axs[len(images)+dim].xaxis.set_tick_params(labelsize=24)
173
+ axs[len(images)+dim].yaxis.set_tick_params(labelsize=24)
174
+ axs[len(images)+dim].legend(fontsize=20)
175
+ plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.05, wspace=0.3, hspace=0.6)
176
+
177
+ # Save inference figures
178
+ save_path = saving_folder + inference_key+"/" #remember to add / at the end
179
+ # data_content = re.search(trajectory_name_regex, hdf5_path).group(1)
180
+ data_content = "test"
181
+ filename = "comparison_figure_"+data_content +".png"
182
+ if not os.path.exists(save_path):
183
+ os.makedirs(save_path)
184
+ print(save_path + filename)
185
+ # Save the figure with the specified path and filename
186
+ plt.savefig(save_path + filename)
187
+ mse_training_per_traj.append(mse_for_one_traj)
188
+ data_name.append(hdf5_path)
189
+
190
+ # log MSE information
191
+ accuracy_thresholds = np.logspace(-3,-5, num=3).tolist()
192
+ mse = torch.nn.functional.mse_loss(torch.tensor(predicted_actions_all_traj), torch.tensor(actual_actions_all_traj), reduction='none') # (NxT, D)
193
+ step_log = {}
194
+ step_log[f'{inference_key}_action_mse_error'] = mse.mean().item() # average MSE across all timesteps averaged across all action dimensions (D,)
195
+
196
+ # compute percentage of timesteps that have MSE less than the accuracy thresholds
197
+ for accuracy_threshold in accuracy_thresholds:
198
+ step_log[f'{inference_key}_action_accuracy@{accuracy_threshold}'] = (torch.less(mse,accuracy_threshold).float().mean().item())
199
+
200
+
201
+ average_mse_per_dimension = np.mean(mse_training_per_traj, axis=0) # (D,)
202
+ txt_path = saving_folder+inference_key+"/" +"output.txt"
203
+ list_str = '\n'.join(['{} {}'.format(desc, ' '.join(map(str, sublist))) for desc, sublist in zip(data_name, mse_training_per_traj)])
204
+
205
+ # save MSE information
206
+ with open(txt_path, "w+") as txt_file:
207
+ txt_file.write(f"MSE per trajectory:\n{list_str}\n")
208
+ txt_file.write("\n")
209
+ txt_file.write(f"Average MSE across trajectories per dimension: {average_mse_per_dimension}\n")
210
+ txt_file.write("\n")
211
+ txt_file.write(f"MSE log: {step_log}\n")
212
+
213
+
aloha-devel/robomimic/scripts/setup_macros.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This script sets up a private macros file.
3
+
4
+ The private macros file (macros_private.py) is not tracked by git,
5
+ allowing user-specific settings that are not tracked by git.
6
+
7
+ This script checks if macros_private.py exists.
8
+ If applicable, it creates the private macros at robomimic/macros_private.py
9
+ """
10
+
11
+ import os
12
+ import robomimic
13
+ import shutil
14
+
15
+ if __name__ == "__main__":
16
+ base_path = robomimic.__path__[0]
17
+ macros_path = os.path.join(base_path, "macros.py")
18
+ macros_private_path = os.path.join(base_path, "macros_private.py")
19
+
20
+ if not os.path.exists(macros_path):
21
+ print("{} does not exist! Aborting...".format(macros_path))
22
+
23
+ if os.path.exists(macros_private_path):
24
+ ans = input("{} already exists! \noverwrite? (y/n)\n".format(macros_private_path))
25
+
26
+ if ans == "y":
27
+ print("REMOVING")
28
+ else:
29
+ exit()
30
+
31
+ shutil.copyfile(macros_path, macros_private_path)
32
+ print("copied {}\nto {}".format(macros_path, macros_private_path))
aloha-devel/robomimic/scripts/split_train_val.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Script for splitting a dataset hdf5 file into training and validation trajectories.
3
+
4
+ Args:
5
+ dataset (str): path to hdf5 dataset
6
+
7
+ filter_key (str): if provided, split the subset of trajectories
8
+ in the file that correspond to this filter key into a training
9
+ and validation set of trajectories, instead of splitting the
10
+ full set of trajectories
11
+
12
+ ratio (float): validation ratio, in (0, 1). Defaults to 0.1, which is 10%.
13
+
14
+ Example usage:
15
+ python split_train_val.py --dataset /path/to/demo.hdf5 --ratio 0.1
16
+ """
17
+
18
+ import argparse
19
+ import h5py
20
+ import numpy as np
21
+
22
+ from robomimic.utils.file_utils import create_hdf5_filter_key
23
+
24
+
25
+ def split_train_val_from_hdf5(hdf5_path, val_ratio=0.1, filter_key=None):
26
+ """
27
+ Splits data into training set and validation set from HDF5 file.
28
+
29
+ Args:
30
+ hdf5_path (str): path to the hdf5 file
31
+ to load the transitions from
32
+
33
+ val_ratio (float): ratio of validation demonstrations to all demonstrations
34
+
35
+ filter_key (str): if provided, split the subset of demonstration keys stored
36
+ under mask/@filter_key instead of the full set of demonstrations
37
+ """
38
+
39
+ # retrieve number of demos
40
+ f = h5py.File(hdf5_path, "r")
41
+ if filter_key is not None:
42
+ print("using filter key: {}".format(filter_key))
43
+ demos = sorted([elem.decode("utf-8") for elem in np.array(f["mask/{}".format(filter_key)])])
44
+ else:
45
+ demos = sorted(list(f["data"].keys()))
46
+ num_demos = len(demos)
47
+ f.close()
48
+
49
+ # get random split
50
+ num_demos = len(demos)
51
+ num_val = int(val_ratio * num_demos)
52
+ mask = np.zeros(num_demos)
53
+ mask[:num_val] = 1.
54
+ np.random.shuffle(mask)
55
+ mask = mask.astype(int)
56
+ train_inds = (1 - mask).nonzero()[0]
57
+ valid_inds = mask.nonzero()[0]
58
+ train_keys = [demos[i] for i in train_inds]
59
+ valid_keys = [demos[i] for i in valid_inds]
60
+ print("{} validation demonstrations out of {} total demonstrations.".format(num_val, num_demos))
61
+
62
+ # pass mask to generate split
63
+ name_1 = "train"
64
+ name_2 = "valid"
65
+ if filter_key is not None:
66
+ name_1 = "{}_{}".format(filter_key, name_1)
67
+ name_2 = "{}_{}".format(filter_key, name_2)
68
+
69
+ train_lengths = create_hdf5_filter_key(hdf5_path=hdf5_path, demo_keys=train_keys, key_name=name_1)
70
+ valid_lengths = create_hdf5_filter_key(hdf5_path=hdf5_path, demo_keys=valid_keys, key_name=name_2)
71
+
72
+ print("Total number of train samples: {}".format(np.sum(train_lengths)))
73
+ print("Average number of train samples {}".format(np.mean(train_lengths)))
74
+
75
+ print("Total number of valid samples: {}".format(np.sum(valid_lengths)))
76
+ print("Average number of valid samples {}".format(np.mean(valid_lengths)))
77
+
78
+
79
+ if __name__ == "__main__":
80
+ parser = argparse.ArgumentParser()
81
+ parser.add_argument(
82
+ "--dataset",
83
+ type=str,
84
+ help="path to hdf5 dataset",
85
+ )
86
+ parser.add_argument(
87
+ "--filter_key",
88
+ type=str,
89
+ default=None,
90
+ help="if provided, split the subset of trajectories in the file that correspond to\
91
+ this filter key into a training and validation set of trajectories, instead of\
92
+ splitting the full set of trajectories",
93
+ )
94
+ parser.add_argument(
95
+ "--ratio",
96
+ type=float,
97
+ default=0.1,
98
+ help="validation ratio, in (0, 1)"
99
+ )
100
+ args = parser.parse_args()
101
+
102
+ # seed to make sure results are consistent
103
+ np.random.seed(0)
104
+
105
+ split_train_val_from_hdf5(args.dataset, val_ratio=args.ratio, filter_key=args.filter_key)
aloha-devel/robomimic/scripts/train.py ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ The main entry point for training policies.
3
+
4
+ Args:
5
+ config (str): path to a config json that will be used to override the default settings.
6
+ If omitted, default settings are used. This is the preferred way to run experiments.
7
+
8
+ algo (str): name of the algorithm to run. Only needs to be provided if @config is not
9
+ provided.
10
+
11
+ name (str): if provided, override the experiment name defined in the config
12
+
13
+ dataset (str): if provided, override the dataset path defined in the config
14
+
15
+ debug (bool): set this flag to run a quick training run for debugging purposes
16
+ """
17
+
18
+ import argparse
19
+ import json
20
+ import numpy as np
21
+ import time
22
+ import os
23
+ import shutil
24
+ import psutil
25
+ import sys
26
+ import socket
27
+ import traceback
28
+
29
+ from collections import OrderedDict
30
+
31
+ import torch
32
+ from torch.utils.data import DataLoader
33
+
34
+ import robomimic
35
+ import robomimic.utils.train_utils as TrainUtils
36
+ import robomimic.utils.torch_utils as TorchUtils
37
+ import robomimic.utils.obs_utils as ObsUtils
38
+ import robomimic.utils.env_utils as EnvUtils
39
+ import robomimic.utils.file_utils as FileUtils
40
+ from robomimic.config import config_factory
41
+ from robomimic.algo import algo_factory, RolloutPolicy
42
+ from robomimic.utils.log_utils import PrintLogger, DataLogger, flush_warnings
43
+
44
+
45
+ def train(config, device):
46
+ """
47
+ Train a model using the algorithm.
48
+ """
49
+
50
+ # first set seeds
51
+ np.random.seed(config.train.seed)
52
+ torch.manual_seed(config.train.seed)
53
+
54
+ # set num workers
55
+ torch.set_num_threads(1)
56
+
57
+ print("\n============= New Training Run with Config =============")
58
+ print(config)
59
+ print("")
60
+ log_dir, ckpt_dir, video_dir, vis_dir = TrainUtils.get_exp_dir(config)
61
+
62
+ if config.experiment.logging.terminal_output_to_txt:
63
+ # log stdout and stderr to a text file
64
+ logger = PrintLogger(os.path.join(log_dir, 'log.txt'))
65
+ sys.stdout = logger
66
+ sys.stderr = logger
67
+
68
+ # read config to set up metadata for observation modalities (e.g. detecting rgb observations)
69
+ ObsUtils.initialize_obs_utils_with_config(config)
70
+
71
+ # extract the metadata and shape metadata across all datasets
72
+ env_meta_list = []
73
+ shape_meta_list = []
74
+ for dataset_cfg in config.train.data:
75
+ dataset_path = os.path.expanduser(dataset_cfg["path"])
76
+ ds_format = config.train.data_format
77
+ if not os.path.exists(dataset_path):
78
+ raise Exception("Dataset at provided path {} not found!".format(dataset_path))
79
+
80
+ # load basic metadata from training file
81
+ print("\n============= Loaded Environment Metadata =============")
82
+ env_meta = FileUtils.get_env_metadata_from_dataset(dataset_path=dataset_path, ds_format=ds_format)
83
+
84
+ # populate language instruction for env in env_meta
85
+ env_meta["lang"] = dataset_cfg.get("lang", "dummy")
86
+
87
+ # update env meta if applicable
88
+ from robomimic.utils.script_utils import deep_update
89
+ deep_update(env_meta, config.experiment.env_meta_update_dict)
90
+ env_meta_list.append(env_meta)
91
+
92
+ shape_meta = FileUtils.get_shape_metadata_from_dataset(
93
+ dataset_path=dataset_path,
94
+ action_keys=config.train.action_keys,
95
+ all_obs_keys=config.all_obs_keys,
96
+ ds_format=ds_format,
97
+ verbose=True
98
+ )
99
+ shape_meta_list.append(shape_meta)
100
+
101
+ if config.experiment.env is not None:
102
+ env_meta["env_name"] = config.experiment.env
103
+ print("=" * 30 + "\n" + "Replacing Env to {}\n".format(env_meta["env_name"]) + "=" * 30)
104
+
105
+ # create environment
106
+ envs = OrderedDict()
107
+ if config.experiment.rollout.enabled:
108
+ # create environments for validation runs
109
+ # env_names = [env_meta["env_name"]]
110
+
111
+ # # disable this feature for now
112
+ # if config.experiment.additional_envs is not None:
113
+ # raise NotImplementedError
114
+ # for name in config.experiment.additional_envs:
115
+ # env_names.append(name)
116
+
117
+ for (dataset_i, dataset_cfg) in enumerate(config.train.data):
118
+ do_eval = dataset_cfg.get("eval", True)
119
+ if do_eval is not True:
120
+ continue
121
+ env_meta = env_meta_list[dataset_i]
122
+ shape_meta = shape_meta_list[dataset_i]
123
+ env_name = env_meta["env_name"]
124
+
125
+ def create_env(env_i=0):
126
+ env_kwargs = dict(
127
+ env_meta=env_meta,
128
+ env_name=env_name,
129
+ render=False,
130
+ render_offscreen=config.experiment.render_video,
131
+ use_image_obs=shape_meta["use_images"],
132
+ # seed=config.train.seed * 1000 + env_i # TODO: add seeding across environments
133
+ )
134
+ env = EnvUtils.create_env_from_metadata(**env_kwargs)
135
+ # handle environment wrappers
136
+ env = EnvUtils.wrap_env_from_config(env, config=config) # apply environment warpper, if applicable
137
+
138
+ return env
139
+
140
+ if config.experiment.rollout.batched:
141
+ from tianshou.env import SubprocVectorEnv
142
+ env_fns = [lambda env_i=i: create_env(env_i) for i in range(config.experiment.rollout.num_batch_envs)]
143
+ env = SubprocVectorEnv(env_fns)
144
+ env_name = env.get_env_attr(key="name", id=0)[0]
145
+ else:
146
+ env = create_env()
147
+ env_name = env.name
148
+
149
+ envs[env_name] = env
150
+ print(env)
151
+
152
+ print("")
153
+
154
+ # setup for a new training run
155
+ data_logger = DataLogger(
156
+ log_dir,
157
+ config,
158
+ log_tb=config.experiment.logging.log_tb,
159
+ log_wandb=config.experiment.logging.log_wandb,
160
+ )
161
+ model = algo_factory(
162
+ algo_name=config.algo_name,
163
+ config=config,
164
+ obs_key_shapes=shape_meta_list[0]["all_shapes"],
165
+ ac_dim=shape_meta_list[0]["ac_dim"],
166
+ device=device,
167
+ )
168
+
169
+ # save the config as a json file
170
+ with open(os.path.join(log_dir, '..', 'config.json'), 'w') as outfile:
171
+ json.dump(config, outfile, indent=4)
172
+
173
+ # if checkpoint is specified, load in model weights
174
+ ckpt_path = config.experiment.ckpt_path
175
+ if ckpt_path is not None:
176
+ print("LOADING MODEL WEIGHTS FROM " + ckpt_path)
177
+ from robomimic.utils.file_utils import maybe_dict_from_checkpoint
178
+ ckpt_dict = maybe_dict_from_checkpoint(ckpt_path=ckpt_path)
179
+ model.deserialize(ckpt_dict["model"])
180
+
181
+ print("\n============= Model Summary =============")
182
+ print(model) # print model summary
183
+ print("")
184
+
185
+ # load training data
186
+ trainset, validset = TrainUtils.load_data_for_training(
187
+ config, obs_keys=shape_meta["all_obs_keys"])
188
+ train_sampler = trainset.get_dataset_sampler()
189
+ print("\n============= Training Dataset =============")
190
+ print(trainset)
191
+ print("")
192
+ if validset is not None:
193
+ print("\n============= Validation Dataset =============")
194
+ print(validset)
195
+ print("")
196
+
197
+ # maybe retreve statistics for normalizing observations
198
+ obs_normalization_stats = None
199
+ if config.train.hdf5_normalize_obs:
200
+ obs_normalization_stats = trainset.get_obs_normalization_stats()
201
+
202
+ # maybe retreve statistics for normalizing actions
203
+ action_normalization_stats = trainset.get_action_normalization_stats()
204
+
205
+ # initialize data loaders
206
+ train_loader = DataLoader(
207
+ dataset=trainset,
208
+ sampler=train_sampler,
209
+ batch_size=config.train.batch_size,
210
+ shuffle=(train_sampler is None),
211
+ num_workers=config.train.num_data_workers,
212
+ drop_last=True
213
+ )
214
+
215
+ if config.experiment.validate:
216
+ # cap num workers for validation dataset at 1
217
+ num_workers = min(config.train.num_data_workers, 1)
218
+ valid_sampler = validset.get_dataset_sampler()
219
+ valid_loader = DataLoader(
220
+ dataset=validset,
221
+ sampler=valid_sampler,
222
+ batch_size=config.train.batch_size,
223
+ shuffle=(valid_sampler is None),
224
+ num_workers=num_workers,
225
+ drop_last=True
226
+ )
227
+ else:
228
+ valid_loader = None
229
+
230
+ # print all warnings before training begins
231
+ print("*" * 50)
232
+ print("Warnings generated by robomimic have been duplicated here (from above) for convenience. Please check them carefully.")
233
+ flush_warnings()
234
+ print("*" * 50)
235
+ print("")
236
+
237
+ # main training loop
238
+ best_valid_loss = None
239
+ best_return = {k: -np.inf for k in envs} if config.experiment.rollout.enabled else None
240
+ best_success_rate = {k: -1. for k in envs} if config.experiment.rollout.enabled else None
241
+ last_ckpt_time = time.time()
242
+
243
+ # number of learning steps per epoch (defaults to a full dataset pass)
244
+ train_num_steps = config.experiment.epoch_every_n_steps
245
+ valid_num_steps = config.experiment.validation_epoch_every_n_steps
246
+
247
+ for epoch in range(1, config.train.num_epochs + 1): # epoch numbers start at 1
248
+ step_log = TrainUtils.run_epoch(
249
+ model=model,
250
+ data_loader=train_loader,
251
+ epoch=epoch,
252
+ num_steps=train_num_steps,
253
+ obs_normalization_stats=obs_normalization_stats,
254
+ )
255
+ model.on_epoch_end(epoch)
256
+
257
+ # setup checkpoint path
258
+ epoch_ckpt_name = "model_epoch_{}".format(epoch)
259
+
260
+ # check for recurring checkpoint saving conditions
261
+ should_save_ckpt = False
262
+ if config.experiment.save.enabled:
263
+ time_check = (config.experiment.save.every_n_seconds is not None) and \
264
+ (time.time() - last_ckpt_time > config.experiment.save.every_n_seconds)
265
+ epoch_check = (config.experiment.save.every_n_epochs is not None) and \
266
+ (epoch > 0) and (epoch % config.experiment.save.every_n_epochs == 0)
267
+ epoch_list_check = (epoch in config.experiment.save.epochs)
268
+ should_save_ckpt = (time_check or epoch_check or epoch_list_check)
269
+ ckpt_reason = None
270
+ if should_save_ckpt:
271
+ last_ckpt_time = time.time()
272
+ ckpt_reason = "time"
273
+
274
+ print("Train Epoch {}".format(epoch))
275
+ print(json.dumps(step_log, sort_keys=True, indent=4))
276
+ for k, v in step_log.items():
277
+ if k.startswith("Time_"):
278
+ data_logger.record("Timing_Stats/Train_{}".format(k[5:]), v, epoch)
279
+ else:
280
+ data_logger.record("Train/{}".format(k), v, epoch)
281
+
282
+ # Evaluate the model on validation set
283
+ if config.experiment.validate:
284
+ with torch.no_grad():
285
+ step_log = TrainUtils.run_epoch(model=model, data_loader=valid_loader, epoch=epoch, validate=True, num_steps=valid_num_steps)
286
+ for k, v in step_log.items():
287
+ if k.startswith("Time_"):
288
+ data_logger.record("Timing_Stats/Valid_{}".format(k[5:]), v, epoch)
289
+ else:
290
+ data_logger.record("Valid/{}".format(k), v, epoch)
291
+
292
+ print("Validation Epoch {}".format(epoch))
293
+ print(json.dumps(step_log, sort_keys=True, indent=4))
294
+
295
+ # save checkpoint if achieve new best validation loss
296
+ valid_check = "Loss" in step_log
297
+ if valid_check and (best_valid_loss is None or (step_log["Loss"] <= best_valid_loss)):
298
+ best_valid_loss = step_log["Loss"]
299
+ if config.experiment.save.enabled and config.experiment.save.on_best_validation:
300
+ epoch_ckpt_name += "_best_validation_{}".format(best_valid_loss)
301
+ should_save_ckpt = True
302
+ ckpt_reason = "valid" if ckpt_reason is None else ckpt_reason
303
+
304
+ # Evaluate the model by by running rollouts
305
+
306
+ # do rollouts at fixed rate or if it's time to save a new ckpt
307
+ video_paths = None
308
+ rollout_check = (epoch % config.experiment.rollout.rate == 0) or (should_save_ckpt and ckpt_reason == "time")
309
+ if config.experiment.rollout.enabled and (epoch > config.experiment.rollout.warmstart) and rollout_check:
310
+ # wrap model as a RolloutPolicy to prepare for rollouts
311
+ rollout_model = RolloutPolicy(
312
+ model,
313
+ obs_normalization_stats=obs_normalization_stats,
314
+ action_normalization_stats=action_normalization_stats,
315
+ )
316
+
317
+ num_episodes = config.experiment.rollout.n
318
+ all_rollout_logs, video_paths = TrainUtils.rollout_with_stats(
319
+ policy=rollout_model,
320
+ envs=envs,
321
+ horizon=config.experiment.rollout.horizon,
322
+ use_goals=config.use_goals,
323
+ num_episodes=num_episodes,
324
+ render=False,
325
+ video_dir=video_dir if config.experiment.render_video else None,
326
+ epoch=epoch,
327
+ video_skip=config.experiment.get("video_skip", 5),
328
+ terminate_on_success=config.experiment.rollout.terminate_on_success,
329
+ )
330
+
331
+ # summarize results from rollouts to tensorboard and terminal
332
+ for env_name in all_rollout_logs:
333
+ rollout_logs = all_rollout_logs[env_name]
334
+ for k, v in rollout_logs.items():
335
+ if k.startswith("Time_"):
336
+ data_logger.record("Timing_Stats/Rollout_{}_{}".format(env_name, k[5:]), v, epoch)
337
+ else:
338
+ data_logger.record("Rollout/{}/{}".format(k, env_name), v, epoch, log_stats=True)
339
+
340
+ print("\nEpoch {} Rollouts took {}s (avg) with results:".format(epoch, rollout_logs["time"]))
341
+ print('Env: {}'.format(env_name))
342
+ print(json.dumps(rollout_logs, sort_keys=True, indent=4))
343
+
344
+ # checkpoint and video saving logic
345
+ updated_stats = TrainUtils.should_save_from_rollout_logs(
346
+ all_rollout_logs=all_rollout_logs,
347
+ best_return=best_return,
348
+ best_success_rate=best_success_rate,
349
+ epoch_ckpt_name=epoch_ckpt_name,
350
+ save_on_best_rollout_return=config.experiment.save.on_best_rollout_return,
351
+ save_on_best_rollout_success_rate=config.experiment.save.on_best_rollout_success_rate,
352
+ )
353
+ best_return = updated_stats["best_return"]
354
+ best_success_rate = updated_stats["best_success_rate"]
355
+ epoch_ckpt_name = updated_stats["epoch_ckpt_name"]
356
+ should_save_ckpt = (config.experiment.save.enabled and updated_stats["should_save_ckpt"]) or should_save_ckpt
357
+ if updated_stats["ckpt_reason"] is not None:
358
+ ckpt_reason = updated_stats["ckpt_reason"]
359
+
360
+ # check if we need to save model MSE
361
+ should_save_mse = False
362
+ if config.experiment.mse.enabled:
363
+ if config.experiment.mse.every_n_epochs is not None and epoch % config.experiment.mse.every_n_epochs == 0:
364
+ should_save_mse = True
365
+ if config.experiment.mse.on_save_ckpt and should_save_ckpt:
366
+ should_save_mse = True
367
+ if should_save_mse:
368
+ print("Computing MSE ...")
369
+ if config.experiment.mse.visualize:
370
+ save_vis_dir = os.path.join(vis_dir, epoch_ckpt_name)
371
+ else:
372
+ save_vis_dir = None
373
+ mse_log, vis_log = model.compute_mse_visualize(
374
+ trainset,
375
+ validset,
376
+ num_samples=config.experiment.mse.num_samples,
377
+ savedir=save_vis_dir,
378
+ )
379
+ for k, v in mse_log.items():
380
+ data_logger.record("{}".format(k), v, epoch)
381
+
382
+ for k, v in vis_log.items():
383
+ data_logger.record("{}".format(k), v, epoch, data_type='image')
384
+
385
+
386
+ print("MSE Log Epoch {}".format(epoch))
387
+ print(json.dumps(mse_log, sort_keys=True, indent=4))
388
+
389
+ # # Only keep saved videos if the ckpt should be saved (but not because of validation score)
390
+ # should_save_video = (should_save_ckpt and (ckpt_reason != "valid")) or config.experiment.keep_all_videos
391
+ # if video_paths is not None and not should_save_video:
392
+ # for env_name in video_paths:
393
+ # os.remove(video_paths[env_name])
394
+
395
+ # Save model checkpoints based on conditions (success rate, validation loss, etc)
396
+ if should_save_ckpt:
397
+ TrainUtils.save_model(
398
+ model=model,
399
+ config=config,
400
+ env_meta=env_meta,
401
+ shape_meta=shape_meta,
402
+ ckpt_path=os.path.join(ckpt_dir, epoch_ckpt_name + ".pth"),
403
+ obs_normalization_stats=obs_normalization_stats,
404
+ action_normalization_stats=action_normalization_stats,
405
+ )
406
+
407
+ # Finally, log memory usage in MB
408
+ process = psutil.Process(os.getpid())
409
+ mem_usage = int(process.memory_info().rss / 1000000)
410
+ data_logger.record("System/RAM Usage (MB)", mem_usage, epoch)
411
+ print("\nEpoch {} Memory Usage: {} MB\n".format(epoch, mem_usage))
412
+
413
+ # terminate logging
414
+ data_logger.close()
415
+
416
+
417
+ def main(args):
418
+
419
+ if args.config is not None:
420
+ ext_cfg = json.load(open(args.config, 'r'))
421
+ config = config_factory(ext_cfg["algo_name"])
422
+ # update config with external json - this will throw errors if
423
+ # the external config has keys not present in the base algo config
424
+ with config.values_unlocked():
425
+ config.update(ext_cfg)
426
+ else:
427
+ config = config_factory(args.algo)
428
+
429
+ if args.dataset is not None:
430
+ config.train.data = args.dataset
431
+
432
+ if args.name is not None:
433
+ config.experiment.name = args.name
434
+
435
+ # get torch device
436
+ device = TorchUtils.get_torch_device(try_to_use_cuda=config.train.cuda)
437
+
438
+ # maybe modify config for debugging purposes
439
+ if args.debug:
440
+ # shrink length of training to test whether this run is likely to crash
441
+ config.unlock()
442
+ config.lock_keys()
443
+
444
+ # train and validate (if enabled) for 3 gradient steps, for 2 epochs
445
+ config.experiment.epoch_every_n_steps = 3
446
+ config.experiment.validation_epoch_every_n_steps = 3
447
+ config.train.num_epochs = 2
448
+
449
+ # if rollouts are enabled, try 2 rollouts at end of each epoch, with 10 environment steps
450
+ config.experiment.rollout.rate = 1
451
+ config.experiment.rollout.n = 2
452
+ config.experiment.rollout.horizon = 10
453
+
454
+ # send output to a temporary directory
455
+ config.train.output_dir = "/tmp/tmp_trained_models"
456
+
457
+ # lock config to prevent further modifications and ensure missing keys raise errors
458
+ config.lock()
459
+
460
+ # catch error during training and print it
461
+ res_str = "finished run successfully!"
462
+ try:
463
+ train(config, device=device)
464
+ except Exception as e:
465
+ res_str = "run failed with error:\n{}\n\n{}".format(e, traceback.format_exc())
466
+ print(res_str)
467
+
468
+
469
+ if __name__ == "__main__":
470
+ parser = argparse.ArgumentParser()
471
+
472
+ # External config file that overwrites default config
473
+ parser.add_argument(
474
+ "--config",
475
+ type=str,
476
+ default=None,
477
+ help="(optional) path to a config json that will be used to override the default settings. \
478
+ If omitted, default settings are used. This is the preferred way to run experiments.",
479
+ )
480
+
481
+ # Algorithm Name
482
+ parser.add_argument(
483
+ "--algo",
484
+ type=str,
485
+ help="(optional) name of algorithm to run. Only needs to be provided if --config is not provided",
486
+ )
487
+
488
+ # Experiment Name (for tensorboard, saving models, etc.)
489
+ parser.add_argument(
490
+ "--name",
491
+ type=str,
492
+ default=None,
493
+ help="(optional) if provided, override the experiment name defined in the config",
494
+ )
495
+
496
+ # Dataset path, to override the one in the config
497
+ parser.add_argument(
498
+ "--dataset",
499
+ type=str,
500
+ default=None,
501
+ help="(optional) if provided, override the dataset path defined in the config",
502
+ )
503
+
504
+ # debug mode
505
+ parser.add_argument(
506
+ "--debug",
507
+ action='store_true',
508
+ help="set this flag to run a quick training run for debugging purposes"
509
+ )
510
+
511
+ args = parser.parse_args()
512
+ main(args)
camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/base_realsense_node.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5541553727cbf098869ea2e94b1d1296cb4a23f3258499d0318e27bae3858a8f
3
+ size 1491304
camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/realsense_node_factory.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aa2a7c905e752af30b16e13412c4114c0b73c4848379d92bf532a79e3dc7f299
3
+ size 803520
camera_ws/build/realsense-ros/realsense2_camera/CMakeFiles/realsense2_camera.dir/src/t265_realsense_node.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:189eb3a5400ed16e4bcab1e831922471e8fc927cdc0235594120a8c3e2be9a35
3
+ size 461856
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/d2c_viewer.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b2aa26446f153e3aad326a6f330b067fbb42b34e88de3dc8609aad0de1610f1f
3
+ size 680928
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_info.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c188bd95821da73d09da0921b14b9e18a510f296500023b092ac22f42cf865e2
3
+ size 237456
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_node.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:583cd3770af8e1212e18b2e660a460b508c6537760c8a439a7630a6652c7ba7c
3
+ size 1317640
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ob_camera_node_factory.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b7d398107f96df3449e2551b80e7f07b646935f64a5540be3ad73d1bf80cc928
3
+ size 266032
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/point_cloud_proc/point_cloud_xyz.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:69cbd4b7187bd4e4363f70c0d6d412a2d08e2cb75752b7bdbf9d6a655a01e4d2
3
+ size 258720
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/point_cloud_proc/point_cloud_xyzrgb.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:aca6aa937515cc81b5f6a8ea1770c64a00a313df60efbddce8fa68e0b31a2ab5
3
+ size 938608
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/ros_service.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ead048ee4c26f280065dac38206a5a910a6e2f8c409bd04b024d45f18386ce73
3
+ size 975208
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/utils.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:79af685dc753110ab6acf4c2f91b1de9d6d22b07ac08d75f76d0e12b8fc2cdef
3
+ size 120352
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera.dir/src/uvc_camera_driver.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e1be3bf2cd7b7243b156945d353a7f4b87b9c804654d0552c6c9183558d3dc73
3
+ size 586224
camera_ws/build/ros_astra_camera/CMakeFiles/astra_camera_node.dir/src/main.cpp.o ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cab5e1b87593816f7c47df5a3ade6f8e61bd8591e770939ae65f3fbe84845685
3
+ size 163160
camera_ws/devel/lib/astra_camera/astra_camera_node ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9853d91bcfa0dd299e1e680ce58b6227154200d486514a8081e2b45c0d7dd1f4
3
+ size 115152
camera_ws/devel/lib/libastra_camera.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ba880c2c2a063ee0746bcb0f604b0cb7cc69e2cb0ca631fe01687ce38d19b119
3
+ size 2427240